Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / views.py @ 17ad5d37

History | View | Annotate | Download (47.9 kB)

1 aba1e498 Antony Chazapis
# Copyright 2011-2012 GRNET S.A. All rights reserved.
2 176023aa Kostas Papadimitriou
#
3 64cd4730 Antony Chazapis
# Redistribution and use in source and binary forms, with or
4 64cd4730 Antony Chazapis
# without modification, are permitted provided that the following
5 64cd4730 Antony Chazapis
# conditions are met:
6 176023aa Kostas Papadimitriou
#
7 64cd4730 Antony Chazapis
#   1. Redistributions of source code must retain the above
8 64cd4730 Antony Chazapis
#      copyright notice, this list of conditions and the following
9 64cd4730 Antony Chazapis
#      disclaimer.
10 176023aa Kostas Papadimitriou
#
11 64cd4730 Antony Chazapis
#   2. Redistributions in binary form must reproduce the above
12 64cd4730 Antony Chazapis
#      copyright notice, this list of conditions and the following
13 64cd4730 Antony Chazapis
#      disclaimer in the documentation and/or other materials
14 64cd4730 Antony Chazapis
#      provided with the distribution.
15 176023aa Kostas Papadimitriou
#
16 64cd4730 Antony Chazapis
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 64cd4730 Antony Chazapis
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 64cd4730 Antony Chazapis
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 64cd4730 Antony Chazapis
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 64cd4730 Antony Chazapis
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 64cd4730 Antony Chazapis
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 64cd4730 Antony Chazapis
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 64cd4730 Antony Chazapis
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 64cd4730 Antony Chazapis
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 64cd4730 Antony Chazapis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 64cd4730 Antony Chazapis
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 64cd4730 Antony Chazapis
# POSSIBILITY OF SUCH DAMAGE.
28 176023aa Kostas Papadimitriou
#
29 64cd4730 Antony Chazapis
# The views and conclusions contained in the software and
30 64cd4730 Antony Chazapis
# documentation are those of the authors and should not be
31 64cd4730 Antony Chazapis
# interpreted as representing official policies, either expressed
32 64cd4730 Antony Chazapis
# or implied, of GRNET S.A.
33 64cd4730 Antony Chazapis
34 64cd4730 Antony Chazapis
import logging
35 6e029beb Sofia Papagiannaki
import calendar
36 9a06d96f Olga Brani
import inflect
37 9a06d96f Olga Brani
38 9a06d96f Olga Brani
engine = inflect.engine()
39 64cd4730 Antony Chazapis
40 0905ccd2 Sofia Papagiannaki
from urllib import quote
41 63ecdd20 Sofia Papagiannaki
from functools import wraps
42 c0b26605 Sofia Papagiannaki
from datetime import datetime
43 64cd4730 Antony Chazapis
44 a5cef8d0 Kostas Papadimitriou
from django_tables2 import RequestConfig
45 a5cef8d0 Kostas Papadimitriou
46 c630fee6 Kostas Papadimitriou
from django.shortcuts import get_object_or_404
47 890b0eaf Sofia Papagiannaki
from django.contrib import messages
48 01ac12d5 Sofia Papagiannaki
from django.contrib.auth.decorators import login_required
49 01ac12d5 Sofia Papagiannaki
from django.core.urlresolvers import reverse
50 01ac12d5 Sofia Papagiannaki
from django.db import transaction
51 01ac12d5 Sofia Papagiannaki
from django.db.utils import IntegrityError
52 73fbaec4 Sofia Papagiannaki
from django.http import (
53 73fbaec4 Sofia Papagiannaki
    HttpResponse, HttpResponseBadRequest,
54 73fbaec4 Sofia Papagiannaki
    HttpResponseForbidden, HttpResponseRedirect,
55 73fbaec4 Sofia Papagiannaki
    HttpResponseBadRequest, Http404)
56 01ac12d5 Sofia Papagiannaki
from django.shortcuts import redirect
57 661c4479 Sofia Papagiannaki
from django.template import RequestContext, loader as template_loader
58 01ac12d5 Sofia Papagiannaki
from django.utils.http import urlencode
59 564a2292 Kostas Papadimitriou
from django.utils.safestring import mark_safe
60 01ac12d5 Sofia Papagiannaki
from django.utils.translation import ugettext as _
61 e1a80257 Sofia Papagiannaki
from django.views.generic.create_update import (
62 4e748491 Sofia Papagiannaki
    apply_extra_context, lookup_object, delete_object, get_model_and_form_class)
63 f3342849 Sofia Papagiannaki
from django.views.generic.list_detail import object_list, object_detail
64 661c4479 Sofia Papagiannaki
from django.core.xheaders import populate_xheaders
65 792c2f3b Olga Brani
from django.core.exceptions import ValidationError, PermissionDenied
66 c0b26605 Sofia Papagiannaki
from django.template.loader import render_to_string
67 9a06d96f Olga Brani
from django.views.decorators.http import require_http_methods
68 29b0ec5a Sofia Papagiannaki
from django.db.models import Q
69 bfe23b13 Sofia Papagiannaki
from django.core.exceptions import PermissionDenied
70 96b44c04 Sofia Papagiannaki
from django.utils import simplejson as json
71 c0b26605 Sofia Papagiannaki
72 c630fee6 Kostas Papadimitriou
import astakos.im.messages as astakos_messages
73 c630fee6 Kostas Papadimitriou
74 29b0ec5a Sofia Papagiannaki
from astakos.im.activation_backends import get_backend, SimpleBackend
75 5550bcfb Kostas Papadimitriou
from astakos.im import tables
76 e1a80257 Sofia Papagiannaki
from astakos.im.models import (
77 73fbaec4 Sofia Papagiannaki
    AstakosUser, ApprovalTerms,
78 fcc1e93f Sofia Papagiannaki
    EmailChange, RESOURCE_SEPARATOR,
79 fcc1e93f Sofia Papagiannaki
    AstakosUserAuthProvider, PendingThirdPartyUser,
80 73fbaec4 Sofia Papagiannaki
    ProjectApplication, ProjectMembership, Project)
81 73fbaec4 Sofia Papagiannaki
from astakos.im.util import (
82 73fbaec4 Sofia Papagiannaki
    get_context, prepare_response, get_query, restrict_next)
83 e1a80257 Sofia Papagiannaki
from astakos.im.forms import (
84 f7400729 Kostas Papadimitriou
    LoginForm, InvitationForm,
85 e1a80257 Sofia Papagiannaki
    FeedbackForm, SignApprovalTermsForm,
86 e1a80257 Sofia Papagiannaki
    EmailChangeForm,
87 bfe23b13 Sofia Papagiannaki
    ProjectApplicationForm, ProjectSortForm,
88 73fbaec4 Sofia Papagiannaki
    AddProjectMembersForm, ProjectSearchForm,
89 73fbaec4 Sofia Papagiannaki
    ProjectMembersSortForm)
90 f7400729 Kostas Papadimitriou
from astakos.im.forms import ExtendedProfileForm as ProfileForm
91 f3342849 Sofia Papagiannaki
from astakos.im.functions import (
92 f3342849 Sofia Papagiannaki
    send_feedback, SendMailError,
93 f3342849 Sofia Papagiannaki
    logout as auth_logout,
94 f3342849 Sofia Papagiannaki
    activate as activate_func,
95 73fbaec4 Sofia Papagiannaki
    invite,
96 f3342849 Sofia Papagiannaki
    send_activation as send_activation_func,
97 73fbaec4 Sofia Papagiannaki
    SendNotificationError,
98 73fbaec4 Sofia Papagiannaki
    accept_membership, reject_membership, remove_membership,
99 7dd3047d Sofia Papagiannaki
    leave_project, join_project, enroll_member)
100 f3342849 Sofia Papagiannaki
from astakos.im.settings import (
101 f3342849 Sofia Papagiannaki
    COOKIE_DOMAIN, LOGOUT_NEXT,
102 f3342849 Sofia Papagiannaki
    LOGGING_LEVEL, PAGINATE_BY,
103 a9c7ff8a Sofia Papagiannaki
    RESOURCES_PRESENTATION_DATA, PAGINATE_BY_ALL,
104 a9c7ff8a Sofia Papagiannaki
    MODERATION_ENABLED)
105 1ebea3d3 Kostas Papadimitriou
from astakos.im.api import get_services_dict
106 48421603 Kostas Papadimitriou
from astakos.im import settings as astakos_settings
107 820b18e0 Sofia Papagiannaki
from astakos.im.api.callpoint import AstakosCallpoint
108 792c2f3b Olga Brani
from astakos.im import auth_providers
109 ae497612 Olga Brani
110 e015e9e6 Sofia Papagiannaki
logger = logging.getLogger(__name__)
111 e015e9e6 Sofia Papagiannaki
112 820b18e0 Sofia Papagiannaki
callpoint = AstakosCallpoint()
113 9a06d96f Olga Brani
114 b2ffa772 Sofia Papagiannaki
def render_response(template, tab=None, status=200, context_instance=None, **kwargs):
115 890b0eaf Sofia Papagiannaki
    """
116 890b0eaf Sofia Papagiannaki
    Calls ``django.template.loader.render_to_string`` with an additional ``tab``
117 890b0eaf Sofia Papagiannaki
    keyword argument and returns an ``django.http.HttpResponse`` with the
118 890b0eaf Sofia Papagiannaki
    specified ``status``.
119 890b0eaf Sofia Papagiannaki
    """
120 64cd4730 Antony Chazapis
    if tab is None:
121 881c856c Sofia Papagiannaki
        tab = template.partition('_')[0].partition('.html')[0]
122 64cd4730 Antony Chazapis
    kwargs.setdefault('tab', tab)
123 661c4479 Sofia Papagiannaki
    html = template_loader.render_to_string(
124 5ce3ce4f Sofia Papagiannaki
        template, kwargs, context_instance=context_instance)
125 c301698f Sofia Papagiannaki
    response = HttpResponse(html, status=status)
126 c301698f Sofia Papagiannaki
    return response
127 64cd4730 Antony Chazapis
128 792c2f3b Olga Brani
def requires_auth_provider(provider_id, **perms):
129 792c2f3b Olga Brani
    """
130 792c2f3b Olga Brani
    """
131 792c2f3b Olga Brani
    def decorator(func, *args, **kwargs):
132 792c2f3b Olga Brani
        @wraps(func)
133 792c2f3b Olga Brani
        def wrapper(request, *args, **kwargs):
134 792c2f3b Olga Brani
            provider = auth_providers.get_provider(provider_id)
135 792c2f3b Olga Brani
136 792c2f3b Olga Brani
            if not provider or not provider.is_active():
137 792c2f3b Olga Brani
                raise PermissionDenied
138 792c2f3b Olga Brani
139 792c2f3b Olga Brani
            if provider:
140 792c2f3b Olga Brani
                for pkey, value in perms.iteritems():
141 792c2f3b Olga Brani
                    attr = 'is_available_for_%s' % pkey.lower()
142 792c2f3b Olga Brani
                    if getattr(provider, attr)() != value:
143 279d6e51 Olga Brani
                        #TODO: add session message
144 c630fee6 Kostas Papadimitriou
                        return HttpResponseRedirect(reverse('login'))
145 792c2f3b Olga Brani
            return func(request, *args)
146 792c2f3b Olga Brani
        return wrapper
147 792c2f3b Olga Brani
    return decorator
148 792c2f3b Olga Brani
149 63ecdd20 Sofia Papagiannaki
150 63ecdd20 Sofia Papagiannaki
def requires_anonymous(func):
151 63ecdd20 Sofia Papagiannaki
    """
152 270dd48d Sofia Papagiannaki
    Decorator checkes whether the request.user is not Anonymous and in that case
153 7482228b Sofia Papagiannaki
    redirects to `logout`.
154 63ecdd20 Sofia Papagiannaki
    """
155 63ecdd20 Sofia Papagiannaki
    @wraps(func)
156 63ecdd20 Sofia Papagiannaki
    def wrapper(request, *args):
157 63ecdd20 Sofia Papagiannaki
        if not request.user.is_anonymous():
158 63ecdd20 Sofia Papagiannaki
            next = urlencode({'next': request.build_absolute_uri()})
159 270dd48d Sofia Papagiannaki
            logout_uri = reverse(logout) + '?' + next
160 270dd48d Sofia Papagiannaki
            return HttpResponseRedirect(logout_uri)
161 63ecdd20 Sofia Papagiannaki
        return func(request, *args)
162 63ecdd20 Sofia Papagiannaki
    return wrapper
163 63ecdd20 Sofia Papagiannaki
164 5ce3ce4f Sofia Papagiannaki
165 270dd48d Sofia Papagiannaki
def signed_terms_required(func):
166 270dd48d Sofia Papagiannaki
    """
167 badcb2a9 Kostas Papadimitriou
    Decorator checks whether the request.user is Anonymous and in that case
168 270dd48d Sofia Papagiannaki
    redirects to `logout`.
169 270dd48d Sofia Papagiannaki
    """
170 270dd48d Sofia Papagiannaki
    @wraps(func)
171 270dd48d Sofia Papagiannaki
    def wrapper(request, *args, **kwargs):
172 fcf90160 Sofia Papagiannaki
        if request.user.is_authenticated() and not request.user.signed_terms:
173 270dd48d Sofia Papagiannaki
            params = urlencode({'next': request.build_absolute_uri(),
174 5ce3ce4f Sofia Papagiannaki
                                'show_form': ''})
175 270dd48d Sofia Papagiannaki
            terms_uri = reverse('latest_terms') + '?' + params
176 270dd48d Sofia Papagiannaki
            return HttpResponseRedirect(terms_uri)
177 270dd48d Sofia Papagiannaki
        return func(request, *args, **kwargs)
178 270dd48d Sofia Papagiannaki
    return wrapper
179 270dd48d Sofia Papagiannaki
180 5ce3ce4f Sofia Papagiannaki
181 badcb2a9 Kostas Papadimitriou
def required_auth_methods_assigned(only_warn=False):
182 badcb2a9 Kostas Papadimitriou
    """
183 badcb2a9 Kostas Papadimitriou
    Decorator that checks whether the request.user has all required auth providers
184 badcb2a9 Kostas Papadimitriou
    assigned.
185 badcb2a9 Kostas Papadimitriou
    """
186 badcb2a9 Kostas Papadimitriou
    required_providers = auth_providers.REQUIRED_PROVIDERS.keys()
187 badcb2a9 Kostas Papadimitriou
188 badcb2a9 Kostas Papadimitriou
    def decorator(func):
189 badcb2a9 Kostas Papadimitriou
        if not required_providers:
190 badcb2a9 Kostas Papadimitriou
            return func
191 badcb2a9 Kostas Papadimitriou
192 badcb2a9 Kostas Papadimitriou
        @wraps(func)
193 badcb2a9 Kostas Papadimitriou
        def wrapper(request, *args, **kwargs):
194 badcb2a9 Kostas Papadimitriou
            if request.user.is_authenticated():
195 badcb2a9 Kostas Papadimitriou
                for required in required_providers:
196 badcb2a9 Kostas Papadimitriou
                    if not request.user.has_auth_provider(required):
197 badcb2a9 Kostas Papadimitriou
                        provider = auth_providers.get_provider(required)
198 badcb2a9 Kostas Papadimitriou
                        if only_warn:
199 badcb2a9 Kostas Papadimitriou
                            messages.error(request,
200 badcb2a9 Kostas Papadimitriou
                                           _(astakos_messages.AUTH_PROVIDER_REQUIRED  % {
201 badcb2a9 Kostas Papadimitriou
                                               'provider': provider.get_title_display}))
202 badcb2a9 Kostas Papadimitriou
                        else:
203 badcb2a9 Kostas Papadimitriou
                            return HttpResponseRedirect(reverse('edit_profile'))
204 badcb2a9 Kostas Papadimitriou
            return func(request, *args, **kwargs)
205 badcb2a9 Kostas Papadimitriou
        return wrapper
206 badcb2a9 Kostas Papadimitriou
    return decorator
207 badcb2a9 Kostas Papadimitriou
208 badcb2a9 Kostas Papadimitriou
209 badcb2a9 Kostas Papadimitriou
def valid_astakos_user_required(func):
210 badcb2a9 Kostas Papadimitriou
    return signed_terms_required(required_auth_methods_assigned()(login_required(func)))
211 badcb2a9 Kostas Papadimitriou
212 badcb2a9 Kostas Papadimitriou
213 9a06d96f Olga Brani
@require_http_methods(["GET", "POST"])
214 270dd48d Sofia Papagiannaki
@signed_terms_required
215 1f3b4b39 Sofia Papagiannaki
def index(request, login_template_name='im/login.html', profile_template_name='im/profile.html', extra_context=None):
216 890b0eaf Sofia Papagiannaki
    """
217 dcf55476 Sofia Papagiannaki
    If there is logged on user renders the profile page otherwise renders login page.
218 176023aa Kostas Papadimitriou

219 890b0eaf Sofia Papagiannaki
    **Arguments**
220 176023aa Kostas Papadimitriou

221 dcf55476 Sofia Papagiannaki
    ``login_template_name``
222 dcf55476 Sofia Papagiannaki
        A custom login template to use. This is optional; if not specified,
223 1e685275 Sofia Papagiannaki
        this will default to ``im/login.html``.
224 176023aa Kostas Papadimitriou

225 dcf55476 Sofia Papagiannaki
    ``profile_template_name``
226 dcf55476 Sofia Papagiannaki
        A custom profile template to use. This is optional; if not specified,
227 1e685275 Sofia Papagiannaki
        this will default to ``im/profile.html``.
228 176023aa Kostas Papadimitriou

229 890b0eaf Sofia Papagiannaki
    ``extra_context``
230 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
231 176023aa Kostas Papadimitriou

232 890b0eaf Sofia Papagiannaki
    **Template:**
233 176023aa Kostas Papadimitriou

234 1e685275 Sofia Papagiannaki
    im/profile.html or im/login.html or ``template_name`` keyword argument.
235 176023aa Kostas Papadimitriou

236 890b0eaf Sofia Papagiannaki
    """
237 1f3b4b39 Sofia Papagiannaki
    extra_context = extra_context or {}
238 dcf55476 Sofia Papagiannaki
    template_name = login_template_name
239 dcf55476 Sofia Papagiannaki
    if request.user.is_authenticated():
240 f534fb96 Sofia Papagiannaki
        return HttpResponseRedirect(reverse('astakos.im.views.edit_profile'))
241 792c2f3b Olga Brani
242 f7cf5257 Kostas Papadimitriou
    third_party_token = request.GET.get('key', False)
243 f7cf5257 Kostas Papadimitriou
    if third_party_token:
244 f7cf5257 Kostas Papadimitriou
        messages.info(request, astakos_messages.AUTH_PROVIDER_LOGIN_TO_ADD)
245 f7cf5257 Kostas Papadimitriou
246 ef20ea07 Sofia Papagiannaki
    return render_response(
247 ef20ea07 Sofia Papagiannaki
        template_name,
248 ef20ea07 Sofia Papagiannaki
        login_form = LoginForm(request=request),
249 ef20ea07 Sofia Papagiannaki
        context_instance = get_context(request, extra_context)
250 ef20ea07 Sofia Papagiannaki
    )
251 5ce3ce4f Sofia Papagiannaki
252 64cd4730 Antony Chazapis
253 9a06d96f Olga Brani
@require_http_methods(["GET", "POST"])
254 badcb2a9 Kostas Papadimitriou
@valid_astakos_user_required
255 890b0eaf Sofia Papagiannaki
@transaction.commit_manually
256 aab4d540 Sofia Papagiannaki
def invite(request, template_name='im/invitations.html', extra_context=None):
257 890b0eaf Sofia Papagiannaki
    """
258 890b0eaf Sofia Papagiannaki
    Allows a user to invite somebody else.
259 176023aa Kostas Papadimitriou

260 890b0eaf Sofia Papagiannaki
    In case of GET request renders a form for providing the invitee information.
261 890b0eaf Sofia Papagiannaki
    In case of POST checks whether the user has not run out of invitations and then
262 890b0eaf Sofia Papagiannaki
    sends an invitation email to singup to the service.
263 176023aa Kostas Papadimitriou

264 890b0eaf Sofia Papagiannaki
    The view uses commit_manually decorator in order to ensure the number of the
265 890b0eaf Sofia Papagiannaki
    user invitations is going to be updated only if the email has been successfully sent.
266 176023aa Kostas Papadimitriou

267 2cbaacd5 Sofia Papagiannaki
    If the user isn't logged in, redirects to settings.LOGIN_URL.
268 176023aa Kostas Papadimitriou

269 890b0eaf Sofia Papagiannaki
    **Arguments**
270 176023aa Kostas Papadimitriou

271 890b0eaf Sofia Papagiannaki
    ``template_name``
272 890b0eaf Sofia Papagiannaki
        A custom template to use. This is optional; if not specified,
273 1e685275 Sofia Papagiannaki
        this will default to ``im/invitations.html``.
274 176023aa Kostas Papadimitriou

275 890b0eaf Sofia Papagiannaki
    ``extra_context``
276 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
277 176023aa Kostas Papadimitriou

278 890b0eaf Sofia Papagiannaki
    **Template:**
279 176023aa Kostas Papadimitriou

280 1e685275 Sofia Papagiannaki
    im/invitations.html or ``template_name`` keyword argument.
281 176023aa Kostas Papadimitriou

282 890b0eaf Sofia Papagiannaki
    **Settings:**
283 176023aa Kostas Papadimitriou

284 890b0eaf Sofia Papagiannaki
    The view expectes the following settings are defined:
285 176023aa Kostas Papadimitriou

286 890b0eaf Sofia Papagiannaki
    * LOGIN_URL: login uri
287 890b0eaf Sofia Papagiannaki
    """
288 1f3b4b39 Sofia Papagiannaki
    extra_context = extra_context or {}
289 64cd4730 Antony Chazapis
    status = None
290 64cd4730 Antony Chazapis
    message = None
291 8f5a3a06 Sofia Papagiannaki
    form = InvitationForm()
292 5ce3ce4f Sofia Papagiannaki
293 18ffbee1 Sofia Papagiannaki
    inviter = request.user
294 64cd4730 Antony Chazapis
    if request.method == 'POST':
295 8f5a3a06 Sofia Papagiannaki
        form = InvitationForm(request.POST)
296 64cd4730 Antony Chazapis
        if inviter.invitations > 0:
297 8f5a3a06 Sofia Papagiannaki
            if form.is_valid():
298 8f5a3a06 Sofia Papagiannaki
                try:
299 9a06d96f Olga Brani
                    email = form.cleaned_data.get('username')
300 9a06d96f Olga Brani
                    realname = form.cleaned_data.get('realname')
301 73fbaec4 Sofia Papagiannaki
                    invite(inviter, email, realname)
302 ae497612 Olga Brani
                    message = _(astakos_messages.INVITATION_SENT) % locals()
303 24406ae3 Sofia Papagiannaki
                    messages.success(request, message)
304 8f5a3a06 Sofia Papagiannaki
                except SendMailError, e:
305 8f5a3a06 Sofia Papagiannaki
                    message = e.message
306 24406ae3 Sofia Papagiannaki
                    messages.error(request, message)
307 8f5a3a06 Sofia Papagiannaki
                    transaction.rollback()
308 18ffbee1 Sofia Papagiannaki
                except BaseException, e:
309 ae497612 Olga Brani
                    message = _(astakos_messages.GENERIC_ERROR)
310 24406ae3 Sofia Papagiannaki
                    messages.error(request, message)
311 18ffbee1 Sofia Papagiannaki
                    logger.exception(e)
312 18ffbee1 Sofia Papagiannaki
                    transaction.rollback()
313 18ffbee1 Sofia Papagiannaki
                else:
314 18ffbee1 Sofia Papagiannaki
                    transaction.commit()
315 64cd4730 Antony Chazapis
        else:
316 ae497612 Olga Brani
            message = _(astakos_messages.MAX_INVITATION_NUMBER_REACHED)
317 24406ae3 Sofia Papagiannaki
            messages.error(request, message)
318 176023aa Kostas Papadimitriou
319 a196eb7e Sofia Papagiannaki
    sent = [{'email': inv.username,
320 d6ae71a2 root
             'realname': inv.realname,
321 d6ae71a2 root
             'is_consumed': inv.is_consumed}
322 5ce3ce4f Sofia Papagiannaki
            for inv in request.user.invitations_sent.all()]
323 77e2ad52 root
    kwargs = {'inviter': inviter,
324 5ce3ce4f Sofia Papagiannaki
              'sent': sent}
325 0905ccd2 Sofia Papagiannaki
    context = get_context(request, extra_context, **kwargs)
326 0905ccd2 Sofia Papagiannaki
    return render_response(template_name,
327 5ce3ce4f Sofia Papagiannaki
                           invitation_form=form,
328 5ce3ce4f Sofia Papagiannaki
                           context_instance=context)
329 5ce3ce4f Sofia Papagiannaki
330 64cd4730 Antony Chazapis
331 9a06d96f Olga Brani
@require_http_methods(["GET", "POST"])
332 badcb2a9 Kostas Papadimitriou
@required_auth_methods_assigned(only_warn=True)
333 890b0eaf Sofia Papagiannaki
@login_required
334 270dd48d Sofia Papagiannaki
@signed_terms_required
335 aab4d540 Sofia Papagiannaki
def edit_profile(request, template_name='im/profile.html', extra_context=None):
336 890b0eaf Sofia Papagiannaki
    """
337 890b0eaf Sofia Papagiannaki
    Allows a user to edit his/her profile.
338 176023aa Kostas Papadimitriou

339 890b0eaf Sofia Papagiannaki
    In case of GET request renders a form for displaying the user information.
340 ce86cd44 Sofia Papagiannaki
    In case of POST updates the user informantion and redirects to ``next``
341 ce86cd44 Sofia Papagiannaki
    url parameter if exists.
342 176023aa Kostas Papadimitriou

343 2cbaacd5 Sofia Papagiannaki
    If the user isn't logged in, redirects to settings.LOGIN_URL.
344 176023aa Kostas Papadimitriou

345 890b0eaf Sofia Papagiannaki
    **Arguments**
346 176023aa Kostas Papadimitriou

347 890b0eaf Sofia Papagiannaki
    ``template_name``
348 890b0eaf Sofia Papagiannaki
        A custom template to use. This is optional; if not specified,
349 1e685275 Sofia Papagiannaki
        this will default to ``im/profile.html``.
350 176023aa Kostas Papadimitriou

351 890b0eaf Sofia Papagiannaki
    ``extra_context``
352 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
353 176023aa Kostas Papadimitriou

354 890b0eaf Sofia Papagiannaki
    **Template:**
355 176023aa Kostas Papadimitriou

356 1e685275 Sofia Papagiannaki
    im/profile.html or ``template_name`` keyword argument.
357 176023aa Kostas Papadimitriou

358 92defad4 Sofia Papagiannaki
    **Settings:**
359 176023aa Kostas Papadimitriou

360 92defad4 Sofia Papagiannaki
    The view expectes the following settings are defined:
361 176023aa Kostas Papadimitriou

362 92defad4 Sofia Papagiannaki
    * LOGIN_URL: login uri
363 890b0eaf Sofia Papagiannaki
    """
364 aab4d540 Sofia Papagiannaki
    extra_context = extra_context or {}
365 bf0c6de5 Sofia Papagiannaki
    form = ProfileForm(
366 bf0c6de5 Sofia Papagiannaki
        instance=request.user,
367 bf0c6de5 Sofia Papagiannaki
        session_key=request.session.session_key
368 bf0c6de5 Sofia Papagiannaki
    )
369 15efc749 Sofia Papagiannaki
    extra_context['next'] = request.GET.get('next')
370 64cd4730 Antony Chazapis
    if request.method == 'POST':
371 bf0c6de5 Sofia Papagiannaki
        form = ProfileForm(
372 bf0c6de5 Sofia Papagiannaki
            request.POST,
373 bf0c6de5 Sofia Papagiannaki
            instance=request.user,
374 bf0c6de5 Sofia Papagiannaki
            session_key=request.session.session_key
375 bf0c6de5 Sofia Papagiannaki
        )
376 890b0eaf Sofia Papagiannaki
        if form.is_valid():
377 64cd4730 Antony Chazapis
            try:
378 c301698f Sofia Papagiannaki
                prev_token = request.user.auth_token
379 3fbf7863 Kostas Papadimitriou
                user = form.save(request=request)
380 217994f8 Sofia Papagiannaki
                next = restrict_next(
381 217994f8 Sofia Papagiannaki
                    request.POST.get('next'),
382 217994f8 Sofia Papagiannaki
                    domain=COOKIE_DOMAIN
383 217994f8 Sofia Papagiannaki
                )
384 ae497612 Olga Brani
                msg = _(astakos_messages.PROFILE_UPDATED)
385 24406ae3 Sofia Papagiannaki
                messages.success(request, msg)
386 f7400729 Kostas Papadimitriou
                if next:
387 f7400729 Kostas Papadimitriou
                    return redirect(next)
388 f7400729 Kostas Papadimitriou
                else:
389 f7400729 Kostas Papadimitriou
                    return redirect(reverse('edit_profile'))
390 890b0eaf Sofia Papagiannaki
            except ValueError, ve:
391 24406ae3 Sofia Papagiannaki
                messages.success(request, ve)
392 23447441 Sofia Papagiannaki
    elif request.method == "GET":
393 792c2f3b Olga Brani
        request.user.is_verified = True
394 792c2f3b Olga Brani
        request.user.save()
395 792c2f3b Olga Brani
396 792c2f3b Olga Brani
    # existing providers
397 792c2f3b Olga Brani
    user_providers = request.user.get_active_auth_providers()
398 792c2f3b Olga Brani
399 792c2f3b Olga Brani
    # providers that user can add
400 792c2f3b Olga Brani
    user_available_providers = request.user.get_available_auth_providers()
401 792c2f3b Olga Brani
402 1ebea3d3 Kostas Papadimitriou
    extra_context['services'] = get_services_dict()
403 0905ccd2 Sofia Papagiannaki
    return render_response(template_name,
404 8f5a3a06 Sofia Papagiannaki
                           profile_form = form,
405 792c2f3b Olga Brani
                           user_providers = user_providers,
406 792c2f3b Olga Brani
                           user_available_providers = user_available_providers,
407 0905ccd2 Sofia Papagiannaki
                           context_instance = get_context(request,
408 c301698f Sofia Papagiannaki
                                                          extra_context))
409 5ce3ce4f Sofia Papagiannaki
410 64cd4730 Antony Chazapis
411 10ed0073 Sofia Papagiannaki
@transaction.commit_manually
412 9a06d96f Olga Brani
@require_http_methods(["GET", "POST"])
413 43332a76 Kostas Papadimitriou
def signup(request, template_name='im/signup.html', on_success='index', extra_context=None, backend=None):
414 890b0eaf Sofia Papagiannaki
    """
415 890b0eaf Sofia Papagiannaki
    Allows a user to create a local account.
416 176023aa Kostas Papadimitriou

417 b669d9c0 Sofia Papagiannaki
    In case of GET request renders a form for entering the user information.
418 890b0eaf Sofia Papagiannaki
    In case of POST handles the signup.
419 176023aa Kostas Papadimitriou

420 890b0eaf Sofia Papagiannaki
    The user activation will be delegated to the backend specified by the ``backend`` keyword argument
421 8f5a3a06 Sofia Papagiannaki
    if present, otherwise to the ``astakos.im.activation_backends.InvitationBackend``
422 8f5a3a06 Sofia Papagiannaki
    if settings.ASTAKOS_INVITATIONS_ENABLED is True or ``astakos.im.activation_backends.SimpleBackend`` if not
423 8f5a3a06 Sofia Papagiannaki
    (see activation_backends);
424 5ce3ce4f Sofia Papagiannaki

425 b669d9c0 Sofia Papagiannaki
    Upon successful user creation, if ``next`` url parameter is present the user is redirected there
426 890b0eaf Sofia Papagiannaki
    otherwise renders the same page with a success message.
427 5ce3ce4f Sofia Papagiannaki

428 8f5a3a06 Sofia Papagiannaki
    On unsuccessful creation, renders ``template_name`` with an error message.
429 5ce3ce4f Sofia Papagiannaki

430 890b0eaf Sofia Papagiannaki
    **Arguments**
431 5ce3ce4f Sofia Papagiannaki

432 8f5a3a06 Sofia Papagiannaki
    ``template_name``
433 8f5a3a06 Sofia Papagiannaki
        A custom template to render. This is optional;
434 1e685275 Sofia Papagiannaki
        if not specified, this will default to ``im/signup.html``.
435 176023aa Kostas Papadimitriou

436 890b0eaf Sofia Papagiannaki
    ``extra_context``
437 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
438 176023aa Kostas Papadimitriou

439 43332a76 Kostas Papadimitriou
    ``on_success``
440 43332a76 Kostas Papadimitriou
        Resolvable view name to redirect on registration success.
441 43332a76 Kostas Papadimitriou

442 890b0eaf Sofia Papagiannaki
    **Template:**
443 5ce3ce4f Sofia Papagiannaki

444 8f5a3a06 Sofia Papagiannaki
    im/signup.html or ``template_name`` keyword argument.
445 890b0eaf Sofia Papagiannaki
    """
446 1f3b4b39 Sofia Papagiannaki
    extra_context = extra_context or {}
447 0d02a287 Sofia Papagiannaki
    if request.user.is_authenticated():
448 6ff7a7ca Sofia Papagiannaki
        return HttpResponseRedirect(reverse('edit_profile'))
449 5ce3ce4f Sofia Papagiannaki
450 0a569195 Sofia Papagiannaki
    provider = get_query(request).get('provider', 'local')
451 279d6e51 Olga Brani
    if not auth_providers.get_provider(provider).is_available_for_create():
452 279d6e51 Olga Brani
        raise PermissionDenied
453 279d6e51 Olga Brani
454 6c8a3f7c Sofia Papagiannaki
    id = get_query(request).get('id')
455 6c8a3f7c Sofia Papagiannaki
    try:
456 6c8a3f7c Sofia Papagiannaki
        instance = AstakosUser.objects.get(id=id) if id else None
457 6c8a3f7c Sofia Papagiannaki
    except AstakosUser.DoesNotExist:
458 6c8a3f7c Sofia Papagiannaki
        instance = None
459 6c8a3f7c Sofia Papagiannaki
460 8ab484ea Kostas Papadimitriou
    third_party_token = request.REQUEST.get('third_party_token', None)
461 c630fee6 Kostas Papadimitriou
    if third_party_token:
462 c630fee6 Kostas Papadimitriou
        pending = get_object_or_404(PendingThirdPartyUser,
463 c630fee6 Kostas Papadimitriou
                                    token=third_party_token)
464 c630fee6 Kostas Papadimitriou
        provider = pending.provider
465 c630fee6 Kostas Papadimitriou
        instance = pending.get_user_instance()
466 8ab484ea Kostas Papadimitriou
467 890b0eaf Sofia Papagiannaki
    try:
468 18ffbee1 Sofia Papagiannaki
        if not backend:
469 18ffbee1 Sofia Papagiannaki
            backend = get_backend(request)
470 6c8a3f7c Sofia Papagiannaki
        form = backend.get_signup_form(provider, instance)
471 0a569195 Sofia Papagiannaki
    except Exception, e:
472 4e30244e Sofia Papagiannaki
        form = SimpleBackend(request).get_signup_form(provider)
473 24406ae3 Sofia Papagiannaki
        messages.error(request, e)
474 8f5a3a06 Sofia Papagiannaki
    if request.method == 'POST':
475 8f5a3a06 Sofia Papagiannaki
        if form.is_valid():
476 18ffbee1 Sofia Papagiannaki
            user = form.save(commit=False)
477 43332a76 Kostas Papadimitriou
478 43332a76 Kostas Papadimitriou
            # delete previously unverified accounts
479 43332a76 Kostas Papadimitriou
            if AstakosUser.objects.user_exists(user.email):
480 43332a76 Kostas Papadimitriou
                AstakosUser.objects.get_by_identifier(user.email).delete()
481 43332a76 Kostas Papadimitriou
482 8f5a3a06 Sofia Papagiannaki
            try:
483 8f5a3a06 Sofia Papagiannaki
                result = backend.handle_activation(user)
484 8f5a3a06 Sofia Papagiannaki
                status = messages.SUCCESS
485 18ffbee1 Sofia Papagiannaki
                message = result.message
486 792c2f3b Olga Brani
487 792c2f3b Olga Brani
                form.store_user(user, request)
488 792c2f3b Olga Brani
489 ca828a10 Sofia Papagiannaki
                if 'additional_email' in form.cleaned_data:
490 ca828a10 Sofia Papagiannaki
                    additional_email = form.cleaned_data['additional_email']
491 ca828a10 Sofia Papagiannaki
                    if additional_email != user.email:
492 ca828a10 Sofia Papagiannaki
                        user.additionalmail_set.create(email=additional_email)
493 5ce3ce4f Sofia Papagiannaki
                        msg = 'Additional email: %s saved for user %s.' % (
494 6c8a3f7c Sofia Papagiannaki
                            additional_email,
495 6c8a3f7c Sofia Papagiannaki
                            user.email
496 6c8a3f7c Sofia Papagiannaki
                        )
497 b669d9c0 Sofia Papagiannaki
                        logger._log(LOGGING_LEVEL, msg, [])
498 43332a76 Kostas Papadimitriou
499 8f5a3a06 Sofia Papagiannaki
                if user and user.is_active:
500 8f5a3a06 Sofia Papagiannaki
                    next = request.POST.get('next', '')
501 40a0cd8b Sofia Papagiannaki
                    response = prepare_response(request, user, next=next)
502 c3f6cdf1 root
                    transaction.commit()
503 40a0cd8b Sofia Papagiannaki
                    return response
504 43332a76 Kostas Papadimitriou
505 792c2f3b Olga Brani
                transaction.commit()
506 43332a76 Kostas Papadimitriou
                messages.add_message(request, status, message)
507 43332a76 Kostas Papadimitriou
                return HttpResponseRedirect(reverse(on_success))
508 43332a76 Kostas Papadimitriou
509 18ffbee1 Sofia Papagiannaki
            except SendMailError, e:
510 c44955a6 Sofia Papagiannaki
                logger.exception(e)
511 18ffbee1 Sofia Papagiannaki
                status = messages.ERROR
512 18ffbee1 Sofia Papagiannaki
                message = e.message
513 24406ae3 Sofia Papagiannaki
                messages.error(request, message)
514 10ed0073 Sofia Papagiannaki
                transaction.rollback()
515 18ffbee1 Sofia Papagiannaki
            except BaseException, e:
516 678b2236 Sofia Papagiannaki
                logger.exception(e)
517 ae497612 Olga Brani
                message = _(astakos_messages.GENERIC_ERROR)
518 24406ae3 Sofia Papagiannaki
                messages.error(request, message)
519 0a569195 Sofia Papagiannaki
                logger.exception(e)
520 10ed0073 Sofia Papagiannaki
                transaction.rollback()
521 43332a76 Kostas Papadimitriou
522 8f5a3a06 Sofia Papagiannaki
    return render_response(template_name,
523 5ce3ce4f Sofia Papagiannaki
                           signup_form=form,
524 8ab484ea Kostas Papadimitriou
                           third_party_token=third_party_token,
525 5ce3ce4f Sofia Papagiannaki
                           provider=provider,
526 890b0eaf Sofia Papagiannaki
                           context_instance=get_context(request, extra_context))
527 64cd4730 Antony Chazapis
528 5ce3ce4f Sofia Papagiannaki
529 9a06d96f Olga Brani
@require_http_methods(["GET", "POST"])
530 badcb2a9 Kostas Papadimitriou
@required_auth_methods_assigned(only_warn=True)
531 890b0eaf Sofia Papagiannaki
@login_required
532 270dd48d Sofia Papagiannaki
@signed_terms_required
533 aab4d540 Sofia Papagiannaki
def feedback(request, template_name='im/feedback.html', email_template_name='im/feedback_mail.txt', extra_context=None):
534 890b0eaf Sofia Papagiannaki
    """
535 890b0eaf Sofia Papagiannaki
    Allows a user to send feedback.
536 176023aa Kostas Papadimitriou

537 890b0eaf Sofia Papagiannaki
    In case of GET request renders a form for providing the feedback information.
538 890b0eaf Sofia Papagiannaki
    In case of POST sends an email to support team.
539 176023aa Kostas Papadimitriou

540 2cbaacd5 Sofia Papagiannaki
    If the user isn't logged in, redirects to settings.LOGIN_URL.
541 176023aa Kostas Papadimitriou

542 890b0eaf Sofia Papagiannaki
    **Arguments**
543 176023aa Kostas Papadimitriou

544 890b0eaf Sofia Papagiannaki
    ``template_name``
545 890b0eaf Sofia Papagiannaki
        A custom template to use. This is optional; if not specified,
546 1e685275 Sofia Papagiannaki
        this will default to ``im/feedback.html``.
547 176023aa Kostas Papadimitriou

548 890b0eaf Sofia Papagiannaki
    ``extra_context``
549 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
550 176023aa Kostas Papadimitriou

551 890b0eaf Sofia Papagiannaki
    **Template:**
552 176023aa Kostas Papadimitriou

553 1e685275 Sofia Papagiannaki
    im/signup.html or ``template_name`` keyword argument.
554 176023aa Kostas Papadimitriou

555 890b0eaf Sofia Papagiannaki
    **Settings:**
556 176023aa Kostas Papadimitriou

557 92defad4 Sofia Papagiannaki
    * LOGIN_URL: login uri
558 890b0eaf Sofia Papagiannaki
    """
559 1f3b4b39 Sofia Papagiannaki
    extra_context = extra_context or {}
560 64cd4730 Antony Chazapis
    if request.method == 'GET':
561 890b0eaf Sofia Papagiannaki
        form = FeedbackForm()
562 890b0eaf Sofia Papagiannaki
    if request.method == 'POST':
563 890b0eaf Sofia Papagiannaki
        if not request.user:
564 890b0eaf Sofia Papagiannaki
            return HttpResponse('Unauthorized', status=401)
565 176023aa Kostas Papadimitriou
566 890b0eaf Sofia Papagiannaki
        form = FeedbackForm(request.POST)
567 890b0eaf Sofia Papagiannaki
        if form.is_valid():
568 e9083112 Sofia Papagiannaki
            msg = form.cleaned_data['feedback_msg']
569 8f5a3a06 Sofia Papagiannaki
            data = form.cleaned_data['feedback_data']
570 538ccdd5 Sofia Papagiannaki
            try:
571 8f5a3a06 Sofia Papagiannaki
                send_feedback(msg, data, request.user, email_template_name)
572 8f5a3a06 Sofia Papagiannaki
            except SendMailError, e:
573 24406ae3 Sofia Papagiannaki
                messages.error(request, message)
574 8f5a3a06 Sofia Papagiannaki
            else:
575 ae497612 Olga Brani
                message = _(astakos_messages.FEEDBACK_SENT)
576 aab4d540 Sofia Papagiannaki
                messages.success(request, message)
577 890b0eaf Sofia Papagiannaki
    return render_response(template_name,
578 5ce3ce4f Sofia Papagiannaki
                           feedback_form=form,
579 5ce3ce4f Sofia Papagiannaki
                           context_instance=get_context(request, extra_context))
580 5ce3ce4f Sofia Papagiannaki
581 15efc749 Sofia Papagiannaki
582 217994f8 Sofia Papagiannaki
@require_http_methods(["GET"])
583 8e45d6fd Sofia Papagiannaki
@signed_terms_required
584 aab4d540 Sofia Papagiannaki
def logout(request, template='registration/logged_out.html', extra_context=None):
585 63ecdd20 Sofia Papagiannaki
    """
586 b2ffa772 Sofia Papagiannaki
    Wraps `django.contrib.auth.logout`.
587 63ecdd20 Sofia Papagiannaki
    """
588 1f3b4b39 Sofia Papagiannaki
    extra_context = extra_context or {}
589 7482228b Sofia Papagiannaki
    response = HttpResponse()
590 8e45d6fd Sofia Papagiannaki
    if request.user.is_authenticated():
591 8e45d6fd Sofia Papagiannaki
        email = request.user.email
592 8e45d6fd Sofia Papagiannaki
        auth_logout(request)
593 c630fee6 Kostas Papadimitriou
    else:
594 c630fee6 Kostas Papadimitriou
        response['Location'] = reverse('index')
595 c630fee6 Kostas Papadimitriou
        response.status_code = 301
596 c630fee6 Kostas Papadimitriou
        return response
597 c630fee6 Kostas Papadimitriou
598 217994f8 Sofia Papagiannaki
    next = restrict_next(
599 217994f8 Sofia Papagiannaki
        request.GET.get('next'),
600 217994f8 Sofia Papagiannaki
        domain=COOKIE_DOMAIN
601 217994f8 Sofia Papagiannaki
    )
602 c630fee6 Kostas Papadimitriou
603 63ecdd20 Sofia Papagiannaki
    if next:
604 63ecdd20 Sofia Papagiannaki
        response['Location'] = next
605 63ecdd20 Sofia Papagiannaki
        response.status_code = 302
606 0d02a287 Sofia Papagiannaki
    elif LOGOUT_NEXT:
607 0d02a287 Sofia Papagiannaki
        response['Location'] = LOGOUT_NEXT
608 0d02a287 Sofia Papagiannaki
        response.status_code = 301
609 b2ffa772 Sofia Papagiannaki
    else:
610 564a2292 Kostas Papadimitriou
        message = _(astakos_messages.LOGOUT_SUCCESS)
611 564a2292 Kostas Papadimitriou
        last_provider = request.COOKIES.get('astakos_last_login_method', None)
612 564a2292 Kostas Papadimitriou
        if last_provider:
613 564a2292 Kostas Papadimitriou
            provider = auth_providers.get_provider(last_provider)
614 564a2292 Kostas Papadimitriou
            extra_message = provider.get_logout_message_display
615 564a2292 Kostas Papadimitriou
            if extra_message:
616 564a2292 Kostas Papadimitriou
                message += '<br />' + extra_message
617 564a2292 Kostas Papadimitriou
        messages.add_message(request, messages.SUCCESS, mark_safe(message))
618 c630fee6 Kostas Papadimitriou
        response['Location'] = reverse('index')
619 c630fee6 Kostas Papadimitriou
        response.status_code = 301
620 49df775e Sofia Papagiannaki
    return response
621 2126d85d Sofia Papagiannaki
622 5ce3ce4f Sofia Papagiannaki
623 9a06d96f Olga Brani
@require_http_methods(["GET", "POST"])
624 683cf244 Sofia Papagiannaki
@transaction.commit_manually
625 3bb604eb Sofia Papagiannaki
def activate(request, greeting_email_template_name='im/welcome_email.txt',
626 3bb604eb Sofia Papagiannaki
             helpdesk_email_template_name='im/helpdesk_notification.txt'):
627 2126d85d Sofia Papagiannaki
    """
628 683cf244 Sofia Papagiannaki
    Activates the user identified by the ``auth`` request parameter, sends a welcome email
629 683cf244 Sofia Papagiannaki
    and renews the user token.
630 176023aa Kostas Papadimitriou

631 683cf244 Sofia Papagiannaki
    The view uses commit_manually decorator in order to ensure the user state will be updated
632 683cf244 Sofia Papagiannaki
    only if the email will be send successfully.
633 2126d85d Sofia Papagiannaki
    """
634 2126d85d Sofia Papagiannaki
    token = request.GET.get('auth')
635 2126d85d Sofia Papagiannaki
    next = request.GET.get('next')
636 2126d85d Sofia Papagiannaki
    try:
637 2126d85d Sofia Papagiannaki
        user = AstakosUser.objects.get(auth_token=token)
638 2126d85d Sofia Papagiannaki
    except AstakosUser.DoesNotExist:
639 279d6e51 Olga Brani
        return HttpResponseBadRequest(_(astakos_messages.ACCOUNT_UNKNOWN))
640 5ce3ce4f Sofia Papagiannaki
641 d1757ca7 Sofia Papagiannaki
    if user.is_active:
642 ae497612 Olga Brani
        message = _(astakos_messages.ACCOUNT_ALREADY_ACTIVE)
643 24406ae3 Sofia Papagiannaki
        messages.error(request, message)
644 279d6e51 Olga Brani
        return index(request)
645 5ce3ce4f Sofia Papagiannaki
646 0a569195 Sofia Papagiannaki
    try:
647 279d6e51 Olga Brani
        activate_func(user, greeting_email_template_name, helpdesk_email_template_name, verify_email=True)
648 ef20ea07 Sofia Papagiannaki
        response = prepare_response(request, user, next, renew=True)
649 ef20ea07 Sofia Papagiannaki
        transaction.commit()
650 279d6e51 Olga Brani
        return response
651 ef20ea07 Sofia Papagiannaki
    except SendMailError, e:
652 ef20ea07 Sofia Papagiannaki
        message = e.message
653 ef20ea07 Sofia Papagiannaki
        messages.add_message(request, messages.ERROR, message)
654 ef20ea07 Sofia Papagiannaki
        transaction.rollback()
655 279d6e51 Olga Brani
        return index(request)
656 ef20ea07 Sofia Papagiannaki
    except BaseException, e:
657 ef20ea07 Sofia Papagiannaki
        status = messages.ERROR
658 c0b26605 Sofia Papagiannaki
        message = _(astakos_messages.GENERIC_ERROR)
659 ef20ea07 Sofia Papagiannaki
        messages.add_message(request, messages.ERROR, message)
660 ef20ea07 Sofia Papagiannaki
        logger.exception(e)
661 ef20ea07 Sofia Papagiannaki
        transaction.rollback()
662 279d6e51 Olga Brani
        return index(request)
663 270dd48d Sofia Papagiannaki
664 5ce3ce4f Sofia Papagiannaki
665 9a06d96f Olga Brani
@require_http_methods(["GET", "POST"])
666 aab4d540 Sofia Papagiannaki
def approval_terms(request, term_id=None, template_name='im/approval_terms.html', extra_context=None):
667 1f3b4b39 Sofia Papagiannaki
    extra_context = extra_context or {}
668 270dd48d Sofia Papagiannaki
    term = None
669 270dd48d Sofia Papagiannaki
    terms = None
670 270dd48d Sofia Papagiannaki
    if not term_id:
671 270dd48d Sofia Papagiannaki
        try:
672 270dd48d Sofia Papagiannaki
            term = ApprovalTerms.objects.order_by('-id')[0]
673 270dd48d Sofia Papagiannaki
        except IndexError:
674 270dd48d Sofia Papagiannaki
            pass
675 270dd48d Sofia Papagiannaki
    else:
676 270dd48d Sofia Papagiannaki
        try:
677 aab4d540 Sofia Papagiannaki
            term = ApprovalTerms.objects.get(id=term_id)
678 aab4d540 Sofia Papagiannaki
        except ApprovalTerms.DoesNotExist, e:
679 270dd48d Sofia Papagiannaki
            pass
680 176023aa Kostas Papadimitriou
681 270dd48d Sofia Papagiannaki
    if not term:
682 ae497612 Olga Brani
        messages.error(request, _(astakos_messages.NO_APPROVAL_TERMS))
683 6ff7a7ca Sofia Papagiannaki
        return HttpResponseRedirect(reverse('index'))
684 270dd48d Sofia Papagiannaki
    f = open(term.location, 'r')
685 270dd48d Sofia Papagiannaki
    terms = f.read()
686 176023aa Kostas Papadimitriou
687 270dd48d Sofia Papagiannaki
    if request.method == 'POST':
688 217994f8 Sofia Papagiannaki
        next = restrict_next(
689 217994f8 Sofia Papagiannaki
            request.POST.get('next'),
690 217994f8 Sofia Papagiannaki
            domain=COOKIE_DOMAIN
691 217994f8 Sofia Papagiannaki
        )
692 270dd48d Sofia Papagiannaki
        if not next:
693 6ff7a7ca Sofia Papagiannaki
            next = reverse('index')
694 270dd48d Sofia Papagiannaki
        form = SignApprovalTermsForm(request.POST, instance=request.user)
695 270dd48d Sofia Papagiannaki
        if not form.is_valid():
696 270dd48d Sofia Papagiannaki
            return render_response(template_name,
697 5ce3ce4f Sofia Papagiannaki
                                   terms=terms,
698 5ce3ce4f Sofia Papagiannaki
                                   approval_terms_form=form,
699 5ce3ce4f Sofia Papagiannaki
                                   context_instance=get_context(request, extra_context))
700 270dd48d Sofia Papagiannaki
        user = form.save()
701 270dd48d Sofia Papagiannaki
        return HttpResponseRedirect(next)
702 270dd48d Sofia Papagiannaki
    else:
703 586967c0 Sofia Papagiannaki
        form = None
704 fcf90160 Sofia Papagiannaki
        if request.user.is_authenticated() and not request.user.signed_terms:
705 586967c0 Sofia Papagiannaki
            form = SignApprovalTermsForm(instance=request.user)
706 270dd48d Sofia Papagiannaki
        return render_response(template_name,
707 5ce3ce4f Sofia Papagiannaki
                               terms=terms,
708 5ce3ce4f Sofia Papagiannaki
                               approval_terms_form=form,
709 5ce3ce4f Sofia Papagiannaki
                               context_instance=get_context(request, extra_context))
710 5ce3ce4f Sofia Papagiannaki
711 270dd48d Sofia Papagiannaki
712 9a06d96f Olga Brani
@require_http_methods(["GET", "POST"])
713 49790d9d Sofia Papagiannaki
@transaction.commit_manually
714 49790d9d Sofia Papagiannaki
def change_email(request, activation_key=None,
715 49790d9d Sofia Papagiannaki
                 email_template_name='registration/email_change_email.txt',
716 49790d9d Sofia Papagiannaki
                 form_template_name='registration/email_change_form.html',
717 49790d9d Sofia Papagiannaki
                 confirm_template_name='registration/email_change_done.html',
718 aab4d540 Sofia Papagiannaki
                 extra_context=None):
719 1f3b4b39 Sofia Papagiannaki
    extra_context = extra_context or {}
720 53e0b8fe Kostas Papadimitriou
721 53e0b8fe Kostas Papadimitriou
722 17ad5d37 Kostas Papadimitriou
    if not astakos_settings.EMAILCHANGE_ENABLED:
723 17ad5d37 Kostas Papadimitriou
        raise PermissionDenied
724 17ad5d37 Kostas Papadimitriou
725 49790d9d Sofia Papagiannaki
    if activation_key:
726 49790d9d Sofia Papagiannaki
        try:
727 49790d9d Sofia Papagiannaki
            user = EmailChange.objects.change_email(activation_key)
728 10a870d5 Kostas Papadimitriou
            if request.user.is_authenticated() and request.user == user or not \
729 10a870d5 Kostas Papadimitriou
                    request.user.is_authenticated():
730 ae497612 Olga Brani
                msg = _(astakos_messages.EMAIL_CHANGED)
731 24406ae3 Sofia Papagiannaki
                messages.success(request, msg)
732 49790d9d Sofia Papagiannaki
                transaction.commit()
733 53e0b8fe Kostas Papadimitriou
                return HttpResponseRedirect(reverse('edit_profile'))
734 49790d9d Sofia Papagiannaki
        except ValueError, e:
735 24406ae3 Sofia Papagiannaki
            messages.error(request, e)
736 53e0b8fe Kostas Papadimitriou
            transaction.rollback()
737 53e0b8fe Kostas Papadimitriou
            return HttpResponseRedirect(reverse('index'))
738 53e0b8fe Kostas Papadimitriou
739 49790d9d Sofia Papagiannaki
        return render_response(confirm_template_name,
740 53e0b8fe Kostas Papadimitriou
                               modified_user=user if 'user' in locals() \
741 53e0b8fe Kostas Papadimitriou
                               else None, context_instance=get_context(request,
742 5ce3ce4f Sofia Papagiannaki
                                                            extra_context))
743 5ce3ce4f Sofia Papagiannaki
744 49790d9d Sofia Papagiannaki
    if not request.user.is_authenticated():
745 49790d9d Sofia Papagiannaki
        path = quote(request.get_full_path())
746 6ff7a7ca Sofia Papagiannaki
        url = request.build_absolute_uri(reverse('index'))
747 49790d9d Sofia Papagiannaki
        return HttpResponseRedirect(url + '?next=' + path)
748 53e0b8fe Kostas Papadimitriou
749 53e0b8fe Kostas Papadimitriou
    # clean up expired email changes
750 53e0b8fe Kostas Papadimitriou
    if request.user.email_change_is_pending():
751 53e0b8fe Kostas Papadimitriou
        change = request.user.emailchanges.get()
752 53e0b8fe Kostas Papadimitriou
        if change.activation_key_expired():
753 53e0b8fe Kostas Papadimitriou
            change.delete()
754 53e0b8fe Kostas Papadimitriou
            transaction.commit()
755 53e0b8fe Kostas Papadimitriou
            return HttpResponseRedirect(reverse('email_change'))
756 53e0b8fe Kostas Papadimitriou
757 49790d9d Sofia Papagiannaki
    form = EmailChangeForm(request.POST or None)
758 49790d9d Sofia Papagiannaki
    if request.method == 'POST' and form.is_valid():
759 49790d9d Sofia Papagiannaki
        try:
760 49790d9d Sofia Papagiannaki
            ec = form.save(email_template_name, request)
761 49790d9d Sofia Papagiannaki
        except SendMailError, e:
762 49790d9d Sofia Papagiannaki
            msg = e
763 24406ae3 Sofia Papagiannaki
            messages.error(request, msg)
764 49790d9d Sofia Papagiannaki
            transaction.rollback()
765 53e0b8fe Kostas Papadimitriou
            return HttpResponseRedirect(reverse('edit_profile'))
766 49790d9d Sofia Papagiannaki
        else:
767 ae497612 Olga Brani
            msg = _(astakos_messages.EMAIL_CHANGE_REGISTERED)
768 24406ae3 Sofia Papagiannaki
            messages.success(request, msg)
769 49790d9d Sofia Papagiannaki
            transaction.commit()
770 53e0b8fe Kostas Papadimitriou
            return HttpResponseRedirect(reverse('edit_profile'))
771 53e0b8fe Kostas Papadimitriou
772 53e0b8fe Kostas Papadimitriou
    if request.user.email_change_is_pending():
773 53e0b8fe Kostas Papadimitriou
        messages.warning(request, astakos_messages.PENDING_EMAIL_CHANGE_REQUEST)
774 53e0b8fe Kostas Papadimitriou
775 c0b26605 Sofia Papagiannaki
    return render_response(
776 c0b26605 Sofia Papagiannaki
        form_template_name,
777 c0b26605 Sofia Papagiannaki
        form=form,
778 c0b26605 Sofia Papagiannaki
        context_instance=get_context(request, extra_context)
779 c0b26605 Sofia Papagiannaki
    )
780 1f3b4b39 Sofia Papagiannaki
781 1f3b4b39 Sofia Papagiannaki
782 1f3b4b39 Sofia Papagiannaki
def send_activation(request, user_id, template_name='im/login.html', extra_context=None):
783 792c2f3b Olga Brani
784 badcb2a9 Kostas Papadimitriou
    if request.user.is_authenticated():
785 badcb2a9 Kostas Papadimitriou
        messages.error(request, _(astakos_messages.ALREADY_LOGGED_IN))
786 badcb2a9 Kostas Papadimitriou
        return HttpResponseRedirect(reverse('edit_profile'))
787 badcb2a9 Kostas Papadimitriou
788 48421603 Kostas Papadimitriou
    if astakos_settings.MODERATION_ENABLED:
789 792c2f3b Olga Brani
        raise PermissionDenied
790 792c2f3b Olga Brani
791 1f3b4b39 Sofia Papagiannaki
    extra_context = extra_context or {}
792 1f3b4b39 Sofia Papagiannaki
    try:
793 1f3b4b39 Sofia Papagiannaki
        u = AstakosUser.objects.get(id=user_id)
794 1f3b4b39 Sofia Papagiannaki
    except AstakosUser.DoesNotExist:
795 c0b26605 Sofia Papagiannaki
        messages.error(request, _(astakos_messages.ACCOUNT_UNKNOWN))
796 1f3b4b39 Sofia Papagiannaki
    else:
797 1f3b4b39 Sofia Papagiannaki
        try:
798 1f3b4b39 Sofia Papagiannaki
            send_activation_func(u)
799 c0b26605 Sofia Papagiannaki
            msg = _(astakos_messages.ACTIVATION_SENT)
800 1f3b4b39 Sofia Papagiannaki
            messages.success(request, msg)
801 1f3b4b39 Sofia Papagiannaki
        except SendMailError, e:
802 1f3b4b39 Sofia Papagiannaki
            messages.error(request, e)
803 1f3b4b39 Sofia Papagiannaki
    return render_response(
804 1f3b4b39 Sofia Papagiannaki
        template_name,
805 c0b26605 Sofia Papagiannaki
        login_form = LoginForm(request=request),
806 1f3b4b39 Sofia Papagiannaki
        context_instance = get_context(
807 1f3b4b39 Sofia Papagiannaki
            request,
808 1f3b4b39 Sofia Papagiannaki
            extra_context
809 1f3b4b39 Sofia Papagiannaki
        )
810 1f3b4b39 Sofia Papagiannaki
    )
811 5ce3ce4f Sofia Papagiannaki
812 73fbaec4 Sofia Papagiannaki
813 73fbaec4 Sofia Papagiannaki
@require_http_methods(["GET"])
814 badcb2a9 Kostas Papadimitriou
@valid_astakos_user_required
815 666c7490 Sofia Papagiannaki
def resource_usage(request):
816 e9ef5009 Kostas Papadimitriou
817 e9ef5009 Kostas Papadimitriou
    def with_class(entry):
818 e9ef5009 Kostas Papadimitriou
         entry['load_class'] = 'red'
819 e9ef5009 Kostas Papadimitriou
         max_value = float(entry['maxValue'])
820 e9ef5009 Kostas Papadimitriou
         curr_value = float(entry['currValue'])
821 e9ef5009 Kostas Papadimitriou
         entry['ratio_limited']= 0
822 e9ef5009 Kostas Papadimitriou
         if max_value > 0 :
823 e9ef5009 Kostas Papadimitriou
             entry['ratio'] = (curr_value / max_value) * 100
824 e9ef5009 Kostas Papadimitriou
         else:
825 e9ef5009 Kostas Papadimitriou
             entry['ratio'] = 0
826 e9ef5009 Kostas Papadimitriou
         if entry['ratio'] < 66:
827 e9ef5009 Kostas Papadimitriou
             entry['load_class'] = 'yellow'
828 e9ef5009 Kostas Papadimitriou
         if entry['ratio'] < 33:
829 e9ef5009 Kostas Papadimitriou
             entry['load_class'] = 'green'
830 e9ef5009 Kostas Papadimitriou
         if entry['ratio']<0:
831 e9ef5009 Kostas Papadimitriou
             entry['ratio'] = 0
832 e9ef5009 Kostas Papadimitriou
         if entry['ratio']>100:
833 e9ef5009 Kostas Papadimitriou
             entry['ratio_limited'] = 100
834 e9ef5009 Kostas Papadimitriou
         else:
835 e9ef5009 Kostas Papadimitriou
             entry['ratio_limited'] = entry['ratio']
836 e9ef5009 Kostas Papadimitriou
         return entry
837 e9ef5009 Kostas Papadimitriou
838 e9ef5009 Kostas Papadimitriou
    def pluralize(entry):
839 e9ef5009 Kostas Papadimitriou
        entry['plural'] = engine.plural(entry.get('name'))
840 e9ef5009 Kostas Papadimitriou
        return entry
841 e9ef5009 Kostas Papadimitriou
842 a9c7ff8a Sofia Papagiannaki
    resource_usage = None
843 666c7490 Sofia Papagiannaki
    result = callpoint.get_user_usage(request.user.id)
844 820b18e0 Sofia Papagiannaki
    if result.is_success:
845 a9c7ff8a Sofia Papagiannaki
        resource_usage = result.data
846 e9ef5009 Kostas Papadimitriou
        backenddata = map(with_class, result.data)
847 e2497bc5 Sofia Papagiannaki
        backenddata = map(pluralize , backenddata)
848 9a06d96f Olga Brani
    else:
849 820b18e0 Sofia Papagiannaki
        messages.error(request, result.reason)
850 37f8b1a6 Olga Brani
        backenddata = []
851 401089d8 Kostas Papadimitriou
        resource_usage = []
852 401089d8 Kostas Papadimitriou
853 401089d8 Kostas Papadimitriou
    if request.REQUEST.get('json', None):
854 401089d8 Kostas Papadimitriou
        return HttpResponse(json.dumps(backenddata),
855 401089d8 Kostas Papadimitriou
                            mimetype="application/json")
856 401089d8 Kostas Papadimitriou
857 666c7490 Sofia Papagiannaki
    return render_response('im/resource_usage.html',
858 3cbd5e47 Olga Brani
                           context_instance=get_context(request),
859 e9ef5009 Kostas Papadimitriou
                           resource_usage=backenddata,
860 401089d8 Kostas Papadimitriou
                           usage_update_interval=astakos_settings.USAGE_UPDATE_INTERVAL,
861 3cbd5e47 Olga Brani
                           result=result)
862 9a06d96f Olga Brani
863 f432088a Kostas Papadimitriou
# TODO: action only on POST and user should confirm the removal
864 d2633501 Kostas Papadimitriou
@require_http_methods(["GET", "POST"])
865 d2633501 Kostas Papadimitriou
@login_required
866 d2633501 Kostas Papadimitriou
@signed_terms_required
867 d2633501 Kostas Papadimitriou
def remove_auth_provider(request, pk):
868 f432088a Kostas Papadimitriou
    try:
869 f432088a Kostas Papadimitriou
        provider = request.user.auth_providers.get(pk=pk)
870 f432088a Kostas Papadimitriou
    except AstakosUserAuthProvider.DoesNotExist:
871 f432088a Kostas Papadimitriou
        raise Http404
872 f432088a Kostas Papadimitriou
873 d2633501 Kostas Papadimitriou
    if provider.can_remove():
874 d2633501 Kostas Papadimitriou
        provider.delete()
875 d2633501 Kostas Papadimitriou
        return HttpResponseRedirect(reverse('edit_profile'))
876 d2633501 Kostas Papadimitriou
    else:
877 f432088a Kostas Papadimitriou
        raise PermissionDenied
878 5ebebb20 Olga Brani
879 792c2f3b Olga Brani
880 5ebebb20 Olga Brani
def how_it_works(request):
881 5ebebb20 Olga Brani
    return render_response(
882 ccab6eb5 Sofia Papagiannaki
        'im/how_it_works.html',
883 ccab6eb5 Sofia Papagiannaki
        context_instance=get_context(request))
884 e1a80257 Sofia Papagiannaki
885 bfe23b13 Sofia Papagiannaki
@transaction.commit_manually
886 172ce682 Sofia Papagiannaki
def _create_object(request, model=None, template_name=None,
887 172ce682 Sofia Papagiannaki
        template_loader=template_loader, extra_context=None, post_save_redirect=None,
888 6556e514 Sofia Papagiannaki
        login_required=False, context_processors=None, form_class=None,
889 6556e514 Sofia Papagiannaki
        msg=None):
890 172ce682 Sofia Papagiannaki
    """
891 4e748491 Sofia Papagiannaki
    Based of django.views.generic.create_update.create_object which displays a
892 172ce682 Sofia Papagiannaki
    summary page before creating the object.
893 172ce682 Sofia Papagiannaki
    """
894 bfe23b13 Sofia Papagiannaki
    rollback = False
895 172ce682 Sofia Papagiannaki
    response = None
896 4e748491 Sofia Papagiannaki
897 4e748491 Sofia Papagiannaki
    if extra_context is None: extra_context = {}
898 4e748491 Sofia Papagiannaki
    if login_required and not request.user.is_authenticated():
899 4e748491 Sofia Papagiannaki
        return redirect_to_login(request.path)
900 ccab6eb5 Sofia Papagiannaki
    try:
901 f7cf5257 Kostas Papadimitriou
902 172ce682 Sofia Papagiannaki
        model, form_class = get_model_and_form_class(model, form_class)
903 172ce682 Sofia Papagiannaki
        extra_context['edit'] = 0
904 172ce682 Sofia Papagiannaki
        if request.method == 'POST':
905 172ce682 Sofia Papagiannaki
            form = form_class(request.POST, request.FILES)
906 172ce682 Sofia Papagiannaki
            if form.is_valid():
907 172ce682 Sofia Papagiannaki
                verify = request.GET.get('verify')
908 172ce682 Sofia Papagiannaki
                edit = request.GET.get('edit')
909 172ce682 Sofia Papagiannaki
                if verify == '1':
910 172ce682 Sofia Papagiannaki
                    extra_context['show_form'] = False
911 172ce682 Sofia Papagiannaki
                    extra_context['form_data'] = form.cleaned_data
912 172ce682 Sofia Papagiannaki
                elif edit == '1':
913 172ce682 Sofia Papagiannaki
                    extra_context['show_form'] = True
914 172ce682 Sofia Papagiannaki
                else:
915 172ce682 Sofia Papagiannaki
                    new_object = form.save()
916 6556e514 Sofia Papagiannaki
                    if not msg:
917 6556e514 Sofia Papagiannaki
                        msg = _("The %(verbose_name)s was created successfully.")
918 6556e514 Sofia Papagiannaki
                    msg = msg % model._meta.__dict__
919 172ce682 Sofia Papagiannaki
                    messages.success(request, msg, fail_silently=True)
920 172ce682 Sofia Papagiannaki
                    response = redirect(post_save_redirect, new_object)
921 172ce682 Sofia Papagiannaki
        else:
922 172ce682 Sofia Papagiannaki
            form = form_class()
923 b8f05f8d Sofia Papagiannaki
    except BaseException, e:
924 b8f05f8d Sofia Papagiannaki
        logger.exception(e)
925 b8f05f8d Sofia Papagiannaki
        messages.error(request, _(astakos_messages.GENERIC_ERROR))
926 bfe23b13 Sofia Papagiannaki
        rollback = True
927 bfe23b13 Sofia Papagiannaki
    finally:
928 bfe23b13 Sofia Papagiannaki
        if rollback:
929 bfe23b13 Sofia Papagiannaki
            transaction.rollback()
930 bfe23b13 Sofia Papagiannaki
        else:
931 bfe23b13 Sofia Papagiannaki
            transaction.commit()
932 4e748491 Sofia Papagiannaki
933 172ce682 Sofia Papagiannaki
        if response == None:
934 172ce682 Sofia Papagiannaki
            # Create the template, context, response
935 172ce682 Sofia Papagiannaki
            if not template_name:
936 172ce682 Sofia Papagiannaki
                template_name = "%s/%s_form.html" %\
937 172ce682 Sofia Papagiannaki
                     (model._meta.app_label, model._meta.object_name.lower())
938 172ce682 Sofia Papagiannaki
            t = template_loader.get_template(template_name)
939 172ce682 Sofia Papagiannaki
            c = RequestContext(request, {
940 172ce682 Sofia Papagiannaki
                'form': form
941 172ce682 Sofia Papagiannaki
            }, context_processors)
942 172ce682 Sofia Papagiannaki
            apply_extra_context(extra_context, c)
943 172ce682 Sofia Papagiannaki
            response = HttpResponse(t.render(c))
944 172ce682 Sofia Papagiannaki
        return response
945 172ce682 Sofia Papagiannaki
946 4e748491 Sofia Papagiannaki
@transaction.commit_manually
947 4e748491 Sofia Papagiannaki
def _update_object(request, model=None, object_id=None, slug=None,
948 4e748491 Sofia Papagiannaki
        slug_field='slug', template_name=None, template_loader=template_loader,
949 4e748491 Sofia Papagiannaki
        extra_context=None, post_save_redirect=None, login_required=False,
950 4e748491 Sofia Papagiannaki
        context_processors=None, template_object_name='object',
951 6556e514 Sofia Papagiannaki
        form_class=None, msg=None):
952 4e748491 Sofia Papagiannaki
    """
953 4e748491 Sofia Papagiannaki
    Based of django.views.generic.create_update.update_object which displays a
954 4e748491 Sofia Papagiannaki
    summary page before updating the object.
955 4e748491 Sofia Papagiannaki
    """
956 4e748491 Sofia Papagiannaki
    rollback = False
957 4e748491 Sofia Papagiannaki
    response = None
958 4e748491 Sofia Papagiannaki
959 4e748491 Sofia Papagiannaki
    if extra_context is None: extra_context = {}
960 4e748491 Sofia Papagiannaki
    if login_required and not request.user.is_authenticated():
961 4e748491 Sofia Papagiannaki
        return redirect_to_login(request.path)
962 f7cf5257 Kostas Papadimitriou
963 4e748491 Sofia Papagiannaki
    try:
964 4e748491 Sofia Papagiannaki
        model, form_class = get_model_and_form_class(model, form_class)
965 4e748491 Sofia Papagiannaki
        obj = lookup_object(model, object_id, slug, slug_field)
966 f7cf5257 Kostas Papadimitriou
967 4e748491 Sofia Papagiannaki
        if request.method == 'POST':
968 4e748491 Sofia Papagiannaki
            form = form_class(request.POST, request.FILES, instance=obj)
969 4e748491 Sofia Papagiannaki
            if form.is_valid():
970 4e748491 Sofia Papagiannaki
                verify = request.GET.get('verify')
971 4e748491 Sofia Papagiannaki
                edit = request.GET.get('edit')
972 4e748491 Sofia Papagiannaki
                if verify == '1':
973 4e748491 Sofia Papagiannaki
                    extra_context['show_form'] = False
974 4e748491 Sofia Papagiannaki
                    extra_context['form_data'] = form.cleaned_data
975 4e748491 Sofia Papagiannaki
                elif edit == '1':
976 4e748491 Sofia Papagiannaki
                    extra_context['show_form'] = True
977 f7cf5257 Kostas Papadimitriou
                else:
978 4e748491 Sofia Papagiannaki
                    obj = form.save()
979 6556e514 Sofia Papagiannaki
                    if not msg:
980 6556e514 Sofia Papagiannaki
                        msg = _("The %(verbose_name)s was created successfully.")
981 6556e514 Sofia Papagiannaki
                    msg = msg % model._meta.__dict__
982 6556e514 Sofia Papagiannaki
                    messages.success(request, msg, fail_silently=True)
983 4e748491 Sofia Papagiannaki
                    response = redirect(post_save_redirect, obj)
984 4e748491 Sofia Papagiannaki
        else:
985 4e748491 Sofia Papagiannaki
            form = form_class(instance=obj)
986 4e748491 Sofia Papagiannaki
    except BaseException, e:
987 4e748491 Sofia Papagiannaki
        logger.exception(e)
988 4e748491 Sofia Papagiannaki
        messages.error(request, _(astakos_messages.GENERIC_ERROR))
989 4e748491 Sofia Papagiannaki
        rollback = True
990 4e748491 Sofia Papagiannaki
    finally:
991 4e748491 Sofia Papagiannaki
        if rollback:
992 4e748491 Sofia Papagiannaki
            transaction.rollback()
993 4e748491 Sofia Papagiannaki
        else:
994 4e748491 Sofia Papagiannaki
            transaction.commit()
995 4e748491 Sofia Papagiannaki
        if response == None:
996 4e748491 Sofia Papagiannaki
            if not template_name:
997 4e748491 Sofia Papagiannaki
                template_name = "%s/%s_form.html" %\
998 4e748491 Sofia Papagiannaki
                    (model._meta.app_label, model._meta.object_name.lower())
999 4e748491 Sofia Papagiannaki
            t = template_loader.get_template(template_name)
1000 4e748491 Sofia Papagiannaki
            c = RequestContext(request, {
1001 4e748491 Sofia Papagiannaki
                'form': form,
1002 4e748491 Sofia Papagiannaki
                template_object_name: obj,
1003 4e748491 Sofia Papagiannaki
            }, context_processors)
1004 4e748491 Sofia Papagiannaki
            apply_extra_context(extra_context, c)
1005 4e748491 Sofia Papagiannaki
            response = HttpResponse(t.render(c))
1006 4e748491 Sofia Papagiannaki
            populate_xheaders(request, response, model, getattr(obj, obj._meta.pk.attname))
1007 4e748491 Sofia Papagiannaki
        return response
1008 4e748491 Sofia Papagiannaki
1009 172ce682 Sofia Papagiannaki
@require_http_methods(["GET", "POST"])
1010 172ce682 Sofia Papagiannaki
@signed_terms_required
1011 172ce682 Sofia Papagiannaki
@login_required
1012 172ce682 Sofia Papagiannaki
def project_add(request):
1013 6556e514 Sofia Papagiannaki
    resource_groups = RESOURCES_PRESENTATION_DATA.get('groups', {})
1014 6556e514 Sofia Papagiannaki
    resource_catalog = ()
1015 172ce682 Sofia Papagiannaki
    result = callpoint.list_resources()
1016 6556e514 Sofia Papagiannaki
    details_fields = [
1017 6556e514 Sofia Papagiannaki
        "name", "homepage", "description","start_date","end_date", "comments"]
1018 6556e514 Sofia Papagiannaki
    membership_fields =[
1019 6556e514 Sofia Papagiannaki
        "member_join_policy", "member_leave_policy", "limit_on_members_number"]
1020 172ce682 Sofia Papagiannaki
    if not result.is_success:
1021 172ce682 Sofia Papagiannaki
        messages.error(
1022 172ce682 Sofia Papagiannaki
            request,
1023 172ce682 Sofia Papagiannaki
            'Unable to retrieve system resources: %s' % result.reason
1024 172ce682 Sofia Papagiannaki
    )
1025 172ce682 Sofia Papagiannaki
    else:
1026 6556e514 Sofia Papagiannaki
        resource_catalog = [
1027 6556e514 Sofia Papagiannaki
            (g, filter(lambda r: r.get('group', '') == g, result.data)) \
1028 6556e514 Sofia Papagiannaki
                for g in resource_groups]
1029 6556e514 Sofia Papagiannaki
    extra_context = {
1030 6556e514 Sofia Papagiannaki
        'resource_catalog':resource_catalog,
1031 6556e514 Sofia Papagiannaki
        'resource_groups':resource_groups,
1032 6556e514 Sofia Papagiannaki
        'show_form':True,
1033 6556e514 Sofia Papagiannaki
        'details_fields':details_fields,
1034 6556e514 Sofia Papagiannaki
        'membership_fields':membership_fields}
1035 6556e514 Sofia Papagiannaki
    return _create_object(
1036 6556e514 Sofia Papagiannaki
        request,
1037 6556e514 Sofia Papagiannaki
        template_name='im/projects/projectapplication_form.html',
1038 6556e514 Sofia Papagiannaki
        extra_context=extra_context,
1039 6556e514 Sofia Papagiannaki
        post_save_redirect=reverse('project_list'),
1040 6556e514 Sofia Papagiannaki
        form_class=ProjectApplicationForm,
1041 6556e514 Sofia Papagiannaki
        msg=_("The %(verbose_name)s has been received and \
1042 6556e514 Sofia Papagiannaki
                 is under consideration."))
1043 ccab6eb5 Sofia Papagiannaki
1044 e1a80257 Sofia Papagiannaki
1045 e1a80257 Sofia Papagiannaki
@require_http_methods(["GET"])
1046 e1a80257 Sofia Papagiannaki
@signed_terms_required
1047 e1a80257 Sofia Papagiannaki
@login_required
1048 f3342849 Sofia Papagiannaki
def project_list(request):
1049 05617ab9 Kostas Papadimitriou
    projects = ProjectApplication.objects.user_accessible_projects(request.user).select_related()
1050 2743e261 Kostas Papadimitriou
    table = tables.UserProjectApplicationsTable(projects, user=request.user,
1051 2743e261 Kostas Papadimitriou
                                                prefix="my_projects_")
1052 e6d284ef Olga Brani
    RequestConfig(request, paginate={"per_page": PAGINATE_BY}).configure(table)
1053 f7cf5257 Kostas Papadimitriou
1054 e1a80257 Sofia Papagiannaki
    return object_list(
1055 e1a80257 Sofia Papagiannaki
        request,
1056 5550bcfb Kostas Papadimitriou
        projects,
1057 71a38edf Sofia Papagiannaki
        template_name='im/projects/project_list.html',
1058 71a38edf Sofia Papagiannaki
        extra_context={
1059 71a38edf Sofia Papagiannaki
            'is_search':False,
1060 5550bcfb Kostas Papadimitriou
            'table': table,
1061 3f0d6293 Kostas Papadimitriou
        })
1062 3f0d6293 Kostas Papadimitriou
1063 e1a80257 Sofia Papagiannaki
1064 f3342849 Sofia Papagiannaki
@require_http_methods(["GET", "POST"])
1065 e1a80257 Sofia Papagiannaki
@signed_terms_required
1066 e1a80257 Sofia Papagiannaki
@login_required
1067 73fbaec4 Sofia Papagiannaki
def project_update(request, application_id):
1068 6556e514 Sofia Papagiannaki
    resource_groups = RESOURCES_PRESENTATION_DATA.get('groups', {})
1069 6556e514 Sofia Papagiannaki
    resource_catalog = ()
1070 8327782d Sofia Papagiannaki
    result = callpoint.list_resources()
1071 6556e514 Sofia Papagiannaki
    details_fields = [
1072 6556e514 Sofia Papagiannaki
        "name", "homepage", "description","start_date","end_date", "comments"]
1073 6556e514 Sofia Papagiannaki
    membership_fields =[
1074 3f0d6293 Kostas Papadimitriou
        "member_join_policy", "member_leave_policy", "limit_on_members_number"]
1075 8327782d Sofia Papagiannaki
    if not result.is_success:
1076 8327782d Sofia Papagiannaki
        messages.error(
1077 8327782d Sofia Papagiannaki
            request,
1078 8327782d Sofia Papagiannaki
            'Unable to retrieve system resources: %s' % result.reason
1079 8327782d Sofia Papagiannaki
    )
1080 172ce682 Sofia Papagiannaki
    else:
1081 6556e514 Sofia Papagiannaki
        resource_catalog = [
1082 6556e514 Sofia Papagiannaki
            (g, filter(lambda r: r.get('group', '') == g, result.data)) \
1083 6556e514 Sofia Papagiannaki
                for g in resource_groups]
1084 6556e514 Sofia Papagiannaki
    extra_context = {
1085 6556e514 Sofia Papagiannaki
        'resource_catalog':resource_catalog,
1086 6556e514 Sofia Papagiannaki
        'resource_groups':resource_groups,
1087 6556e514 Sofia Papagiannaki
        'show_form':True,
1088 6556e514 Sofia Papagiannaki
        'details_fields':details_fields,
1089 6003d0a8 Kostas Papadimitriou
        'update_form': True,
1090 6556e514 Sofia Papagiannaki
        'membership_fields':membership_fields}
1091 4e748491 Sofia Papagiannaki
    return _update_object(
1092 f3342849 Sofia Papagiannaki
        request,
1093 73fbaec4 Sofia Papagiannaki
        object_id=application_id,
1094 8327782d Sofia Papagiannaki
        template_name='im/projects/projectapplication_form.html',
1095 37f8b1a6 Olga Brani
        extra_context=extra_context, post_save_redirect=reverse('project_list'),
1096 6556e514 Sofia Papagiannaki
        form_class=ProjectApplicationForm,
1097 6556e514 Sofia Papagiannaki
        msg = _("The %(verbose_name)s has been received and \
1098 6556e514 Sofia Papagiannaki
                    is under consideration."))
1099 17a2f450 Sofia Papagiannaki
1100 e1a80257 Sofia Papagiannaki
1101 e1a80257 Sofia Papagiannaki
@require_http_methods(["GET", "POST"])
1102 e1a80257 Sofia Papagiannaki
@signed_terms_required
1103 e1a80257 Sofia Papagiannaki
@login_required
1104 fcde23e4 Sofia Papagiannaki
@transaction.commit_on_success
1105 73fbaec4 Sofia Papagiannaki
def project_detail(request, application_id):
1106 bfe23b13 Sofia Papagiannaki
    addmembers_form = AddProjectMembersForm()
1107 ccab6eb5 Sofia Papagiannaki
    if request.method == 'POST':
1108 e47fb17a Sofia Papagiannaki
        addmembers_form = AddProjectMembersForm(
1109 e47fb17a Sofia Papagiannaki
            request.POST,
1110 e47fb17a Sofia Papagiannaki
            application_id=int(application_id),
1111 e47fb17a Sofia Papagiannaki
            request_user=request.user)
1112 ccab6eb5 Sofia Papagiannaki
        if addmembers_form.is_valid():
1113 ccab6eb5 Sofia Papagiannaki
            try:
1114 73fbaec4 Sofia Papagiannaki
                rollback = False
1115 7dd3047d Sofia Papagiannaki
                application_id = int(application_id)
1116 7dd3047d Sofia Papagiannaki
                map(lambda u: enroll_member(
1117 73fbaec4 Sofia Papagiannaki
                        application_id,
1118 73fbaec4 Sofia Papagiannaki
                        u,
1119 73fbaec4 Sofia Papagiannaki
                        request_user=request.user),
1120 73fbaec4 Sofia Papagiannaki
                    addmembers_form.valid_users)
1121 73fbaec4 Sofia Papagiannaki
            except (IOError, PermissionDenied), e:
1122 73fbaec4 Sofia Papagiannaki
                messages.error(request, e)
1123 bfe23b13 Sofia Papagiannaki
            except BaseException, e:
1124 73fbaec4 Sofia Papagiannaki
                rollback = True
1125 bfe23b13 Sofia Papagiannaki
                messages.error(request, e)
1126 73fbaec4 Sofia Papagiannaki
            finally:
1127 73fbaec4 Sofia Papagiannaki
                if rollback == True:
1128 73fbaec4 Sofia Papagiannaki
                    transaction.rollback()
1129 73fbaec4 Sofia Papagiannaki
                else:
1130 73fbaec4 Sofia Papagiannaki
                    transaction.commit()
1131 bfe23b13 Sofia Papagiannaki
            addmembers_form = AddProjectMembersForm()
1132 f7cf5257 Kostas Papadimitriou
1133 2ddfc92b Giorgos Korfiatis
    rollback = False
1134 2743e261 Kostas Papadimitriou
1135 2743e261 Kostas Papadimitriou
    application = get_object_or_404(ProjectApplication, pk=application_id)
1136 3f297552 Sofia Papagiannaki
    try:
1137 3f297552 Sofia Papagiannaki
        members = application.project.projectmembership_set.select_related()
1138 3f297552 Sofia Papagiannaki
    except Project.DoesNotExist:
1139 3f297552 Sofia Papagiannaki
        members = ProjectMembership.objects.none()
1140 3f0d6293 Kostas Papadimitriou
1141 3f0d6293 Kostas Papadimitriou
    members_table = tables.ProjectApplicationMembersTable(application,
1142 3f0d6293 Kostas Papadimitriou
                                                          members,
1143 3f0d6293 Kostas Papadimitriou
                                                          user=request.user,
1144 2743e261 Kostas Papadimitriou
                                                          prefix="members_")
1145 e6d284ef Olga Brani
    RequestConfig(request, paginate={"per_page": PAGINATE_BY}).configure(members_table)
1146 2743e261 Kostas Papadimitriou
1147 9b32e2fb Kostas Papadimitriou
    modifications_table = None
1148 9b32e2fb Kostas Papadimitriou
    if application.follower:
1149 9b32e2fb Kostas Papadimitriou
        following_applications = list(application.followers())
1150 9b32e2fb Kostas Papadimitriou
        following_applications.reverse()
1151 9b32e2fb Kostas Papadimitriou
        modifications_table = \
1152 9b32e2fb Kostas Papadimitriou
            tables.ProjectModificationApplicationsTable(following_applications,
1153 9b32e2fb Kostas Papadimitriou
                                                       user=request.user,
1154 9b32e2fb Kostas Papadimitriou
                                                       prefix="modifications_")
1155 9b32e2fb Kostas Papadimitriou
1156 c55e840a Sofia Papagiannaki
    return object_detail(
1157 c55e840a Sofia Papagiannaki
        request,
1158 c55e840a Sofia Papagiannaki
        queryset=ProjectApplication.objects.select_related(),
1159 c55e840a Sofia Papagiannaki
        object_id=application_id,
1160 c55e840a Sofia Papagiannaki
        template_name='im/projects/project_detail.html',
1161 c55e840a Sofia Papagiannaki
        extra_context={
1162 c55e840a Sofia Papagiannaki
            'addmembers_form':addmembers_form,
1163 624f5625 Kostas Papadimitriou
            'members_table': members_table,
1164 db9a498c Kostas Papadimitriou
            'user_owns_project': request.user.owns_project(application),
1165 db9a498c Kostas Papadimitriou
            'modifications_table': modifications_table,
1166 db9a498c Kostas Papadimitriou
            'member_status': application.user_status(request.user)
1167 2743e261 Kostas Papadimitriou
            })
1168 5550bcfb Kostas Papadimitriou
1169 e1a80257 Sofia Papagiannaki
@require_http_methods(["GET", "POST"])
1170 e1a80257 Sofia Papagiannaki
@signed_terms_required
1171 e1a80257 Sofia Papagiannaki
@login_required
1172 e1a80257 Sofia Papagiannaki
def project_search(request):
1173 5550bcfb Kostas Papadimitriou
    q = request.GET.get('q', '')
1174 a5cef8d0 Kostas Papadimitriou
    form = ProjectSearchForm()
1175 a5cef8d0 Kostas Papadimitriou
    q = q.strip()
1176 48421603 Kostas Papadimitriou
1177 a5cef8d0 Kostas Papadimitriou
    if request.method == "POST":
1178 48421603 Kostas Papadimitriou
        form = ProjectSearchForm(request.POST)
1179 48421603 Kostas Papadimitriou
        if form.is_valid():
1180 48421603 Kostas Papadimitriou
            q = form.cleaned_data['q'].strip()
1181 48421603 Kostas Papadimitriou
        else:
1182 a5cef8d0 Kostas Papadimitriou
            q = None
1183 a5cef8d0 Kostas Papadimitriou
1184 a5cef8d0 Kostas Papadimitriou
    if q is None:
1185 a5cef8d0 Kostas Papadimitriou
        projects = ProjectApplication.objects.none()
1186 a5cef8d0 Kostas Papadimitriou
    else:
1187 324fb588 Sofia Papagiannaki
        accepted_projects = request.user.projectmembership_set.filter(
1188 324fb588 Sofia Papagiannaki
            ~Q(acceptance_date__isnull=True)).values_list('project', flat=True)
1189 a5cef8d0 Kostas Papadimitriou
        projects = ProjectApplication.objects.search_by_name(q)
1190 a5cef8d0 Kostas Papadimitriou
        projects = projects.filter(~Q(project__last_approval_date__isnull=True))
1191 324fb588 Sofia Papagiannaki
        projects = projects.exclude(project__in=accepted_projects)
1192 a5cef8d0 Kostas Papadimitriou
1193 2743e261 Kostas Papadimitriou
    table = tables.UserProjectApplicationsTable(projects, user=request.user,
1194 2743e261 Kostas Papadimitriou
                                                prefix="my_projects_")
1195 e6d284ef Olga Brani
    RequestConfig(request, paginate={"per_page": PAGINATE_BY}).configure(table)
1196 48421603 Kostas Papadimitriou
1197 bfe23b13 Sofia Papagiannaki
    return object_list(
1198 bfe23b13 Sofia Papagiannaki
        request,
1199 a5cef8d0 Kostas Papadimitriou
        projects,
1200 6dadd24a Sofia Papagiannaki
        template_name='im/projects/project_list.html',
1201 a5cef8d0 Kostas Papadimitriou
        extra_context={
1202 a5cef8d0 Kostas Papadimitriou
          'form': form,
1203 a5cef8d0 Kostas Papadimitriou
          'is_search': True,
1204 a5cef8d0 Kostas Papadimitriou
          'q': q,
1205 a5cef8d0 Kostas Papadimitriou
          'table': table
1206 a5cef8d0 Kostas Papadimitriou
        })
1207 bfe23b13 Sofia Papagiannaki
1208 db9a498c Kostas Papadimitriou
@require_http_methods(["POST", "GET"])
1209 e1a80257 Sofia Papagiannaki
@signed_terms_required
1210 e1a80257 Sofia Papagiannaki
@login_required
1211 bfe23b13 Sofia Papagiannaki
@transaction.commit_manually
1212 73fbaec4 Sofia Papagiannaki
def project_join(request, application_id):
1213 974ee6a6 Sofia Papagiannaki
    next = request.GET.get('next')
1214 73fbaec4 Sofia Papagiannaki
    if not next:
1215 f807da72 Kostas Papadimitriou
        next = reverse('astakos.im.views.project_detail',
1216 f807da72 Kostas Papadimitriou
                       args=(application_id,))
1217 73fbaec4 Sofia Papagiannaki
1218 bfe23b13 Sofia Papagiannaki
    rollback = False
1219 bfe23b13 Sofia Papagiannaki
    try:
1220 974ee6a6 Sofia Papagiannaki
        application_id = int(application_id)
1221 73fbaec4 Sofia Papagiannaki
        join_project(application_id, request.user)
1222 f807da72 Kostas Papadimitriou
        # TODO: distinct messages for request/auto accept ???
1223 f807da72 Kostas Papadimitriou
        messages.success(request, _(astakos_messages.USER_JOIN_REQUEST_SUBMITED))
1224 73fbaec4 Sofia Papagiannaki
    except (IOError, PermissionDenied), e:
1225 bfe23b13 Sofia Papagiannaki
        messages.error(request, e)
1226 b8f05f8d Sofia Papagiannaki
    except BaseException, e:
1227 b8f05f8d Sofia Papagiannaki
        logger.exception(e)
1228 b8f05f8d Sofia Papagiannaki
        messages.error(request, _(astakos_messages.GENERIC_ERROR))
1229 bfe23b13 Sofia Papagiannaki
        rollback = True
1230 bfe23b13 Sofia Papagiannaki
    finally:
1231 bfe23b13 Sofia Papagiannaki
        if rollback:
1232 bfe23b13 Sofia Papagiannaki
            transaction.rollback()
1233 bfe23b13 Sofia Papagiannaki
        else:
1234 bfe23b13 Sofia Papagiannaki
            transaction.commit()
1235 974ee6a6 Sofia Papagiannaki
    next = restrict_next(next, domain=COOKIE_DOMAIN)
1236 73fbaec4 Sofia Papagiannaki
    return redirect(next)
1237 bfe23b13 Sofia Papagiannaki
1238 73fbaec4 Sofia Papagiannaki
@require_http_methods(["POST"])
1239 e1a80257 Sofia Papagiannaki
@signed_terms_required
1240 e1a80257 Sofia Papagiannaki
@login_required
1241 73fbaec4 Sofia Papagiannaki
@transaction.commit_manually
1242 73fbaec4 Sofia Papagiannaki
def project_leave(request, application_id):
1243 974ee6a6 Sofia Papagiannaki
    next = request.GET.get('next')
1244 73fbaec4 Sofia Papagiannaki
    if not next:
1245 ed1999ad Kostas Papadimitriou
        next = reverse('astakos.im.views.project_list')
1246 e1a80257 Sofia Papagiannaki
1247 73fbaec4 Sofia Papagiannaki
    rollback = False
1248 73fbaec4 Sofia Papagiannaki
    try:
1249 974ee6a6 Sofia Papagiannaki
        application_id = int(application_id)
1250 73fbaec4 Sofia Papagiannaki
        leave_project(application_id, request.user)
1251 73fbaec4 Sofia Papagiannaki
    except (IOError, PermissionDenied), e:
1252 73fbaec4 Sofia Papagiannaki
        messages.error(request, e)
1253 73fbaec4 Sofia Papagiannaki
    except BaseException, e:
1254 73fbaec4 Sofia Papagiannaki
        logger.exception(e)
1255 974ee6a6 Sofia Papagiannaki
        messages.error(request, _(astakos_messages.GENERIC_ERROR))
1256 73fbaec4 Sofia Papagiannaki
        rollback = True
1257 73fbaec4 Sofia Papagiannaki
    finally:
1258 73fbaec4 Sofia Papagiannaki
        if rollback:
1259 73fbaec4 Sofia Papagiannaki
            transaction.rollback()
1260 73fbaec4 Sofia Papagiannaki
        else:
1261 73fbaec4 Sofia Papagiannaki
            transaction.commit()
1262 f7cf5257 Kostas Papadimitriou
1263 974ee6a6 Sofia Papagiannaki
    next = restrict_next(next, domain=COOKIE_DOMAIN)
1264 73fbaec4 Sofia Papagiannaki
    return redirect(next)
1265 bfe23b13 Sofia Papagiannaki
1266 16b22352 Kostas Papadimitriou
@require_http_methods(["POST"])
1267 e1a80257 Sofia Papagiannaki
@signed_terms_required
1268 e1a80257 Sofia Papagiannaki
@login_required
1269 73fbaec4 Sofia Papagiannaki
@transaction.commit_manually
1270 7dd3047d Sofia Papagiannaki
def project_accept_member(request, application_id, user_id):
1271 73fbaec4 Sofia Papagiannaki
    rollback = False
1272 73fbaec4 Sofia Papagiannaki
    try:
1273 974ee6a6 Sofia Papagiannaki
        application_id = int(application_id)
1274 974ee6a6 Sofia Papagiannaki
        user_id = int(user_id)
1275 73fbaec4 Sofia Papagiannaki
        m = accept_membership(application_id, user_id, request.user)
1276 73fbaec4 Sofia Papagiannaki
    except (IOError, PermissionDenied), e:
1277 73fbaec4 Sofia Papagiannaki
        messages.error(request, e)
1278 73fbaec4 Sofia Papagiannaki
    except BaseException, e:
1279 73fbaec4 Sofia Papagiannaki
        logger.exception(e)
1280 974ee6a6 Sofia Papagiannaki
        messages.error(request, _(astakos_messages.GENERIC_ERROR))
1281 73fbaec4 Sofia Papagiannaki
        rollback = True
1282 73fbaec4 Sofia Papagiannaki
    else:
1283 73fbaec4 Sofia Papagiannaki
        realname = m.person.realname
1284 73fbaec4 Sofia Papagiannaki
        msg = _(astakos_messages.USER_JOINED_PROJECT) % locals()
1285 73fbaec4 Sofia Papagiannaki
        messages.success(request, msg)
1286 73fbaec4 Sofia Papagiannaki
    finally:
1287 73fbaec4 Sofia Papagiannaki
        if rollback:
1288 73fbaec4 Sofia Papagiannaki
            transaction.rollback()
1289 73fbaec4 Sofia Papagiannaki
        else:
1290 73fbaec4 Sofia Papagiannaki
            transaction.commit()
1291 7dd3047d Sofia Papagiannaki
    return redirect(reverse('project_detail', args=(application_id,)))
1292 bfe23b13 Sofia Papagiannaki
1293 f3a45fc6 Kostas Papadimitriou
@require_http_methods(["POST"])
1294 bfe23b13 Sofia Papagiannaki
@signed_terms_required
1295 bfe23b13 Sofia Papagiannaki
@login_required
1296 73fbaec4 Sofia Papagiannaki
@transaction.commit_manually
1297 73fbaec4 Sofia Papagiannaki
def project_remove_member(request, application_id, user_id):
1298 73fbaec4 Sofia Papagiannaki
    rollback = False
1299 73fbaec4 Sofia Papagiannaki
    try:
1300 974ee6a6 Sofia Papagiannaki
        application_id = int(application_id)
1301 974ee6a6 Sofia Papagiannaki
        user_id = int(user_id)
1302 73fbaec4 Sofia Papagiannaki
        m = remove_membership(application_id, user_id, request.user)
1303 73fbaec4 Sofia Papagiannaki
    except (IOError, PermissionDenied), e:
1304 73fbaec4 Sofia Papagiannaki
        messages.error(request, e)
1305 73fbaec4 Sofia Papagiannaki
    except BaseException, e:
1306 73fbaec4 Sofia Papagiannaki
        logger.exception(e)
1307 974ee6a6 Sofia Papagiannaki
        messages.error(request, _(astakos_messages.GENERIC_ERROR))
1308 73fbaec4 Sofia Papagiannaki
        rollback = True
1309 73fbaec4 Sofia Papagiannaki
    else:
1310 73fbaec4 Sofia Papagiannaki
        realname = m.person.realname
1311 73fbaec4 Sofia Papagiannaki
        msg = _(astakos_messages.USER_LEFT_PROJECT) % locals()
1312 73fbaec4 Sofia Papagiannaki
        messages.success(request, msg)
1313 73fbaec4 Sofia Papagiannaki
    finally:
1314 73fbaec4 Sofia Papagiannaki
        if rollback:
1315 73fbaec4 Sofia Papagiannaki
            transaction.rollback()
1316 73fbaec4 Sofia Papagiannaki
        else:
1317 73fbaec4 Sofia Papagiannaki
            transaction.commit()
1318 7dd3047d Sofia Papagiannaki
    return redirect(reverse('project_detail', args=(application_id,)))
1319 bfe23b13 Sofia Papagiannaki
1320 f3a45fc6 Kostas Papadimitriou
@require_http_methods(["POST"])
1321 e1a80257 Sofia Papagiannaki
@signed_terms_required
1322 e1a80257 Sofia Papagiannaki
@login_required
1323 73fbaec4 Sofia Papagiannaki
@transaction.commit_manually
1324 73fbaec4 Sofia Papagiannaki
def project_reject_member(request, application_id, user_id):
1325 73fbaec4 Sofia Papagiannaki
    rollback = False
1326 73fbaec4 Sofia Papagiannaki
    try:
1327 974ee6a6 Sofia Papagiannaki
        application_id = int(application_id)
1328 974ee6a6 Sofia Papagiannaki
        user_id = int(user_id)
1329 73fbaec4 Sofia Papagiannaki
        m = reject_membership(application_id, user_id, request.user)
1330 73fbaec4 Sofia Papagiannaki
    except (IOError, PermissionDenied), e:
1331 73fbaec4 Sofia Papagiannaki
        messages.error(request, e)
1332 73fbaec4 Sofia Papagiannaki
    except BaseException, e:
1333 73fbaec4 Sofia Papagiannaki
        logger.exception(e)
1334 974ee6a6 Sofia Papagiannaki
        messages.error(request, _(astakos_messages.GENERIC_ERROR))
1335 73fbaec4 Sofia Papagiannaki
        rollback = True
1336 73fbaec4 Sofia Papagiannaki
    else:
1337 73fbaec4 Sofia Papagiannaki
        realname = m.person.realname
1338 73fbaec4 Sofia Papagiannaki
        msg = _(astakos_messages.USER_LEFT_PROJECT) % locals()
1339 73fbaec4 Sofia Papagiannaki
        messages.success(request, msg)
1340 73fbaec4 Sofia Papagiannaki
    finally:
1341 73fbaec4 Sofia Papagiannaki
        if rollback:
1342 73fbaec4 Sofia Papagiannaki
            transaction.rollback()
1343 73fbaec4 Sofia Papagiannaki
        else:
1344 73fbaec4 Sofia Papagiannaki
            transaction.commit()
1345 7dd3047d Sofia Papagiannaki
    return redirect(reverse('project_detail', args=(application_id,)))
1346 c630fee6 Kostas Papadimitriou