Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / views.py @ fc1e2f02

History | View | Annotate | Download (30.6 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 64cd4730 Antony Chazapis
36 0905ccd2 Sofia Papagiannaki
from urllib import quote
37 63ecdd20 Sofia Papagiannaki
from functools import wraps
38 aab4d540 Sofia Papagiannaki
from datetime import datetime, timedelta
39 64cd4730 Antony Chazapis
40 890b0eaf Sofia Papagiannaki
from django.contrib import messages
41 01ac12d5 Sofia Papagiannaki
from django.contrib.auth.decorators import login_required
42 270dd48d Sofia Papagiannaki
from django.contrib.auth.views import password_change
43 01ac12d5 Sofia Papagiannaki
from django.core.urlresolvers import reverse
44 01ac12d5 Sofia Papagiannaki
from django.db import transaction
45 d1757ca7 Sofia Papagiannaki
from django.db.models import Q
46 01ac12d5 Sofia Papagiannaki
from django.db.utils import IntegrityError
47 01ac12d5 Sofia Papagiannaki
from django.forms.fields import URLField
48 01ac12d5 Sofia Papagiannaki
from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseForbidden, \
49 01ac12d5 Sofia Papagiannaki
    HttpResponseRedirect, HttpResponseBadRequest
50 01ac12d5 Sofia Papagiannaki
from django.shortcuts import redirect
51 aab4d540 Sofia Papagiannaki
from django.template import RequestContext, loader
52 01ac12d5 Sofia Papagiannaki
from django.utils.http import urlencode
53 01ac12d5 Sofia Papagiannaki
from django.utils.translation import ugettext as _
54 aab4d540 Sofia Papagiannaki
from django.views.generic.create_update import (create_object, delete_object,
55 aab4d540 Sofia Papagiannaki
    get_model_and_form_class
56 aab4d540 Sofia Papagiannaki
)
57 aab4d540 Sofia Papagiannaki
from django.views.generic.list_detail import object_list, object_detail
58 64cd4730 Antony Chazapis
59 aab4d540 Sofia Papagiannaki
from astakos.im.models import (AstakosUser, ApprovalTerms, AstakosGroup, Resource,
60 aab4d540 Sofia Papagiannaki
    EmailChange, GroupKind, Membership)
61 4e30244e Sofia Papagiannaki
from astakos.im.activation_backends import get_backend, SimpleBackend
62 1662ac2d Sofia Papagiannaki
from astakos.im.util import get_context, prepare_response, set_cookie, get_query
63 aab4d540 Sofia Papagiannaki
from astakos.im.forms import (LoginForm, InvitationForm, ProfileForm, FeedbackForm,
64 aab4d540 Sofia Papagiannaki
    SignApprovalTermsForm, ExtendedPasswordChangeForm, EmailChangeForm,
65 aab4d540 Sofia Papagiannaki
    AstakosGroupCreationForm, AstakosGroupSearchForm
66 aab4d540 Sofia Papagiannaki
)
67 aab4d540 Sofia Papagiannaki
from astakos.im.functions import (send_feedback, SendMailError,
68 aab4d540 Sofia Papagiannaki
    invite as invite_func, logout as auth_logout, activate as activate_func,
69 3abf6c78 Sofia Papagiannaki
    switch_account_to_shibboleth, send_admin_notification, SendNotificationError
70 aab4d540 Sofia Papagiannaki
)
71 aab4d540 Sofia Papagiannaki
from astakos.im.settings import (COOKIE_NAME, COOKIE_DOMAIN, SITENAME, LOGOUT_NEXT,
72 aab4d540 Sofia Papagiannaki
    LOGGING_LEVEL
73 aab4d540 Sofia Papagiannaki
)
74 64cd4730 Antony Chazapis
75 e015e9e6 Sofia Papagiannaki
logger = logging.getLogger(__name__)
76 e015e9e6 Sofia Papagiannaki
77 c301698f Sofia Papagiannaki
def render_response(template, tab=None, status=200, reset_cookie=False, context_instance=None, **kwargs):
78 890b0eaf Sofia Papagiannaki
    """
79 890b0eaf Sofia Papagiannaki
    Calls ``django.template.loader.render_to_string`` with an additional ``tab``
80 890b0eaf Sofia Papagiannaki
    keyword argument and returns an ``django.http.HttpResponse`` with the
81 890b0eaf Sofia Papagiannaki
    specified ``status``.
82 890b0eaf Sofia Papagiannaki
    """
83 64cd4730 Antony Chazapis
    if tab is None:
84 881c856c Sofia Papagiannaki
        tab = template.partition('_')[0].partition('.html')[0]
85 64cd4730 Antony Chazapis
    kwargs.setdefault('tab', tab)
86 aab4d540 Sofia Papagiannaki
    html = loader.render_to_string(template, kwargs, context_instance=context_instance)
87 c301698f Sofia Papagiannaki
    response = HttpResponse(html, status=status)
88 c301698f Sofia Papagiannaki
    if reset_cookie:
89 c301698f Sofia Papagiannaki
        set_cookie(response, context_instance['request'].user)
90 c301698f Sofia Papagiannaki
    return response
91 64cd4730 Antony Chazapis
92 63ecdd20 Sofia Papagiannaki
93 63ecdd20 Sofia Papagiannaki
def requires_anonymous(func):
94 63ecdd20 Sofia Papagiannaki
    """
95 270dd48d Sofia Papagiannaki
    Decorator checkes whether the request.user is not Anonymous and in that case
96 7482228b Sofia Papagiannaki
    redirects to `logout`.
97 63ecdd20 Sofia Papagiannaki
    """
98 63ecdd20 Sofia Papagiannaki
    @wraps(func)
99 63ecdd20 Sofia Papagiannaki
    def wrapper(request, *args):
100 63ecdd20 Sofia Papagiannaki
        if not request.user.is_anonymous():
101 63ecdd20 Sofia Papagiannaki
            next = urlencode({'next': request.build_absolute_uri()})
102 270dd48d Sofia Papagiannaki
            logout_uri = reverse(logout) + '?' + next
103 270dd48d Sofia Papagiannaki
            return HttpResponseRedirect(logout_uri)
104 63ecdd20 Sofia Papagiannaki
        return func(request, *args)
105 63ecdd20 Sofia Papagiannaki
    return wrapper
106 63ecdd20 Sofia Papagiannaki
107 270dd48d Sofia Papagiannaki
def signed_terms_required(func):
108 270dd48d Sofia Papagiannaki
    """
109 270dd48d Sofia Papagiannaki
    Decorator checkes whether the request.user is Anonymous and in that case
110 270dd48d Sofia Papagiannaki
    redirects to `logout`.
111 270dd48d Sofia Papagiannaki
    """
112 270dd48d Sofia Papagiannaki
    @wraps(func)
113 270dd48d Sofia Papagiannaki
    def wrapper(request, *args, **kwargs):
114 1662ac2d Sofia Papagiannaki
        if request.user.is_authenticated() and not request.user.signed_terms():
115 270dd48d Sofia Papagiannaki
            params = urlencode({'next': request.build_absolute_uri(),
116 270dd48d Sofia Papagiannaki
                              'show_form':''})
117 270dd48d Sofia Papagiannaki
            terms_uri = reverse('latest_terms') + '?' + params
118 270dd48d Sofia Papagiannaki
            return HttpResponseRedirect(terms_uri)
119 270dd48d Sofia Papagiannaki
        return func(request, *args, **kwargs)
120 270dd48d Sofia Papagiannaki
    return wrapper
121 270dd48d Sofia Papagiannaki
122 270dd48d Sofia Papagiannaki
@signed_terms_required
123 aab4d540 Sofia Papagiannaki
def index(request, login_template_name='im/login.html', extra_context=None):
124 890b0eaf Sofia Papagiannaki
    """
125 dcf55476 Sofia Papagiannaki
    If there is logged on user renders the profile page otherwise renders login page.
126 176023aa Kostas Papadimitriou

127 890b0eaf Sofia Papagiannaki
    **Arguments**
128 176023aa Kostas Papadimitriou

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

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

137 890b0eaf Sofia Papagiannaki
    ``extra_context``
138 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
139 176023aa Kostas Papadimitriou

140 890b0eaf Sofia Papagiannaki
    **Template:**
141 176023aa Kostas Papadimitriou

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

144 890b0eaf Sofia Papagiannaki
    """
145 dcf55476 Sofia Papagiannaki
    template_name = login_template_name
146 dcf55476 Sofia Papagiannaki
    if request.user.is_authenticated():
147 6ff7a7ca Sofia Papagiannaki
        return HttpResponseRedirect(reverse('edit_profile'))
148 0905ccd2 Sofia Papagiannaki
    return render_response(template_name,
149 672d445a Sofia Papagiannaki
                           login_form = LoginForm(request=request),
150 0905ccd2 Sofia Papagiannaki
                           context_instance = get_context(request, extra_context))
151 64cd4730 Antony Chazapis
152 890b0eaf Sofia Papagiannaki
@login_required
153 270dd48d Sofia Papagiannaki
@signed_terms_required
154 890b0eaf Sofia Papagiannaki
@transaction.commit_manually
155 aab4d540 Sofia Papagiannaki
def invite(request, template_name='im/invitations.html', extra_context=None):
156 890b0eaf Sofia Papagiannaki
    """
157 890b0eaf Sofia Papagiannaki
    Allows a user to invite somebody else.
158 176023aa Kostas Papadimitriou

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

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

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

168 890b0eaf Sofia Papagiannaki
    **Arguments**
169 176023aa Kostas Papadimitriou

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

174 890b0eaf Sofia Papagiannaki
    ``extra_context``
175 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
176 176023aa Kostas Papadimitriou

177 890b0eaf Sofia Papagiannaki
    **Template:**
178 176023aa Kostas Papadimitriou

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

181 890b0eaf Sofia Papagiannaki
    **Settings:**
182 176023aa Kostas Papadimitriou

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

185 890b0eaf Sofia Papagiannaki
    * LOGIN_URL: login uri
186 2cbaacd5 Sofia Papagiannaki
    * ASTAKOS_DEFAULT_CONTACT_EMAIL: service support email
187 2cbaacd5 Sofia Papagiannaki
    * ASTAKOS_DEFAULT_FROM_EMAIL: from email
188 890b0eaf Sofia Papagiannaki
    """
189 64cd4730 Antony Chazapis
    status = None
190 64cd4730 Antony Chazapis
    message = None
191 8f5a3a06 Sofia Papagiannaki
    form = InvitationForm()
192 5ed6816e Sofia Papagiannaki
    
193 18ffbee1 Sofia Papagiannaki
    inviter = request.user
194 64cd4730 Antony Chazapis
    if request.method == 'POST':
195 8f5a3a06 Sofia Papagiannaki
        form = InvitationForm(request.POST)
196 64cd4730 Antony Chazapis
        if inviter.invitations > 0:
197 8f5a3a06 Sofia Papagiannaki
            if form.is_valid():
198 8f5a3a06 Sofia Papagiannaki
                try:
199 8f5a3a06 Sofia Papagiannaki
                    invitation = form.save()
200 8f5a3a06 Sofia Papagiannaki
                    invite_func(invitation, inviter)
201 8f5a3a06 Sofia Papagiannaki
                    message = _('Invitation sent to %s' % invitation.username)
202 24406ae3 Sofia Papagiannaki
                    messages.success(request, message)
203 8f5a3a06 Sofia Papagiannaki
                except SendMailError, e:
204 8f5a3a06 Sofia Papagiannaki
                    message = e.message
205 24406ae3 Sofia Papagiannaki
                    messages.error(request, message)
206 8f5a3a06 Sofia Papagiannaki
                    transaction.rollback()
207 18ffbee1 Sofia Papagiannaki
                except BaseException, e:
208 18ffbee1 Sofia Papagiannaki
                    message = _('Something went wrong.')
209 24406ae3 Sofia Papagiannaki
                    messages.error(request, message)
210 18ffbee1 Sofia Papagiannaki
                    logger.exception(e)
211 18ffbee1 Sofia Papagiannaki
                    transaction.rollback()
212 18ffbee1 Sofia Papagiannaki
                else:
213 18ffbee1 Sofia Papagiannaki
                    transaction.commit()
214 64cd4730 Antony Chazapis
        else:
215 64cd4730 Antony Chazapis
            message = _('No invitations left')
216 24406ae3 Sofia Papagiannaki
            messages.error(request, message)
217 176023aa Kostas Papadimitriou
218 a196eb7e Sofia Papagiannaki
    sent = [{'email': inv.username,
219 d6ae71a2 root
             'realname': inv.realname,
220 d6ae71a2 root
             'is_consumed': inv.is_consumed}
221 18ffbee1 Sofia Papagiannaki
             for inv in request.user.invitations_sent.all()]
222 77e2ad52 root
    kwargs = {'inviter': inviter,
223 a196eb7e Sofia Papagiannaki
              'sent':sent}
224 0905ccd2 Sofia Papagiannaki
    context = get_context(request, extra_context, **kwargs)
225 0905ccd2 Sofia Papagiannaki
    return render_response(template_name,
226 8f5a3a06 Sofia Papagiannaki
                           invitation_form = form,
227 0905ccd2 Sofia Papagiannaki
                           context_instance = context)
228 64cd4730 Antony Chazapis
229 890b0eaf Sofia Papagiannaki
@login_required
230 270dd48d Sofia Papagiannaki
@signed_terms_required
231 aab4d540 Sofia Papagiannaki
def edit_profile(request, template_name='im/profile.html', extra_context=None):
232 890b0eaf Sofia Papagiannaki
    """
233 890b0eaf Sofia Papagiannaki
    Allows a user to edit his/her profile.
234 176023aa Kostas Papadimitriou

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

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

241 890b0eaf Sofia Papagiannaki
    **Arguments**
242 176023aa Kostas Papadimitriou

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

247 890b0eaf Sofia Papagiannaki
    ``extra_context``
248 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
249 176023aa Kostas Papadimitriou

250 890b0eaf Sofia Papagiannaki
    **Template:**
251 176023aa Kostas Papadimitriou

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

254 92defad4 Sofia Papagiannaki
    **Settings:**
255 176023aa Kostas Papadimitriou

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

258 92defad4 Sofia Papagiannaki
    * LOGIN_URL: login uri
259 890b0eaf Sofia Papagiannaki
    """
260 aab4d540 Sofia Papagiannaki
    extra_context = extra_context or {}
261 15efc749 Sofia Papagiannaki
    form = ProfileForm(instance=request.user)
262 15efc749 Sofia Papagiannaki
    extra_context['next'] = request.GET.get('next')
263 c301698f Sofia Papagiannaki
    reset_cookie = False
264 64cd4730 Antony Chazapis
    if request.method == 'POST':
265 15efc749 Sofia Papagiannaki
        form = ProfileForm(request.POST, instance=request.user)
266 890b0eaf Sofia Papagiannaki
        if form.is_valid():
267 64cd4730 Antony Chazapis
            try:
268 c301698f Sofia Papagiannaki
                prev_token = request.user.auth_token
269 c301698f Sofia Papagiannaki
                user = form.save()
270 c301698f Sofia Papagiannaki
                reset_cookie = user.auth_token != prev_token
271 c301698f Sofia Papagiannaki
                form = ProfileForm(instance=user)
272 1a3675a0 Sofia Papagiannaki
                next = request.POST.get('next')
273 1a3675a0 Sofia Papagiannaki
                if next:
274 1a3675a0 Sofia Papagiannaki
                    return redirect(next)
275 890b0eaf Sofia Papagiannaki
                msg = _('Profile has been updated successfully')
276 24406ae3 Sofia Papagiannaki
                messages.success(request, msg)
277 890b0eaf Sofia Papagiannaki
            except ValueError, ve:
278 24406ae3 Sofia Papagiannaki
                messages.success(request, ve)
279 23447441 Sofia Papagiannaki
    elif request.method == "GET":
280 fff4343a Sofia Papagiannaki
        if not request.user.is_verified:
281 fff4343a Sofia Papagiannaki
            request.user.is_verified = True
282 fff4343a Sofia Papagiannaki
            request.user.save()
283 0905ccd2 Sofia Papagiannaki
    return render_response(template_name,
284 c301698f Sofia Papagiannaki
                           reset_cookie = reset_cookie,
285 8f5a3a06 Sofia Papagiannaki
                           profile_form = form,
286 0905ccd2 Sofia Papagiannaki
                           context_instance = get_context(request,
287 c301698f Sofia Papagiannaki
                                                          extra_context))
288 64cd4730 Antony Chazapis
289 aab4d540 Sofia Papagiannaki
def signup(request, template_name='im/signup.html', on_success='im/signup_complete.html', extra_context=None, backend=None):
290 890b0eaf Sofia Papagiannaki
    """
291 890b0eaf Sofia Papagiannaki
    Allows a user to create a local account.
292 176023aa Kostas Papadimitriou

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

296 890b0eaf Sofia Papagiannaki
    The user activation will be delegated to the backend specified by the ``backend`` keyword argument
297 8f5a3a06 Sofia Papagiannaki
    if present, otherwise to the ``astakos.im.activation_backends.InvitationBackend``
298 8f5a3a06 Sofia Papagiannaki
    if settings.ASTAKOS_INVITATIONS_ENABLED is True or ``astakos.im.activation_backends.SimpleBackend`` if not
299 8f5a3a06 Sofia Papagiannaki
    (see activation_backends);
300 890b0eaf Sofia Papagiannaki
    
301 b669d9c0 Sofia Papagiannaki
    Upon successful user creation, if ``next`` url parameter is present the user is redirected there
302 890b0eaf Sofia Papagiannaki
    otherwise renders the same page with a success message.
303 64cd4730 Antony Chazapis
    
304 8f5a3a06 Sofia Papagiannaki
    On unsuccessful creation, renders ``template_name`` with an error message.
305 890b0eaf Sofia Papagiannaki
    
306 890b0eaf Sofia Papagiannaki
    **Arguments**
307 890b0eaf Sofia Papagiannaki
    
308 8f5a3a06 Sofia Papagiannaki
    ``template_name``
309 8f5a3a06 Sofia Papagiannaki
        A custom template to render. This is optional;
310 1e685275 Sofia Papagiannaki
        if not specified, this will default to ``im/signup.html``.
311 176023aa Kostas Papadimitriou

312 f7e8a159 Sofia Papagiannaki
    ``on_success``
313 f7e8a159 Sofia Papagiannaki
        A custom template to render in case of success. This is optional;
314 1e685275 Sofia Papagiannaki
        if not specified, this will default to ``im/signup_complete.html``.
315 176023aa Kostas Papadimitriou

316 890b0eaf Sofia Papagiannaki
    ``extra_context``
317 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
318 176023aa Kostas Papadimitriou

319 890b0eaf Sofia Papagiannaki
    **Template:**
320 890b0eaf Sofia Papagiannaki
    
321 8f5a3a06 Sofia Papagiannaki
    im/signup.html or ``template_name`` keyword argument.
322 1e685275 Sofia Papagiannaki
    im/signup_complete.html or ``on_success`` keyword argument. 
323 890b0eaf Sofia Papagiannaki
    """
324 0d02a287 Sofia Papagiannaki
    if request.user.is_authenticated():
325 6ff7a7ca Sofia Papagiannaki
        return HttpResponseRedirect(reverse('edit_profile'))
326 4e30244e Sofia Papagiannaki
    
327 0a569195 Sofia Papagiannaki
    provider = get_query(request).get('provider', 'local')
328 890b0eaf Sofia Papagiannaki
    try:
329 18ffbee1 Sofia Papagiannaki
        if not backend:
330 18ffbee1 Sofia Papagiannaki
            backend = get_backend(request)
331 8f5a3a06 Sofia Papagiannaki
        form = backend.get_signup_form(provider)
332 0a569195 Sofia Papagiannaki
    except Exception, e:
333 4e30244e Sofia Papagiannaki
        form = SimpleBackend(request).get_signup_form(provider)
334 24406ae3 Sofia Papagiannaki
        messages.error(request, e)
335 8f5a3a06 Sofia Papagiannaki
    if request.method == 'POST':
336 8f5a3a06 Sofia Papagiannaki
        if form.is_valid():
337 18ffbee1 Sofia Papagiannaki
            user = form.save(commit=False)
338 8f5a3a06 Sofia Papagiannaki
            try:
339 8f5a3a06 Sofia Papagiannaki
                result = backend.handle_activation(user)
340 8f5a3a06 Sofia Papagiannaki
                status = messages.SUCCESS
341 18ffbee1 Sofia Papagiannaki
                message = result.message
342 18ffbee1 Sofia Papagiannaki
                user.save()
343 ca828a10 Sofia Papagiannaki
                if 'additional_email' in form.cleaned_data:
344 ca828a10 Sofia Papagiannaki
                    additional_email = form.cleaned_data['additional_email']
345 ca828a10 Sofia Papagiannaki
                    if additional_email != user.email:
346 ca828a10 Sofia Papagiannaki
                        user.additionalmail_set.create(email=additional_email)
347 b669d9c0 Sofia Papagiannaki
                        msg = 'Additional email: %s saved for user %s.' % (additional_email, user.email)
348 aab4d540 Sofia Papagiannaki
                        logger.log(LOGGING_LEVEL, msg)
349 8f5a3a06 Sofia Papagiannaki
                if user and user.is_active:
350 8f5a3a06 Sofia Papagiannaki
                    next = request.POST.get('next', '')
351 8f5a3a06 Sofia Papagiannaki
                    return prepare_response(request, user, next=next)
352 8f5a3a06 Sofia Papagiannaki
                messages.add_message(request, status, message)
353 8f5a3a06 Sofia Papagiannaki
                return render_response(on_success,
354 8f5a3a06 Sofia Papagiannaki
                                       context_instance=get_context(request, extra_context))
355 18ffbee1 Sofia Papagiannaki
            except SendMailError, e:
356 18ffbee1 Sofia Papagiannaki
                message = e.message
357 24406ae3 Sofia Papagiannaki
                messages.error(request, message)
358 18ffbee1 Sofia Papagiannaki
            except BaseException, e:
359 18ffbee1 Sofia Papagiannaki
                message = _('Something went wrong.')
360 24406ae3 Sofia Papagiannaki
                messages.error(request, message)
361 0a569195 Sofia Papagiannaki
                logger.exception(e)
362 8f5a3a06 Sofia Papagiannaki
    return render_response(template_name,
363 18ffbee1 Sofia Papagiannaki
                           signup_form = form,
364 0a569195 Sofia Papagiannaki
                           provider = provider,
365 890b0eaf Sofia Papagiannaki
                           context_instance=get_context(request, extra_context))
366 64cd4730 Antony Chazapis
367 890b0eaf Sofia Papagiannaki
@login_required
368 270dd48d Sofia Papagiannaki
@signed_terms_required
369 aab4d540 Sofia Papagiannaki
def feedback(request, template_name='im/feedback.html', email_template_name='im/feedback_mail.txt', extra_context=None):
370 890b0eaf Sofia Papagiannaki
    """
371 890b0eaf Sofia Papagiannaki
    Allows a user to send feedback.
372 176023aa Kostas Papadimitriou

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

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

378 890b0eaf Sofia Papagiannaki
    **Arguments**
379 176023aa Kostas Papadimitriou

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

384 890b0eaf Sofia Papagiannaki
    ``extra_context``
385 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
386 176023aa Kostas Papadimitriou

387 890b0eaf Sofia Papagiannaki
    **Template:**
388 176023aa Kostas Papadimitriou

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

391 890b0eaf Sofia Papagiannaki
    **Settings:**
392 176023aa Kostas Papadimitriou

393 92defad4 Sofia Papagiannaki
    * LOGIN_URL: login uri
394 2cbaacd5 Sofia Papagiannaki
    * ASTAKOS_DEFAULT_CONTACT_EMAIL: List of feedback recipients
395 890b0eaf Sofia Papagiannaki
    """
396 64cd4730 Antony Chazapis
    if request.method == 'GET':
397 890b0eaf Sofia Papagiannaki
        form = FeedbackForm()
398 890b0eaf Sofia Papagiannaki
    if request.method == 'POST':
399 890b0eaf Sofia Papagiannaki
        if not request.user:
400 890b0eaf Sofia Papagiannaki
            return HttpResponse('Unauthorized', status=401)
401 176023aa Kostas Papadimitriou
402 890b0eaf Sofia Papagiannaki
        form = FeedbackForm(request.POST)
403 890b0eaf Sofia Papagiannaki
        if form.is_valid():
404 e9083112 Sofia Papagiannaki
            msg = form.cleaned_data['feedback_msg']
405 8f5a3a06 Sofia Papagiannaki
            data = form.cleaned_data['feedback_data']
406 538ccdd5 Sofia Papagiannaki
            try:
407 8f5a3a06 Sofia Papagiannaki
                send_feedback(msg, data, request.user, email_template_name)
408 8f5a3a06 Sofia Papagiannaki
            except SendMailError, e:
409 24406ae3 Sofia Papagiannaki
                messages.error(request, message)
410 8f5a3a06 Sofia Papagiannaki
            else:
411 538ccdd5 Sofia Papagiannaki
                message = _('Feedback successfully sent')
412 aab4d540 Sofia Papagiannaki
                messages.success(request, message)
413 890b0eaf Sofia Papagiannaki
    return render_response(template_name,
414 8f5a3a06 Sofia Papagiannaki
                           feedback_form = form,
415 6b4f9fb2 Sofia Papagiannaki
                           context_instance = get_context(request, extra_context))
416 15efc749 Sofia Papagiannaki
417 8e45d6fd Sofia Papagiannaki
@signed_terms_required
418 aab4d540 Sofia Papagiannaki
def logout(request, template='registration/logged_out.html', extra_context=None):
419 63ecdd20 Sofia Papagiannaki
    """
420 7482228b Sofia Papagiannaki
    Wraps `django.contrib.auth.logout` and delete the cookie.
421 63ecdd20 Sofia Papagiannaki
    """
422 7482228b Sofia Papagiannaki
    response = HttpResponse()
423 8e45d6fd Sofia Papagiannaki
    if request.user.is_authenticated():
424 8e45d6fd Sofia Papagiannaki
        email = request.user.email
425 8e45d6fd Sofia Papagiannaki
        auth_logout(request)
426 8e45d6fd Sofia Papagiannaki
        response.delete_cookie(COOKIE_NAME, path='/', domain=COOKIE_DOMAIN)
427 8e45d6fd Sofia Papagiannaki
        msg = 'Cookie deleted for %s' % email
428 aab4d540 Sofia Papagiannaki
        logger.log(LOGGING_LEVEL, msg)
429 63ecdd20 Sofia Papagiannaki
    next = request.GET.get('next')
430 63ecdd20 Sofia Papagiannaki
    if next:
431 63ecdd20 Sofia Papagiannaki
        response['Location'] = next
432 63ecdd20 Sofia Papagiannaki
        response.status_code = 302
433 63ecdd20 Sofia Papagiannaki
        return response
434 0d02a287 Sofia Papagiannaki
    elif LOGOUT_NEXT:
435 0d02a287 Sofia Papagiannaki
        response['Location'] = LOGOUT_NEXT
436 0d02a287 Sofia Papagiannaki
        response.status_code = 301
437 0d02a287 Sofia Papagiannaki
        return response
438 24406ae3 Sofia Papagiannaki
    messages.success(request, _('You have successfully logged out.'))
439 49df775e Sofia Papagiannaki
    context = get_context(request, extra_context)
440 aab4d540 Sofia Papagiannaki
    response.write(loader.render_to_string(template, context_instance=context))
441 49df775e Sofia Papagiannaki
    return response
442 2126d85d Sofia Papagiannaki
443 683cf244 Sofia Papagiannaki
@transaction.commit_manually
444 3e295388 Sofia Papagiannaki
def activate(request, greeting_email_template_name='im/welcome_email.txt', helpdesk_email_template_name='im/helpdesk_notification.txt'):
445 2126d85d Sofia Papagiannaki
    """
446 683cf244 Sofia Papagiannaki
    Activates the user identified by the ``auth`` request parameter, sends a welcome email
447 683cf244 Sofia Papagiannaki
    and renews the user token.
448 176023aa Kostas Papadimitriou

449 683cf244 Sofia Papagiannaki
    The view uses commit_manually decorator in order to ensure the user state will be updated
450 683cf244 Sofia Papagiannaki
    only if the email will be send successfully.
451 2126d85d Sofia Papagiannaki
    """
452 2126d85d Sofia Papagiannaki
    token = request.GET.get('auth')
453 2126d85d Sofia Papagiannaki
    next = request.GET.get('next')
454 2126d85d Sofia Papagiannaki
    try:
455 2126d85d Sofia Papagiannaki
        user = AstakosUser.objects.get(auth_token=token)
456 2126d85d Sofia Papagiannaki
    except AstakosUser.DoesNotExist:
457 683cf244 Sofia Papagiannaki
        return HttpResponseBadRequest(_('No such user'))
458 0a569195 Sofia Papagiannaki
    
459 d1757ca7 Sofia Papagiannaki
    if user.is_active:
460 23b9b72f Sofia Papagiannaki
        message = _('Account already active.')
461 24406ae3 Sofia Papagiannaki
        messages.error(request, message)
462 23b9b72f Sofia Papagiannaki
        return index(request)
463 8e45d6fd Sofia Papagiannaki
        
464 0a569195 Sofia Papagiannaki
    try:
465 3abf6c78 Sofia Papagiannaki
        local_user = AstakosUser.objects.get(
466 3abf6c78 Sofia Papagiannaki
            ~Q(id = user.id),
467 3abf6c78 Sofia Papagiannaki
            email=user.email,
468 3abf6c78 Sofia Papagiannaki
            is_active=True
469 3abf6c78 Sofia Papagiannaki
        )
470 0a569195 Sofia Papagiannaki
    except AstakosUser.DoesNotExist:
471 27e26a41 Sofia Papagiannaki
        try:
472 3abf6c78 Sofia Papagiannaki
            activate_func(
473 3abf6c78 Sofia Papagiannaki
                user,
474 3abf6c78 Sofia Papagiannaki
                greeting_email_template_name,
475 3abf6c78 Sofia Papagiannaki
                helpdesk_email_template_name,
476 3abf6c78 Sofia Papagiannaki
                verify_email=True
477 3abf6c78 Sofia Papagiannaki
            )
478 23b9b72f Sofia Papagiannaki
            response = prepare_response(request, user, next, renew=True)
479 23b9b72f Sofia Papagiannaki
            transaction.commit()
480 23b9b72f Sofia Papagiannaki
            return response
481 23b9b72f Sofia Papagiannaki
        except SendMailError, e:
482 23b9b72f Sofia Papagiannaki
            message = e.message
483 24406ae3 Sofia Papagiannaki
            messages.error(request, message)
484 23b9b72f Sofia Papagiannaki
            transaction.rollback()
485 23b9b72f Sofia Papagiannaki
            return index(request)
486 23b9b72f Sofia Papagiannaki
        except BaseException, e:
487 23b9b72f Sofia Papagiannaki
            message = _('Something went wrong.')
488 24406ae3 Sofia Papagiannaki
            messages.error(request, message)
489 23b9b72f Sofia Papagiannaki
            logger.exception(e)
490 23b9b72f Sofia Papagiannaki
            transaction.rollback()
491 23b9b72f Sofia Papagiannaki
            return index(request)
492 0a569195 Sofia Papagiannaki
    else:
493 23b9b72f Sofia Papagiannaki
        try:
494 3abf6c78 Sofia Papagiannaki
            user = switch_account_to_shibboleth(
495 3abf6c78 Sofia Papagiannaki
                user,
496 3abf6c78 Sofia Papagiannaki
                local_user,
497 3abf6c78 Sofia Papagiannaki
                greeting_email_template_name
498 3abf6c78 Sofia Papagiannaki
            )
499 23b9b72f Sofia Papagiannaki
            response = prepare_response(request, user, next, renew=True)
500 23b9b72f Sofia Papagiannaki
            transaction.commit()
501 23b9b72f Sofia Papagiannaki
            return response
502 23b9b72f Sofia Papagiannaki
        except SendMailError, e:
503 23b9b72f Sofia Papagiannaki
            message = e.message
504 24406ae3 Sofia Papagiannaki
            messages.error(request, message)
505 23b9b72f Sofia Papagiannaki
            transaction.rollback()
506 23b9b72f Sofia Papagiannaki
            return index(request)
507 23b9b72f Sofia Papagiannaki
        except BaseException, e:
508 23b9b72f Sofia Papagiannaki
            message = _('Something went wrong.')
509 24406ae3 Sofia Papagiannaki
            messages.error(request, message)
510 23b9b72f Sofia Papagiannaki
            logger.exception(e)
511 23b9b72f Sofia Papagiannaki
            transaction.rollback()
512 23b9b72f Sofia Papagiannaki
            return index(request)
513 270dd48d Sofia Papagiannaki
514 aab4d540 Sofia Papagiannaki
def approval_terms(request, term_id=None, template_name='im/approval_terms.html', extra_context=None):
515 270dd48d Sofia Papagiannaki
    term = None
516 270dd48d Sofia Papagiannaki
    terms = None
517 270dd48d Sofia Papagiannaki
    if not term_id:
518 270dd48d Sofia Papagiannaki
        try:
519 270dd48d Sofia Papagiannaki
            term = ApprovalTerms.objects.order_by('-id')[0]
520 270dd48d Sofia Papagiannaki
        except IndexError:
521 270dd48d Sofia Papagiannaki
            pass
522 270dd48d Sofia Papagiannaki
    else:
523 270dd48d Sofia Papagiannaki
        try:
524 aab4d540 Sofia Papagiannaki
            term = ApprovalTerms.objects.get(id=term_id)
525 aab4d540 Sofia Papagiannaki
        except ApprovalTerms.DoesNotExist, e:
526 270dd48d Sofia Papagiannaki
            pass
527 176023aa Kostas Papadimitriou
528 270dd48d Sofia Papagiannaki
    if not term:
529 6ff7a7ca Sofia Papagiannaki
        return HttpResponseRedirect(reverse('index'))
530 270dd48d Sofia Papagiannaki
    f = open(term.location, 'r')
531 270dd48d Sofia Papagiannaki
    terms = f.read()
532 176023aa Kostas Papadimitriou
533 270dd48d Sofia Papagiannaki
    if request.method == 'POST':
534 270dd48d Sofia Papagiannaki
        next = request.POST.get('next')
535 270dd48d Sofia Papagiannaki
        if not next:
536 6ff7a7ca Sofia Papagiannaki
            next = reverse('index')
537 270dd48d Sofia Papagiannaki
        form = SignApprovalTermsForm(request.POST, instance=request.user)
538 270dd48d Sofia Papagiannaki
        if not form.is_valid():
539 270dd48d Sofia Papagiannaki
            return render_response(template_name,
540 270dd48d Sofia Papagiannaki
                           terms = terms,
541 8f5a3a06 Sofia Papagiannaki
                           approval_terms_form = form,
542 270dd48d Sofia Papagiannaki
                           context_instance = get_context(request, extra_context))
543 270dd48d Sofia Papagiannaki
        user = form.save()
544 270dd48d Sofia Papagiannaki
        return HttpResponseRedirect(next)
545 270dd48d Sofia Papagiannaki
    else:
546 586967c0 Sofia Papagiannaki
        form = None
547 1662ac2d Sofia Papagiannaki
        if request.user.is_authenticated() and not request.user.signed_terms():
548 586967c0 Sofia Papagiannaki
            form = SignApprovalTermsForm(instance=request.user)
549 270dd48d Sofia Papagiannaki
        return render_response(template_name,
550 270dd48d Sofia Papagiannaki
                               terms = terms,
551 8f5a3a06 Sofia Papagiannaki
                               approval_terms_form = form,
552 270dd48d Sofia Papagiannaki
                               context_instance = get_context(request, extra_context))
553 270dd48d Sofia Papagiannaki
554 270dd48d Sofia Papagiannaki
@signed_terms_required
555 270dd48d Sofia Papagiannaki
def change_password(request):
556 1039bab1 Sofia Papagiannaki
    return password_change(request,
557 6ff7a7ca Sofia Papagiannaki
                            post_change_redirect=reverse('edit_profile'),
558 1039bab1 Sofia Papagiannaki
                            password_change_form=ExtendedPasswordChangeForm)
559 49790d9d Sofia Papagiannaki
560 8e45d6fd Sofia Papagiannaki
@signed_terms_required
561 8e45d6fd Sofia Papagiannaki
@login_required
562 49790d9d Sofia Papagiannaki
@transaction.commit_manually
563 49790d9d Sofia Papagiannaki
def change_email(request, activation_key=None,
564 49790d9d Sofia Papagiannaki
                 email_template_name='registration/email_change_email.txt',
565 49790d9d Sofia Papagiannaki
                 form_template_name='registration/email_change_form.html',
566 49790d9d Sofia Papagiannaki
                 confirm_template_name='registration/email_change_done.html',
567 aab4d540 Sofia Papagiannaki
                 extra_context=None):
568 49790d9d Sofia Papagiannaki
    if activation_key:
569 49790d9d Sofia Papagiannaki
        try:
570 49790d9d Sofia Papagiannaki
            user = EmailChange.objects.change_email(activation_key)
571 49790d9d Sofia Papagiannaki
            if request.user.is_authenticated() and request.user == user:
572 49790d9d Sofia Papagiannaki
                msg = _('Email changed successfully.')
573 24406ae3 Sofia Papagiannaki
                messages.success(request, msg)
574 49790d9d Sofia Papagiannaki
                auth_logout(request)
575 49790d9d Sofia Papagiannaki
                response = prepare_response(request, user)
576 49790d9d Sofia Papagiannaki
                transaction.commit()
577 49790d9d Sofia Papagiannaki
                return response
578 49790d9d Sofia Papagiannaki
        except ValueError, e:
579 24406ae3 Sofia Papagiannaki
            messages.error(request, e)
580 49790d9d Sofia Papagiannaki
        return render_response(confirm_template_name,
581 49790d9d Sofia Papagiannaki
                               modified_user = user if 'user' in locals() else None,
582 49790d9d Sofia Papagiannaki
                               context_instance = get_context(request,
583 49790d9d Sofia Papagiannaki
                                                              extra_context))
584 49790d9d Sofia Papagiannaki
    
585 49790d9d Sofia Papagiannaki
    if not request.user.is_authenticated():
586 49790d9d Sofia Papagiannaki
        path = quote(request.get_full_path())
587 6ff7a7ca Sofia Papagiannaki
        url = request.build_absolute_uri(reverse('index'))
588 49790d9d Sofia Papagiannaki
        return HttpResponseRedirect(url + '?next=' + path)
589 49790d9d Sofia Papagiannaki
    form = EmailChangeForm(request.POST or None)
590 49790d9d Sofia Papagiannaki
    if request.method == 'POST' and form.is_valid():
591 49790d9d Sofia Papagiannaki
        try:
592 49790d9d Sofia Papagiannaki
            ec = form.save(email_template_name, request)
593 49790d9d Sofia Papagiannaki
        except SendMailError, e:
594 49790d9d Sofia Papagiannaki
            msg = e
595 24406ae3 Sofia Papagiannaki
            messages.error(request, msg)
596 49790d9d Sofia Papagiannaki
            transaction.rollback()
597 49790d9d Sofia Papagiannaki
        except IntegrityError, e:
598 49790d9d Sofia Papagiannaki
            msg = _('There is already a pending change email request.')
599 24406ae3 Sofia Papagiannaki
            messages.error(request, msg)
600 49790d9d Sofia Papagiannaki
        else:
601 49790d9d Sofia Papagiannaki
            msg = _('Change email request has been registered succefully.\
602 49790d9d Sofia Papagiannaki
                    You are going to receive a verification email in the new address.')
603 24406ae3 Sofia Papagiannaki
            messages.success(request, msg)
604 49790d9d Sofia Papagiannaki
            transaction.commit()
605 49790d9d Sofia Papagiannaki
    return render_response(form_template_name,
606 49790d9d Sofia Papagiannaki
                           form = form,
607 49790d9d Sofia Papagiannaki
                           context_instance = get_context(request,
608 8e45d6fd Sofia Papagiannaki
                                                          extra_context))
609 8e45d6fd Sofia Papagiannaki
610 8e45d6fd Sofia Papagiannaki
@signed_terms_required
611 01ac12d5 Sofia Papagiannaki
@login_required
612 0f4fa26d Sofia Papagiannaki
def group_add(request, kind_name='default'):
613 0f4fa26d Sofia Papagiannaki
    try:
614 0f4fa26d Sofia Papagiannaki
        kind = GroupKind.objects.get(name = kind_name)
615 0f4fa26d Sofia Papagiannaki
    except:
616 0f4fa26d Sofia Papagiannaki
        return HttpResponseBadRequest(_('No such group kind'))
617 0f4fa26d Sofia Papagiannaki
    
618 0f4fa26d Sofia Papagiannaki
    template_loader=loader
619 0f4fa26d Sofia Papagiannaki
    post_save_redirect='/im/group/%(id)s/'
620 0f4fa26d Sofia Papagiannaki
    context_processors=None
621 0f4fa26d Sofia Papagiannaki
    model, form_class = get_model_and_form_class(
622 0f4fa26d Sofia Papagiannaki
        model=None,
623 0f4fa26d Sofia Papagiannaki
        form_class=AstakosGroupCreationForm
624 0f4fa26d Sofia Papagiannaki
    )
625 0f4fa26d Sofia Papagiannaki
    resources = dict( (str(r.id), r) for r in Resource.objects.select_related().all() )
626 3abf6c78 Sofia Papagiannaki
    policies = []
627 0f4fa26d Sofia Papagiannaki
    if request.method == 'POST':
628 0f4fa26d Sofia Papagiannaki
        form = form_class(request.POST, request.FILES, resources=resources)
629 0f4fa26d Sofia Papagiannaki
        if form.is_valid():
630 0f4fa26d Sofia Papagiannaki
            new_object = form.save()
631 3abf6c78 Sofia Papagiannaki
            
632 3abf6c78 Sofia Papagiannaki
            # save owner
633 0f4fa26d Sofia Papagiannaki
            new_object.owners = [request.user]
634 3abf6c78 Sofia Papagiannaki
            
635 3abf6c78 Sofia Papagiannaki
            # save quota policies
636 0f4fa26d Sofia Papagiannaki
            for (rid, limit) in form.resources():
637 0f4fa26d Sofia Papagiannaki
                try:
638 0f4fa26d Sofia Papagiannaki
                    r = resources[rid]
639 0f4fa26d Sofia Papagiannaki
                except KeyError, e:
640 0f4fa26d Sofia Papagiannaki
                    logger.exception(e)
641 3abf6c78 Sofia Papagiannaki
                    # TODO Should I stay or should I go???
642 0f4fa26d Sofia Papagiannaki
                    continue
643 0f4fa26d Sofia Papagiannaki
                else:
644 0f4fa26d Sofia Papagiannaki
                    new_object.astakosgroupquota_set.create(
645 0f4fa26d Sofia Papagiannaki
                        resource = r,
646 0f4fa26d Sofia Papagiannaki
                        limit = limit
647 0f4fa26d Sofia Papagiannaki
                    )
648 3abf6c78 Sofia Papagiannaki
                policies.append('%s %d' % (r, limit))
649 0f4fa26d Sofia Papagiannaki
            msg = _("The %(verbose_name)s was created successfully.") %\
650 0f4fa26d Sofia Papagiannaki
                                    {"verbose_name": model._meta.verbose_name}
651 0f4fa26d Sofia Papagiannaki
            messages.success(request, msg, fail_silently=True)
652 3abf6c78 Sofia Papagiannaki
            
653 3abf6c78 Sofia Papagiannaki
            # send notification
654 3abf6c78 Sofia Papagiannaki
            try:
655 3abf6c78 Sofia Papagiannaki
                send_admin_notification(
656 3abf6c78 Sofia Papagiannaki
                    template_name='im/group_creation_notification.txt',
657 3abf6c78 Sofia Papagiannaki
                    dictionary={
658 3abf6c78 Sofia Papagiannaki
                        'group':new_object,
659 3abf6c78 Sofia Papagiannaki
                        'owner':request.user,
660 3abf6c78 Sofia Papagiannaki
                        'policies':policies,
661 3abf6c78 Sofia Papagiannaki
                    },
662 3abf6c78 Sofia Papagiannaki
                    subject='%s alpha2 testing group creation notification' % SITENAME
663 3abf6c78 Sofia Papagiannaki
                )
664 3abf6c78 Sofia Papagiannaki
            except SendNotificationError, e:
665 3abf6c78 Sofia Papagiannaki
                messages.error(request, e, fail_silently=True)
666 aab4d540 Sofia Papagiannaki
            return HttpResponseRedirect(post_save_redirect % new_object.__dict__)
667 0f4fa26d Sofia Papagiannaki
    else:
668 0f4fa26d Sofia Papagiannaki
        now = datetime.now()
669 0f4fa26d Sofia Papagiannaki
        data = {
670 fc1e2f02 Sofia Papagiannaki
            'kind':kind
671 0f4fa26d Sofia Papagiannaki
        }
672 0f4fa26d Sofia Papagiannaki
        form = form_class(data, resources=resources)
673 0f4fa26d Sofia Papagiannaki
674 0f4fa26d Sofia Papagiannaki
    # Create the template, context, response
675 0f4fa26d Sofia Papagiannaki
    template_name = "%s/%s_form.html" % (
676 0f4fa26d Sofia Papagiannaki
        model._meta.app_label,
677 0f4fa26d Sofia Papagiannaki
        model._meta.object_name.lower()
678 0f4fa26d Sofia Papagiannaki
    )
679 0f4fa26d Sofia Papagiannaki
    t = template_loader.get_template(template_name)
680 0f4fa26d Sofia Papagiannaki
    c = RequestContext(request, {
681 0f4fa26d Sofia Papagiannaki
        'form': form
682 0f4fa26d Sofia Papagiannaki
    }, context_processors)
683 0f4fa26d Sofia Papagiannaki
    return HttpResponse(t.render(c))
684 8e45d6fd Sofia Papagiannaki
685 8e45d6fd Sofia Papagiannaki
@signed_terms_required
686 8e45d6fd Sofia Papagiannaki
@login_required
687 ade90760 Sofia Papagiannaki
def group_list(request):
688 0f4fa26d Sofia Papagiannaki
    list = request.user.astakos_groups.select_related().all()
689 8e45d6fd Sofia Papagiannaki
    return object_list(request, queryset=list)
690 8e45d6fd Sofia Papagiannaki
691 8e45d6fd Sofia Papagiannaki
@signed_terms_required
692 8e45d6fd Sofia Papagiannaki
@login_required
693 8e45d6fd Sofia Papagiannaki
def group_detail(request, group_id):
694 8e45d6fd Sofia Papagiannaki
    try:
695 8e45d6fd Sofia Papagiannaki
        group = AstakosGroup.objects.select_related().get(id=group_id)
696 8e45d6fd Sofia Papagiannaki
    except AstakosGroup.DoesNotExist:
697 6ff7a7ca Sofia Papagiannaki
        return HttpResponseBadRequest(_('Invalid group.'))
698 8e45d6fd Sofia Papagiannaki
    return object_detail(request,
699 0f4fa26d Sofia Papagiannaki
         AstakosGroup.objects.all(),
700 0f4fa26d Sofia Papagiannaki
         object_id=group_id,
701 0f4fa26d Sofia Papagiannaki
         extra_context = {'quota':group.quota}
702 0f4fa26d Sofia Papagiannaki
    )
703 8e45d6fd Sofia Papagiannaki
704 8e45d6fd Sofia Papagiannaki
@signed_terms_required
705 01ac12d5 Sofia Papagiannaki
@login_required
706 8e45d6fd Sofia Papagiannaki
def group_approval_request(request, group_id):
707 8e45d6fd Sofia Papagiannaki
    return HttpResponse()
708 01ac12d5 Sofia Papagiannaki
709 01ac12d5 Sofia Papagiannaki
@signed_terms_required
710 01ac12d5 Sofia Papagiannaki
@login_required
711 95a51cdc Sofia Papagiannaki
def group_search(request, extra_context=None, **kwargs):
712 01ac12d5 Sofia Papagiannaki
    if request.method == 'GET':
713 01ac12d5 Sofia Papagiannaki
        form = AstakosGroupSearchForm()
714 01ac12d5 Sofia Papagiannaki
    else:
715 01ac12d5 Sofia Papagiannaki
        form = AstakosGroupSearchForm(get_query(request))
716 01ac12d5 Sofia Papagiannaki
        if form.is_valid():
717 01ac12d5 Sofia Papagiannaki
            q = form.cleaned_data['q'].strip()
718 01ac12d5 Sofia Papagiannaki
            q = URLField().to_python(q)
719 01ac12d5 Sofia Papagiannaki
            queryset = AstakosGroup.objects.select_related().filter(name=q)
720 0f4fa26d Sofia Papagiannaki
            return object_list(
721 0f4fa26d Sofia Papagiannaki
                request,
722 0f4fa26d Sofia Papagiannaki
                queryset,
723 0f4fa26d Sofia Papagiannaki
                template_name='im/astakosgroup_list.html',
724 0f4fa26d Sofia Papagiannaki
                extra_context=dict(
725 0f4fa26d Sofia Papagiannaki
                    form=form,
726 95a51cdc Sofia Papagiannaki
                    is_search=True
727 0f4fa26d Sofia Papagiannaki
                )
728 0f4fa26d Sofia Papagiannaki
            )
729 0f4fa26d Sofia Papagiannaki
    return render_response(
730 0f4fa26d Sofia Papagiannaki
        template='im/astakosgroup_list.html',
731 0f4fa26d Sofia Papagiannaki
        form = form,
732 95a51cdc Sofia Papagiannaki
        context_instance=get_context(request, extra_context)
733 0f4fa26d Sofia Papagiannaki
    )
734 01ac12d5 Sofia Papagiannaki
735 01ac12d5 Sofia Papagiannaki
@signed_terms_required
736 01ac12d5 Sofia Papagiannaki
@login_required
737 01ac12d5 Sofia Papagiannaki
def group_join(request, group_id):
738 95a51cdc Sofia Papagiannaki
    m = Membership(group_id=group_id,
739 95a51cdc Sofia Papagiannaki
        person=request.user,
740 95a51cdc Sofia Papagiannaki
        date_requested=datetime.now()
741 95a51cdc Sofia Papagiannaki
    )
742 95a51cdc Sofia Papagiannaki
    try:
743 95a51cdc Sofia Papagiannaki
        m.save()
744 0f4fa26d Sofia Papagiannaki
        post_save_redirect = reverse(
745 0f4fa26d Sofia Papagiannaki
            'group_detail',
746 0f4fa26d Sofia Papagiannaki
            kwargs=dict(group_id=group_id)
747 0f4fa26d Sofia Papagiannaki
        )
748 95a51cdc Sofia Papagiannaki
        return HttpResponseRedirect(post_save_redirect)
749 95a51cdc Sofia Papagiannaki
    except IntegrityError, e:
750 95a51cdc Sofia Papagiannaki
        logger.exception(e)
751 95a51cdc Sofia Papagiannaki
        msg = _('Failed to join group.')
752 95a51cdc Sofia Papagiannaki
        messages.error(request, msg)
753 95a51cdc Sofia Papagiannaki
        return group_search(request)
754 01ac12d5 Sofia Papagiannaki
755 01ac12d5 Sofia Papagiannaki
@signed_terms_required
756 01ac12d5 Sofia Papagiannaki
@login_required
757 01ac12d5 Sofia Papagiannaki
def group_leave(request, group_id):
758 01ac12d5 Sofia Papagiannaki
    try:
759 0f4fa26d Sofia Papagiannaki
        m = Membership.objects.select_related().get(
760 0f4fa26d Sofia Papagiannaki
            group__id=group_id,
761 0f4fa26d Sofia Papagiannaki
            person=request.user
762 0f4fa26d Sofia Papagiannaki
        )
763 01ac12d5 Sofia Papagiannaki
    except Membership.DoesNotExist:
764 01ac12d5 Sofia Papagiannaki
        return HttpResponseBadRequest(_('Invalid membership.'))
765 01ac12d5 Sofia Papagiannaki
    if request.user in m.group.owner.all():
766 01ac12d5 Sofia Papagiannaki
        return HttpResponseForbidden(_('Owner can not leave the group.'))
767 0f4fa26d Sofia Papagiannaki
    return delete_object(
768 0f4fa26d Sofia Papagiannaki
        request,
769 0f4fa26d Sofia Papagiannaki
        model=Membership,
770 0f4fa26d Sofia Papagiannaki
        object_id = m.id,
771 0f4fa26d Sofia Papagiannaki
        template_name='im/astakosgroup_list.html',
772 0f4fa26d Sofia Papagiannaki
        post_delete_redirect = reverse(
773 0f4fa26d Sofia Papagiannaki
            'group_detail',
774 0f4fa26d Sofia Papagiannaki
            kwargs=dict(group_id=group_id)
775 0f4fa26d Sofia Papagiannaki
        )
776 0f4fa26d Sofia Papagiannaki
    )
777 01ac12d5 Sofia Papagiannaki
778 01ac12d5 Sofia Papagiannaki
def handle_membership():
779 01ac12d5 Sofia Papagiannaki
    def decorator(func):
780 01ac12d5 Sofia Papagiannaki
        @wraps(func)
781 ffb1e7a8 Sofia Papagiannaki
        def wrapper(request, group_id, user_id):
782 01ac12d5 Sofia Papagiannaki
            try:
783 0f4fa26d Sofia Papagiannaki
                m = Membership.objects.select_related().get(
784 0f4fa26d Sofia Papagiannaki
                    group__id=group_id,
785 0f4fa26d Sofia Papagiannaki
                    person__id=user_id
786 0f4fa26d Sofia Papagiannaki
                )
787 01ac12d5 Sofia Papagiannaki
            except Membership.DoesNotExist:
788 01ac12d5 Sofia Papagiannaki
                return HttpResponseBadRequest(_('Invalid membership.'))
789 01ac12d5 Sofia Papagiannaki
            else:
790 01ac12d5 Sofia Papagiannaki
                if request.user not in m.group.owner.all():
791 01ac12d5 Sofia Papagiannaki
                    return HttpResponseForbidden(_('User is not a group owner.'))
792 01ac12d5 Sofia Papagiannaki
                func(request, m)
793 0f4fa26d Sofia Papagiannaki
                return render_response(
794 0f4fa26d Sofia Papagiannaki
                    template='im/astakosgroup_detail.html',
795 0f4fa26d Sofia Papagiannaki
                    context_instance=get_context(request),
796 0f4fa26d Sofia Papagiannaki
                    object=m.group,
797 fc1e2f02 Sofia Papagiannaki
                    quota=m.group.quota
798 0f4fa26d Sofia Papagiannaki
                )
799 01ac12d5 Sofia Papagiannaki
        return wrapper
800 01ac12d5 Sofia Papagiannaki
    return decorator
801 01ac12d5 Sofia Papagiannaki
802 01ac12d5 Sofia Papagiannaki
@signed_terms_required
803 01ac12d5 Sofia Papagiannaki
@login_required
804 01ac12d5 Sofia Papagiannaki
@handle_membership()
805 01ac12d5 Sofia Papagiannaki
def approve_member(request, membership):
806 01ac12d5 Sofia Papagiannaki
    try:
807 01ac12d5 Sofia Papagiannaki
        membership.approve()
808 01ac12d5 Sofia Papagiannaki
        realname = membership.person.realname
809 01ac12d5 Sofia Papagiannaki
        msg = _('%s has been successfully joined the group.' % realname)
810 01ac12d5 Sofia Papagiannaki
        messages.success(request, msg)
811 01ac12d5 Sofia Papagiannaki
    except BaseException, e:
812 01ac12d5 Sofia Papagiannaki
        logger.exception(e)
813 01ac12d5 Sofia Papagiannaki
        msg = _('Something went wrong during %s\'s approval.' % realname)
814 01ac12d5 Sofia Papagiannaki
        messages.error(request, msg)
815 7cb372c7 Sofia Papagiannaki
    
816 01ac12d5 Sofia Papagiannaki
@signed_terms_required
817 01ac12d5 Sofia Papagiannaki
@login_required
818 01ac12d5 Sofia Papagiannaki
@handle_membership()
819 01ac12d5 Sofia Papagiannaki
def disapprove_member(request, membership):
820 01ac12d5 Sofia Papagiannaki
    try:
821 01ac12d5 Sofia Papagiannaki
        membership.disapprove()
822 01ac12d5 Sofia Papagiannaki
        realname = membership.person.realname
823 01ac12d5 Sofia Papagiannaki
        msg = _('%s has been successfully removed from the group.' % realname)
824 01ac12d5 Sofia Papagiannaki
        messages.success(request, msg)
825 01ac12d5 Sofia Papagiannaki
    except BaseException, e:
826 01ac12d5 Sofia Papagiannaki
        logger.exception(e)
827 01ac12d5 Sofia Papagiannaki
        msg = _('Something went wrong during %s\'s disapproval.' % realname)
828 01ac12d5 Sofia Papagiannaki
        messages.error(request, msg)
829 ffb1e7a8 Sofia Papagiannaki
830 ffb1e7a8 Sofia Papagiannaki
@signed_terms_required
831 ffb1e7a8 Sofia Papagiannaki
@login_required
832 ffb1e7a8 Sofia Papagiannaki
def resource_list(request):
833 0f4fa26d Sofia Papagiannaki
    return render_response(
834 0f4fa26d Sofia Papagiannaki
        template='im/astakosuserquota_list.html',
835 0f4fa26d Sofia Papagiannaki
        context_instance=get_context(request),
836 0f4fa26d Sofia Papagiannaki
        quota=request.user.quota
837 0f4fa26d Sofia Papagiannaki
    )