Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / views.py @ 5ce3ce4f

History | View | Annotate | Download (32 kB)

1 aba1e498 Antony Chazapis
# Copyright 2011-2012 GRNET S.A. All rights reserved.
2 176023aa Kostas Papadimitriou
#
3 64cd4730 Antony Chazapis
# Redistribution and use in source and binary forms, with or
4 64cd4730 Antony Chazapis
# without modification, are permitted provided that the following
5 64cd4730 Antony Chazapis
# conditions are met:
6 176023aa Kostas Papadimitriou
#
7 64cd4730 Antony Chazapis
#   1. Redistributions of source code must retain the above
8 64cd4730 Antony Chazapis
#      copyright notice, this list of conditions and the following
9 64cd4730 Antony Chazapis
#      disclaimer.
10 176023aa Kostas Papadimitriou
#
11 64cd4730 Antony Chazapis
#   2. Redistributions in binary form must reproduce the above
12 64cd4730 Antony Chazapis
#      copyright notice, this list of conditions and the following
13 64cd4730 Antony Chazapis
#      disclaimer in the documentation and/or other materials
14 64cd4730 Antony Chazapis
#      provided with the distribution.
15 176023aa Kostas Papadimitriou
#
16 64cd4730 Antony Chazapis
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 64cd4730 Antony Chazapis
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 64cd4730 Antony Chazapis
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 64cd4730 Antony Chazapis
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 64cd4730 Antony Chazapis
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 64cd4730 Antony Chazapis
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 64cd4730 Antony Chazapis
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 64cd4730 Antony Chazapis
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 64cd4730 Antony Chazapis
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 64cd4730 Antony Chazapis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 64cd4730 Antony Chazapis
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 64cd4730 Antony Chazapis
# POSSIBILITY OF SUCH DAMAGE.
28 176023aa Kostas Papadimitriou
#
29 64cd4730 Antony Chazapis
# The views and conclusions contained in the software and
30 64cd4730 Antony Chazapis
# documentation are those of the authors and should not be
31 64cd4730 Antony Chazapis
# interpreted as representing official policies, either expressed
32 64cd4730 Antony Chazapis
# or implied, of GRNET S.A.
33 64cd4730 Antony Chazapis
34 64cd4730 Antony Chazapis
import logging
35 6e029beb Sofia Papagiannaki
import calendar
36 64cd4730 Antony Chazapis
37 0905ccd2 Sofia Papagiannaki
from urllib import quote
38 63ecdd20 Sofia Papagiannaki
from functools import wraps
39 aab4d540 Sofia Papagiannaki
from datetime import datetime, timedelta
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 01ac12d5 Sofia Papagiannaki
from django.core.urlresolvers import reverse
45 01ac12d5 Sofia Papagiannaki
from django.db import transaction
46 d1757ca7 Sofia Papagiannaki
from django.db.models import Q
47 01ac12d5 Sofia Papagiannaki
from django.db.utils import IntegrityError
48 01ac12d5 Sofia Papagiannaki
from django.forms.fields import URLField
49 01ac12d5 Sofia Papagiannaki
from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseForbidden, \
50 01ac12d5 Sofia Papagiannaki
    HttpResponseRedirect, HttpResponseBadRequest
51 01ac12d5 Sofia Papagiannaki
from django.shortcuts import redirect
52 aab4d540 Sofia Papagiannaki
from django.template import RequestContext, loader
53 01ac12d5 Sofia Papagiannaki
from django.utils.http import urlencode
54 01ac12d5 Sofia Papagiannaki
from django.utils.translation import ugettext as _
55 aab4d540 Sofia Papagiannaki
from django.views.generic.create_update import (create_object, delete_object,
56 5ce3ce4f Sofia Papagiannaki
                                                get_model_and_form_class
57 5ce3ce4f Sofia Papagiannaki
                                                )
58 aab4d540 Sofia Papagiannaki
from django.views.generic.list_detail import object_list, object_detail
59 64cd4730 Antony Chazapis
60 5ce3ce4f Sofia Papagiannaki
from astakos.im.models import (
61 5ce3ce4f Sofia Papagiannaki
    AstakosUser, ApprovalTerms, AstakosGroup, Resource,
62 aab4d540 Sofia Papagiannaki
    EmailChange, GroupKind, Membership)
63 4e30244e Sofia Papagiannaki
from astakos.im.activation_backends import get_backend, SimpleBackend
64 1662ac2d Sofia Papagiannaki
from astakos.im.util import get_context, prepare_response, set_cookie, get_query
65 5ce3ce4f Sofia Papagiannaki
from astakos.im.forms import (
66 5ce3ce4f Sofia Papagiannaki
    LoginForm, InvitationForm, ProfileForm, FeedbackForm,
67 aab4d540 Sofia Papagiannaki
    SignApprovalTermsForm, ExtendedPasswordChangeForm, EmailChangeForm,
68 aab4d540 Sofia Papagiannaki
    AstakosGroupCreationForm, AstakosGroupSearchForm
69 aab4d540 Sofia Papagiannaki
)
70 aab4d540 Sofia Papagiannaki
from astakos.im.functions import (send_feedback, SendMailError,
71 5ce3ce4f Sofia Papagiannaki
                                  invite as invite_func, logout as auth_logout, activate as activate_func,
72 5ce3ce4f Sofia Papagiannaki
                                  switch_account_to_shibboleth, send_admin_notification, SendNotificationError
73 5ce3ce4f Sofia Papagiannaki
                                  )
74 5ce3ce4f Sofia Papagiannaki
from astakos.im.settings import (
75 5ce3ce4f Sofia Papagiannaki
    COOKIE_NAME, COOKIE_DOMAIN, SITENAME, LOGOUT_NEXT,
76 aab4d540 Sofia Papagiannaki
    LOGGING_LEVEL
77 aab4d540 Sofia Papagiannaki
)
78 6e029beb Sofia Papagiannaki
from astakos.im.tasks import request_billing
79 64cd4730 Antony Chazapis
80 e015e9e6 Sofia Papagiannaki
logger = logging.getLogger(__name__)
81 e015e9e6 Sofia Papagiannaki
82 5ce3ce4f Sofia Papagiannaki
83 c301698f Sofia Papagiannaki
def render_response(template, tab=None, status=200, reset_cookie=False, context_instance=None, **kwargs):
84 890b0eaf Sofia Papagiannaki
    """
85 890b0eaf Sofia Papagiannaki
    Calls ``django.template.loader.render_to_string`` with an additional ``tab``
86 890b0eaf Sofia Papagiannaki
    keyword argument and returns an ``django.http.HttpResponse`` with the
87 890b0eaf Sofia Papagiannaki
    specified ``status``.
88 890b0eaf Sofia Papagiannaki
    """
89 64cd4730 Antony Chazapis
    if tab is None:
90 881c856c Sofia Papagiannaki
        tab = template.partition('_')[0].partition('.html')[0]
91 64cd4730 Antony Chazapis
    kwargs.setdefault('tab', tab)
92 5ce3ce4f Sofia Papagiannaki
    html = loader.render_to_string(
93 5ce3ce4f Sofia Papagiannaki
        template, kwargs, context_instance=context_instance)
94 c301698f Sofia Papagiannaki
    response = HttpResponse(html, status=status)
95 c301698f Sofia Papagiannaki
    if reset_cookie:
96 c301698f Sofia Papagiannaki
        set_cookie(response, context_instance['request'].user)
97 c301698f Sofia Papagiannaki
    return response
98 64cd4730 Antony Chazapis
99 63ecdd20 Sofia Papagiannaki
100 63ecdd20 Sofia Papagiannaki
def requires_anonymous(func):
101 63ecdd20 Sofia Papagiannaki
    """
102 270dd48d Sofia Papagiannaki
    Decorator checkes whether the request.user is not Anonymous and in that case
103 7482228b Sofia Papagiannaki
    redirects to `logout`.
104 63ecdd20 Sofia Papagiannaki
    """
105 63ecdd20 Sofia Papagiannaki
    @wraps(func)
106 63ecdd20 Sofia Papagiannaki
    def wrapper(request, *args):
107 63ecdd20 Sofia Papagiannaki
        if not request.user.is_anonymous():
108 63ecdd20 Sofia Papagiannaki
            next = urlencode({'next': request.build_absolute_uri()})
109 270dd48d Sofia Papagiannaki
            logout_uri = reverse(logout) + '?' + next
110 270dd48d Sofia Papagiannaki
            return HttpResponseRedirect(logout_uri)
111 63ecdd20 Sofia Papagiannaki
        return func(request, *args)
112 63ecdd20 Sofia Papagiannaki
    return wrapper
113 63ecdd20 Sofia Papagiannaki
114 5ce3ce4f Sofia Papagiannaki
115 270dd48d Sofia Papagiannaki
def signed_terms_required(func):
116 270dd48d Sofia Papagiannaki
    """
117 270dd48d Sofia Papagiannaki
    Decorator checkes whether the request.user is Anonymous and in that case
118 270dd48d Sofia Papagiannaki
    redirects to `logout`.
119 270dd48d Sofia Papagiannaki
    """
120 270dd48d Sofia Papagiannaki
    @wraps(func)
121 270dd48d Sofia Papagiannaki
    def wrapper(request, *args, **kwargs):
122 fcf90160 Sofia Papagiannaki
        if request.user.is_authenticated() and not request.user.signed_terms:
123 270dd48d Sofia Papagiannaki
            params = urlencode({'next': request.build_absolute_uri(),
124 5ce3ce4f Sofia Papagiannaki
                                'show_form': ''})
125 270dd48d Sofia Papagiannaki
            terms_uri = reverse('latest_terms') + '?' + params
126 270dd48d Sofia Papagiannaki
            return HttpResponseRedirect(terms_uri)
127 270dd48d Sofia Papagiannaki
        return func(request, *args, **kwargs)
128 270dd48d Sofia Papagiannaki
    return wrapper
129 270dd48d Sofia Papagiannaki
130 5ce3ce4f Sofia Papagiannaki
131 270dd48d Sofia Papagiannaki
@signed_terms_required
132 aab4d540 Sofia Papagiannaki
def index(request, login_template_name='im/login.html', extra_context=None):
133 890b0eaf Sofia Papagiannaki
    """
134 dcf55476 Sofia Papagiannaki
    If there is logged on user renders the profile page otherwise renders login page.
135 176023aa Kostas Papadimitriou

136 890b0eaf Sofia Papagiannaki
    **Arguments**
137 176023aa Kostas Papadimitriou

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

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

146 890b0eaf Sofia Papagiannaki
    ``extra_context``
147 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
148 176023aa Kostas Papadimitriou

149 890b0eaf Sofia Papagiannaki
    **Template:**
150 176023aa Kostas Papadimitriou

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

153 890b0eaf Sofia Papagiannaki
    """
154 dcf55476 Sofia Papagiannaki
    template_name = login_template_name
155 dcf55476 Sofia Papagiannaki
    if request.user.is_authenticated():
156 6ff7a7ca Sofia Papagiannaki
        return HttpResponseRedirect(reverse('edit_profile'))
157 0905ccd2 Sofia Papagiannaki
    return render_response(template_name,
158 5ce3ce4f Sofia Papagiannaki
                           login_form=LoginForm(request=request),
159 5ce3ce4f Sofia Papagiannaki
                           context_instance=get_context(request, extra_context))
160 5ce3ce4f Sofia Papagiannaki
161 64cd4730 Antony Chazapis
162 890b0eaf Sofia Papagiannaki
@login_required
163 270dd48d Sofia Papagiannaki
@signed_terms_required
164 890b0eaf Sofia Papagiannaki
@transaction.commit_manually
165 aab4d540 Sofia Papagiannaki
def invite(request, template_name='im/invitations.html', extra_context=None):
166 890b0eaf Sofia Papagiannaki
    """
167 890b0eaf Sofia Papagiannaki
    Allows a user to invite somebody else.
168 176023aa Kostas Papadimitriou

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

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

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

178 890b0eaf Sofia Papagiannaki
    **Arguments**
179 176023aa Kostas Papadimitriou

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

184 890b0eaf Sofia Papagiannaki
    ``extra_context``
185 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
186 176023aa Kostas Papadimitriou

187 890b0eaf Sofia Papagiannaki
    **Template:**
188 176023aa Kostas Papadimitriou

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

191 890b0eaf Sofia Papagiannaki
    **Settings:**
192 176023aa Kostas Papadimitriou

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

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

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

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

251 890b0eaf Sofia Papagiannaki
    **Arguments**
252 176023aa Kostas Papadimitriou

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

257 890b0eaf Sofia Papagiannaki
    ``extra_context``
258 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
259 176023aa Kostas Papadimitriou

260 890b0eaf Sofia Papagiannaki
    **Template:**
261 176023aa Kostas Papadimitriou

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

264 92defad4 Sofia Papagiannaki
    **Settings:**
265 176023aa Kostas Papadimitriou

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

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

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

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

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

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

317 890b0eaf Sofia Papagiannaki
    **Arguments**
318 5ce3ce4f Sofia Papagiannaki

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

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

327 890b0eaf Sofia Papagiannaki
    ``extra_context``
328 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
329 176023aa Kostas Papadimitriou

330 890b0eaf Sofia Papagiannaki
    **Template:**
331 5ce3ce4f Sofia Papagiannaki

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

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

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

391 890b0eaf Sofia Papagiannaki
    **Arguments**
392 176023aa Kostas Papadimitriou

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

397 890b0eaf Sofia Papagiannaki
    ``extra_context``
398 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
399 176023aa Kostas Papadimitriou

400 890b0eaf Sofia Papagiannaki
    **Template:**
401 176023aa Kostas Papadimitriou

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

404 890b0eaf Sofia Papagiannaki
    **Settings:**
405 176023aa Kostas Papadimitriou

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

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