Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / views.py @ 3abf6c78

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

121 890b0eaf Sofia Papagiannaki
    **Arguments**
122 176023aa Kostas Papadimitriou

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

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

131 890b0eaf Sofia Papagiannaki
    ``extra_context``
132 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
133 176023aa Kostas Papadimitriou

134 890b0eaf Sofia Papagiannaki
    **Template:**
135 176023aa Kostas Papadimitriou

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

138 890b0eaf Sofia Papagiannaki
    """
139 dcf55476 Sofia Papagiannaki
    template_name = login_template_name
140 dcf55476 Sofia Papagiannaki
    if request.user.is_authenticated():
141 6ff7a7ca Sofia Papagiannaki
        return HttpResponseRedirect(reverse('edit_profile'))
142 0905ccd2 Sofia Papagiannaki
    return render_response(template_name,
143 672d445a Sofia Papagiannaki
                           login_form = LoginForm(request=request),
144 0905ccd2 Sofia Papagiannaki
                           context_instance = get_context(request, extra_context))
145 64cd4730 Antony Chazapis
146 890b0eaf Sofia Papagiannaki
@login_required
147 270dd48d Sofia Papagiannaki
@signed_terms_required
148 890b0eaf Sofia Papagiannaki
@transaction.commit_manually
149 1e685275 Sofia Papagiannaki
def invite(request, template_name='im/invitations.html', extra_context={}):
150 890b0eaf Sofia Papagiannaki
    """
151 890b0eaf Sofia Papagiannaki
    Allows a user to invite somebody else.
152 176023aa Kostas Papadimitriou

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

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

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

162 890b0eaf Sofia Papagiannaki
    **Arguments**
163 176023aa Kostas Papadimitriou

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

168 890b0eaf Sofia Papagiannaki
    ``extra_context``
169 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
170 176023aa Kostas Papadimitriou

171 890b0eaf Sofia Papagiannaki
    **Template:**
172 176023aa Kostas Papadimitriou

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

175 890b0eaf Sofia Papagiannaki
    **Settings:**
176 176023aa Kostas Papadimitriou

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

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

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

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

235 890b0eaf Sofia Papagiannaki
    **Arguments**
236 176023aa Kostas Papadimitriou

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

241 890b0eaf Sofia Papagiannaki
    ``extra_context``
242 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
243 176023aa Kostas Papadimitriou

244 890b0eaf Sofia Papagiannaki
    **Template:**
245 176023aa Kostas Papadimitriou

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

248 92defad4 Sofia Papagiannaki
    **Settings:**
249 176023aa Kostas Papadimitriou

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

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

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

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

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

309 890b0eaf Sofia Papagiannaki
    ``extra_context``
310 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
311 176023aa Kostas Papadimitriou

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

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

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

371 890b0eaf Sofia Papagiannaki
    **Arguments**
372 176023aa Kostas Papadimitriou

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

377 890b0eaf Sofia Papagiannaki
    ``extra_context``
378 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
379 176023aa Kostas Papadimitriou

380 890b0eaf Sofia Papagiannaki
    **Template:**
381 176023aa Kostas Papadimitriou

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

384 890b0eaf Sofia Papagiannaki
    **Settings:**
385 176023aa Kostas Papadimitriou

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

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