Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / views.py @ 88305cf0

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

145 890b0eaf Sofia Papagiannaki
    **Arguments**
146 176023aa Kostas Papadimitriou

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

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

155 890b0eaf Sofia Papagiannaki
    ``extra_context``
156 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
157 176023aa Kostas Papadimitriou

158 890b0eaf Sofia Papagiannaki
    **Template:**
159 176023aa Kostas Papadimitriou

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

162 890b0eaf Sofia Papagiannaki
    """
163 dcf55476 Sofia Papagiannaki
    template_name = login_template_name
164 dcf55476 Sofia Papagiannaki
    if request.user.is_authenticated():
165 6ff7a7ca Sofia Papagiannaki
        return HttpResponseRedirect(reverse('edit_profile'))
166 0905ccd2 Sofia Papagiannaki
    return render_response(template_name,
167 5ce3ce4f Sofia Papagiannaki
                           login_form=LoginForm(request=request),
168 5ce3ce4f Sofia Papagiannaki
                           context_instance=get_context(request, extra_context))
169 5ce3ce4f Sofia Papagiannaki
170 64cd4730 Antony Chazapis
171 890b0eaf Sofia Papagiannaki
@login_required
172 270dd48d Sofia Papagiannaki
@signed_terms_required
173 890b0eaf Sofia Papagiannaki
@transaction.commit_manually
174 aab4d540 Sofia Papagiannaki
def invite(request, template_name='im/invitations.html', extra_context=None):
175 890b0eaf Sofia Papagiannaki
    """
176 890b0eaf Sofia Papagiannaki
    Allows a user to invite somebody else.
177 176023aa Kostas Papadimitriou

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

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

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

187 890b0eaf Sofia Papagiannaki
    **Arguments**
188 176023aa Kostas Papadimitriou

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

193 890b0eaf Sofia Papagiannaki
    ``extra_context``
194 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
195 176023aa Kostas Papadimitriou

196 890b0eaf Sofia Papagiannaki
    **Template:**
197 176023aa Kostas Papadimitriou

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

200 890b0eaf Sofia Papagiannaki
    **Settings:**
201 176023aa Kostas Papadimitriou

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

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

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

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

260 890b0eaf Sofia Papagiannaki
    **Arguments**
261 176023aa Kostas Papadimitriou

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

266 890b0eaf Sofia Papagiannaki
    ``extra_context``
267 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
268 176023aa Kostas Papadimitriou

269 890b0eaf Sofia Papagiannaki
    **Template:**
270 176023aa Kostas Papadimitriou

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

273 92defad4 Sofia Papagiannaki
    **Settings:**
274 176023aa Kostas Papadimitriou

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

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

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

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

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

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

327 890b0eaf Sofia Papagiannaki
    **Arguments**
328 5ce3ce4f Sofia Papagiannaki

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

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

337 890b0eaf Sofia Papagiannaki
    ``extra_context``
338 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
339 176023aa Kostas Papadimitriou

340 890b0eaf Sofia Papagiannaki
    **Template:**
341 5ce3ce4f Sofia Papagiannaki

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

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

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

405 890b0eaf Sofia Papagiannaki
    **Arguments**
406 176023aa Kostas Papadimitriou

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

411 890b0eaf Sofia Papagiannaki
    ``extra_context``
412 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
413 176023aa Kostas Papadimitriou

414 890b0eaf Sofia Papagiannaki
    **Template:**
415 176023aa Kostas Papadimitriou

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

418 890b0eaf Sofia Papagiannaki
    **Settings:**
419 176023aa Kostas Papadimitriou

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

478 683cf244 Sofia Papagiannaki
    The view uses commit_manually decorator in order to ensure the user state will be updated
479 683cf244 Sofia Papagiannaki
    only if the email will be send successfully.
480 2126d85d Sofia Papagiannaki
    """
481 2126d85d Sofia Papagiannaki
    token = request.GET.get('auth')
482 2126d85d Sofia Papagiannaki
    next = request.GET.get('next')
483 2126d85d Sofia Papagiannaki
    try:
484 2126d85d Sofia Papagiannaki
        user = AstakosUser.objects.get(auth_token=token)
485 2126d85d Sofia Papagiannaki
    except AstakosUser.DoesNotExist:
486 683cf244 Sofia Papagiannaki
        return HttpResponseBadRequest(_('No such user'))
487 5ce3ce4f Sofia Papagiannaki
488 d1757ca7 Sofia Papagiannaki
    if user.is_active:
489 23b9b72f Sofia Papagiannaki
        message = _('Account already active.')
490 24406ae3 Sofia Papagiannaki
        messages.error(request, message)
491 23b9b72f Sofia Papagiannaki
        return index(request)
492 5ce3ce4f Sofia Papagiannaki
493 0a569195 Sofia Papagiannaki
    try:
494 3abf6c78 Sofia Papagiannaki
        local_user = AstakosUser.objects.get(
495 5ce3ce4f Sofia Papagiannaki
            ~Q(id=user.id),
496 3abf6c78 Sofia Papagiannaki
            email=user.email,
497 3abf6c78 Sofia Papagiannaki
            is_active=True
498 3abf6c78 Sofia Papagiannaki
        )
499 0a569195 Sofia Papagiannaki
    except AstakosUser.DoesNotExist:
500 27e26a41 Sofia Papagiannaki
        try:
501 3abf6c78 Sofia Papagiannaki
            activate_func(
502 3abf6c78 Sofia Papagiannaki
                user,
503 3abf6c78 Sofia Papagiannaki
                greeting_email_template_name,
504 3abf6c78 Sofia Papagiannaki
                helpdesk_email_template_name,
505 3abf6c78 Sofia Papagiannaki
                verify_email=True
506 3abf6c78 Sofia Papagiannaki
            )
507 23b9b72f Sofia Papagiannaki
            response = prepare_response(request, user, next, renew=True)
508 23b9b72f Sofia Papagiannaki
            transaction.commit()
509 23b9b72f Sofia Papagiannaki
            return response
510 23b9b72f Sofia Papagiannaki
        except SendMailError, e:
511 23b9b72f Sofia Papagiannaki
            message = e.message
512 24406ae3 Sofia Papagiannaki
            messages.error(request, message)
513 23b9b72f Sofia Papagiannaki
            transaction.rollback()
514 23b9b72f Sofia Papagiannaki
            return index(request)
515 23b9b72f Sofia Papagiannaki
        except BaseException, e:
516 23b9b72f Sofia Papagiannaki
            message = _('Something went wrong.')
517 24406ae3 Sofia Papagiannaki
            messages.error(request, message)
518 23b9b72f Sofia Papagiannaki
            logger.exception(e)
519 23b9b72f Sofia Papagiannaki
            transaction.rollback()
520 23b9b72f Sofia Papagiannaki
            return index(request)
521 0a569195 Sofia Papagiannaki
    else:
522 23b9b72f Sofia Papagiannaki
        try:
523 3abf6c78 Sofia Papagiannaki
            user = switch_account_to_shibboleth(
524 3abf6c78 Sofia Papagiannaki
                user,
525 3abf6c78 Sofia Papagiannaki
                local_user,
526 3abf6c78 Sofia Papagiannaki
                greeting_email_template_name
527 3abf6c78 Sofia Papagiannaki
            )
528 23b9b72f Sofia Papagiannaki
            response = prepare_response(request, user, next, renew=True)
529 23b9b72f Sofia Papagiannaki
            transaction.commit()
530 23b9b72f Sofia Papagiannaki
            return response
531 23b9b72f Sofia Papagiannaki
        except SendMailError, e:
532 23b9b72f Sofia Papagiannaki
            message = e.message
533 24406ae3 Sofia Papagiannaki
            messages.error(request, message)
534 23b9b72f Sofia Papagiannaki
            transaction.rollback()
535 23b9b72f Sofia Papagiannaki
            return index(request)
536 23b9b72f Sofia Papagiannaki
        except BaseException, e:
537 23b9b72f Sofia Papagiannaki
            message = _('Something went wrong.')
538 24406ae3 Sofia Papagiannaki
            messages.error(request, message)
539 23b9b72f Sofia Papagiannaki
            logger.exception(e)
540 23b9b72f Sofia Papagiannaki
            transaction.rollback()
541 23b9b72f Sofia Papagiannaki
            return index(request)
542 270dd48d Sofia Papagiannaki
543 5ce3ce4f Sofia Papagiannaki
544 aab4d540 Sofia Papagiannaki
def approval_terms(request, term_id=None, template_name='im/approval_terms.html', extra_context=None):
545 270dd48d Sofia Papagiannaki
    term = None
546 270dd48d Sofia Papagiannaki
    terms = None
547 270dd48d Sofia Papagiannaki
    if not term_id:
548 270dd48d Sofia Papagiannaki
        try:
549 270dd48d Sofia Papagiannaki
            term = ApprovalTerms.objects.order_by('-id')[0]
550 270dd48d Sofia Papagiannaki
        except IndexError:
551 270dd48d Sofia Papagiannaki
            pass
552 270dd48d Sofia Papagiannaki
    else:
553 270dd48d Sofia Papagiannaki
        try:
554 aab4d540 Sofia Papagiannaki
            term = ApprovalTerms.objects.get(id=term_id)
555 aab4d540 Sofia Papagiannaki
        except ApprovalTerms.DoesNotExist, e:
556 270dd48d Sofia Papagiannaki
            pass
557 176023aa Kostas Papadimitriou
558 270dd48d Sofia Papagiannaki
    if not term:
559 6ff7a7ca Sofia Papagiannaki
        return HttpResponseRedirect(reverse('index'))
560 270dd48d Sofia Papagiannaki
    f = open(term.location, 'r')
561 270dd48d Sofia Papagiannaki
    terms = f.read()
562 176023aa Kostas Papadimitriou
563 270dd48d Sofia Papagiannaki
    if request.method == 'POST':
564 270dd48d Sofia Papagiannaki
        next = request.POST.get('next')
565 270dd48d Sofia Papagiannaki
        if not next:
566 6ff7a7ca Sofia Papagiannaki
            next = reverse('index')
567 270dd48d Sofia Papagiannaki
        form = SignApprovalTermsForm(request.POST, instance=request.user)
568 270dd48d Sofia Papagiannaki
        if not form.is_valid():
569 270dd48d Sofia Papagiannaki
            return render_response(template_name,
570 5ce3ce4f Sofia Papagiannaki
                                   terms=terms,
571 5ce3ce4f Sofia Papagiannaki
                                   approval_terms_form=form,
572 5ce3ce4f Sofia Papagiannaki
                                   context_instance=get_context(request, extra_context))
573 270dd48d Sofia Papagiannaki
        user = form.save()
574 270dd48d Sofia Papagiannaki
        return HttpResponseRedirect(next)
575 270dd48d Sofia Papagiannaki
    else:
576 586967c0 Sofia Papagiannaki
        form = None
577 fcf90160 Sofia Papagiannaki
        if request.user.is_authenticated() and not request.user.signed_terms:
578 586967c0 Sofia Papagiannaki
            form = SignApprovalTermsForm(instance=request.user)
579 270dd48d Sofia Papagiannaki
        return render_response(template_name,
580 5ce3ce4f Sofia Papagiannaki
                               terms=terms,
581 5ce3ce4f Sofia Papagiannaki
                               approval_terms_form=form,
582 5ce3ce4f Sofia Papagiannaki
                               context_instance=get_context(request, extra_context))
583 5ce3ce4f Sofia Papagiannaki
584 270dd48d Sofia Papagiannaki
585 270dd48d Sofia Papagiannaki
@signed_terms_required
586 270dd48d Sofia Papagiannaki
def change_password(request):
587 1039bab1 Sofia Papagiannaki
    return password_change(request,
588 5ce3ce4f Sofia Papagiannaki
                           post_change_redirect=reverse('edit_profile'),
589 5ce3ce4f Sofia Papagiannaki
                           password_change_form=ExtendedPasswordChangeForm)
590 5ce3ce4f Sofia Papagiannaki
591 49790d9d Sofia Papagiannaki
592 8e45d6fd Sofia Papagiannaki
@signed_terms_required
593 8e45d6fd Sofia Papagiannaki
@login_required
594 49790d9d Sofia Papagiannaki
@transaction.commit_manually
595 49790d9d Sofia Papagiannaki
def change_email(request, activation_key=None,
596 49790d9d Sofia Papagiannaki
                 email_template_name='registration/email_change_email.txt',
597 49790d9d Sofia Papagiannaki
                 form_template_name='registration/email_change_form.html',
598 49790d9d Sofia Papagiannaki
                 confirm_template_name='registration/email_change_done.html',
599 aab4d540 Sofia Papagiannaki
                 extra_context=None):
600 49790d9d Sofia Papagiannaki
    if activation_key:
601 49790d9d Sofia Papagiannaki
        try:
602 49790d9d Sofia Papagiannaki
            user = EmailChange.objects.change_email(activation_key)
603 49790d9d Sofia Papagiannaki
            if request.user.is_authenticated() and request.user == user:
604 49790d9d Sofia Papagiannaki
                msg = _('Email changed successfully.')
605 24406ae3 Sofia Papagiannaki
                messages.success(request, msg)
606 49790d9d Sofia Papagiannaki
                auth_logout(request)
607 49790d9d Sofia Papagiannaki
                response = prepare_response(request, user)
608 49790d9d Sofia Papagiannaki
                transaction.commit()
609 49790d9d Sofia Papagiannaki
                return response
610 49790d9d Sofia Papagiannaki
        except ValueError, e:
611 24406ae3 Sofia Papagiannaki
            messages.error(request, e)
612 49790d9d Sofia Papagiannaki
        return render_response(confirm_template_name,
613 5ce3ce4f Sofia Papagiannaki
                               modified_user=user if 'user' in locals(
614 5ce3ce4f Sofia Papagiannaki
                               ) else None,
615 5ce3ce4f Sofia Papagiannaki
                               context_instance=get_context(request,
616 5ce3ce4f Sofia Papagiannaki
                                                            extra_context))
617 5ce3ce4f Sofia Papagiannaki
618 49790d9d Sofia Papagiannaki
    if not request.user.is_authenticated():
619 49790d9d Sofia Papagiannaki
        path = quote(request.get_full_path())
620 6ff7a7ca Sofia Papagiannaki
        url = request.build_absolute_uri(reverse('index'))
621 49790d9d Sofia Papagiannaki
        return HttpResponseRedirect(url + '?next=' + path)
622 49790d9d Sofia Papagiannaki
    form = EmailChangeForm(request.POST or None)
623 49790d9d Sofia Papagiannaki
    if request.method == 'POST' and form.is_valid():
624 49790d9d Sofia Papagiannaki
        try:
625 49790d9d Sofia Papagiannaki
            ec = form.save(email_template_name, request)
626 49790d9d Sofia Papagiannaki
        except SendMailError, e:
627 49790d9d Sofia Papagiannaki
            msg = e
628 24406ae3 Sofia Papagiannaki
            messages.error(request, msg)
629 49790d9d Sofia Papagiannaki
            transaction.rollback()
630 49790d9d Sofia Papagiannaki
        except IntegrityError, e:
631 49790d9d Sofia Papagiannaki
            msg = _('There is already a pending change email request.')
632 24406ae3 Sofia Papagiannaki
            messages.error(request, msg)
633 49790d9d Sofia Papagiannaki
        else:
634 49790d9d Sofia Papagiannaki
            msg = _('Change email request has been registered succefully.\
635 49790d9d Sofia Papagiannaki
                    You are going to receive a verification email in the new address.')
636 24406ae3 Sofia Papagiannaki
            messages.success(request, msg)
637 49790d9d Sofia Papagiannaki
            transaction.commit()
638 49790d9d Sofia Papagiannaki
    return render_response(form_template_name,
639 5ce3ce4f Sofia Papagiannaki
                           form=form,
640 5ce3ce4f Sofia Papagiannaki
                           context_instance=get_context(request,
641 5ce3ce4f Sofia Papagiannaki
                                                        extra_context))
642 5ce3ce4f Sofia Papagiannaki
643 8e45d6fd Sofia Papagiannaki
644 8e45d6fd Sofia Papagiannaki
@signed_terms_required
645 01ac12d5 Sofia Papagiannaki
@login_required
646 0f4fa26d Sofia Papagiannaki
def group_add(request, kind_name='default'):
647 0f4fa26d Sofia Papagiannaki
    try:
648 5ce3ce4f Sofia Papagiannaki
        kind = GroupKind.objects.get(name=kind_name)
649 0f4fa26d Sofia Papagiannaki
    except:
650 0f4fa26d Sofia Papagiannaki
        return HttpResponseBadRequest(_('No such group kind'))
651 5ce3ce4f Sofia Papagiannaki
652 5ce3ce4f Sofia Papagiannaki
    template_loader = loader
653 5ce3ce4f Sofia Papagiannaki
    post_save_redirect = '/im/group/%(id)s/'
654 5ce3ce4f Sofia Papagiannaki
    context_processors = None
655 0f4fa26d Sofia Papagiannaki
    model, form_class = get_model_and_form_class(
656 0f4fa26d Sofia Papagiannaki
        model=None,
657 0f4fa26d Sofia Papagiannaki
        form_class=AstakosGroupCreationForm
658 0f4fa26d Sofia Papagiannaki
    )
659 5ce3ce4f Sofia Papagiannaki
    resources = dict(
660 5ce3ce4f Sofia Papagiannaki
        (str(r.id), r) for r in Resource.objects.select_related().all())
661 3abf6c78 Sofia Papagiannaki
    policies = []
662 0f4fa26d Sofia Papagiannaki
    if request.method == 'POST':
663 0f4fa26d Sofia Papagiannaki
        form = form_class(request.POST, request.FILES, resources=resources)
664 0f4fa26d Sofia Papagiannaki
        if form.is_valid():
665 0f4fa26d Sofia Papagiannaki
            new_object = form.save()
666 5ce3ce4f Sofia Papagiannaki
667 3abf6c78 Sofia Papagiannaki
            # save owner
668 0f4fa26d Sofia Papagiannaki
            new_object.owners = [request.user]
669 5ce3ce4f Sofia Papagiannaki
670 3abf6c78 Sofia Papagiannaki
            # save quota policies
671 670de92a Sofia Papagiannaki
            for (rid, uplimit) in form.resources():
672 0f4fa26d Sofia Papagiannaki
                try:
673 0f4fa26d Sofia Papagiannaki
                    r = resources[rid]
674 0f4fa26d Sofia Papagiannaki
                except KeyError, e:
675 0f4fa26d Sofia Papagiannaki
                    logger.exception(e)
676 3abf6c78 Sofia Papagiannaki
                    # TODO Should I stay or should I go???
677 0f4fa26d Sofia Papagiannaki
                    continue
678 0f4fa26d Sofia Papagiannaki
                else:
679 0f4fa26d Sofia Papagiannaki
                    new_object.astakosgroupquota_set.create(
680 5ce3ce4f Sofia Papagiannaki
                        resource=r,
681 670de92a Sofia Papagiannaki
                        uplimit=uplimit
682 0f4fa26d Sofia Papagiannaki
                    )
683 670de92a Sofia Papagiannaki
                policies.append('%s %d' % (r, uplimit))
684 0f4fa26d Sofia Papagiannaki
            msg = _("The %(verbose_name)s was created successfully.") %\
685 5ce3ce4f Sofia Papagiannaki
                {"verbose_name": model._meta.verbose_name}
686 0f4fa26d Sofia Papagiannaki
            messages.success(request, msg, fail_silently=True)
687 5ce3ce4f Sofia Papagiannaki
688 3abf6c78 Sofia Papagiannaki
            # send notification
689 3abf6c78 Sofia Papagiannaki
            try:
690 3abf6c78 Sofia Papagiannaki
                send_admin_notification(
691 3abf6c78 Sofia Papagiannaki
                    template_name='im/group_creation_notification.txt',
692 3abf6c78 Sofia Papagiannaki
                    dictionary={
693 5ce3ce4f Sofia Papagiannaki
                        'group': new_object,
694 5ce3ce4f Sofia Papagiannaki
                        'owner': request.user,
695 5ce3ce4f Sofia Papagiannaki
                        'policies': policies,
696 3abf6c78 Sofia Papagiannaki
                    },
697 3abf6c78 Sofia Papagiannaki
                    subject='%s alpha2 testing group creation notification' % SITENAME
698 3abf6c78 Sofia Papagiannaki
                )
699 3abf6c78 Sofia Papagiannaki
            except SendNotificationError, e:
700 3abf6c78 Sofia Papagiannaki
                messages.error(request, e, fail_silently=True)
701 aab4d540 Sofia Papagiannaki
            return HttpResponseRedirect(post_save_redirect % new_object.__dict__)
702 0f4fa26d Sofia Papagiannaki
    else:
703 0f4fa26d Sofia Papagiannaki
        now = datetime.now()
704 0f4fa26d Sofia Papagiannaki
        data = {
705 5ce3ce4f Sofia Papagiannaki
            'kind': kind
706 0f4fa26d Sofia Papagiannaki
        }
707 0f4fa26d Sofia Papagiannaki
        form = form_class(data, resources=resources)
708 0f4fa26d Sofia Papagiannaki
709 0f4fa26d Sofia Papagiannaki
    # Create the template, context, response
710 0f4fa26d Sofia Papagiannaki
    template_name = "%s/%s_form.html" % (
711 0f4fa26d Sofia Papagiannaki
        model._meta.app_label,
712 0f4fa26d Sofia Papagiannaki
        model._meta.object_name.lower()
713 0f4fa26d Sofia Papagiannaki
    )
714 0f4fa26d Sofia Papagiannaki
    t = template_loader.get_template(template_name)
715 0f4fa26d Sofia Papagiannaki
    c = RequestContext(request, {
716 c8977d75 Olga Brani
        'form': form,
717 c8977d75 Olga Brani
        'kind': kind,
718 0f4fa26d Sofia Papagiannaki
    }, context_processors)
719 0f4fa26d Sofia Papagiannaki
    return HttpResponse(t.render(c))
720 8e45d6fd Sofia Papagiannaki
721 5ce3ce4f Sofia Papagiannaki
722 8e45d6fd Sofia Papagiannaki
@signed_terms_required
723 8e45d6fd Sofia Papagiannaki
@login_required
724 ade90760 Sofia Papagiannaki
def group_list(request):
725 789bcaf9 Sofia Papagiannaki
    none = request.user.astakos_groups.none()
726 789bcaf9 Sofia Papagiannaki
    q = AstakosGroup.objects.raw("""
727 789bcaf9 Sofia Papagiannaki
        SELECT auth_group.id,
728 789bcaf9 Sofia Papagiannaki
        %s AS groupname,
729 789bcaf9 Sofia Papagiannaki
        im_groupkind.name AS kindname,
730 789bcaf9 Sofia Papagiannaki
        im_astakosgroup.*,
731 789bcaf9 Sofia Papagiannaki
        owner.email AS groupowner,
732 789bcaf9 Sofia Papagiannaki
        (SELECT COUNT(*) FROM im_membership
733 789bcaf9 Sofia Papagiannaki
            WHERE group_id = im_astakosgroup.group_ptr_id
734 789bcaf9 Sofia Papagiannaki
            AND date_joined IS NOT NULL) AS approved_members_num,
735 789bcaf9 Sofia Papagiannaki
        (SELECT date_joined FROM im_membership
736 789bcaf9 Sofia Papagiannaki
            WHERE group_id = im_astakosgroup.group_ptr_id
737 789bcaf9 Sofia Papagiannaki
            AND person_id = %s) AS membership_approval_date
738 789bcaf9 Sofia Papagiannaki
        FROM im_astakosgroup
739 789bcaf9 Sofia Papagiannaki
        INNER JOIN im_membership ON (
740 789bcaf9 Sofia Papagiannaki
            im_astakosgroup.group_ptr_id = im_membership.group_id)
741 789bcaf9 Sofia Papagiannaki
        INNER JOIN auth_group ON(im_astakosgroup.group_ptr_id = auth_group.id)
742 789bcaf9 Sofia Papagiannaki
        INNER JOIN im_groupkind ON (im_astakosgroup.kind_id = im_groupkind.id)
743 789bcaf9 Sofia Papagiannaki
        LEFT JOIN im_astakosuser_owner ON (
744 789bcaf9 Sofia Papagiannaki
            im_astakosuser_owner.astakosgroup_id = im_astakosgroup.group_ptr_id)
745 789bcaf9 Sofia Papagiannaki
        LEFT JOIN auth_user as owner ON (
746 789bcaf9 Sofia Papagiannaki
            im_astakosuser_owner.astakosuser_id = owner.id)
747 789bcaf9 Sofia Papagiannaki
        WHERE im_membership.person_id = %s
748 789bcaf9 Sofia Papagiannaki
        """ % (DB_REPLACE_GROUP_SCHEME, request.user.id, request.user.id))
749 789bcaf9 Sofia Papagiannaki
    d = defaultdict(list)
750 789bcaf9 Sofia Papagiannaki
    for g in q:
751 789bcaf9 Sofia Papagiannaki
        if request.user.email == g.groupowner:
752 789bcaf9 Sofia Papagiannaki
            d['own'].append(g)
753 789bcaf9 Sofia Papagiannaki
        else:
754 789bcaf9 Sofia Papagiannaki
            d['other'].append(g)
755 88305cf0 root
    d.setdefault('own', [])
756 88305cf0 root
    d.setdefault('other', [])
757 789bcaf9 Sofia Papagiannaki
    for k, l in d.iteritems():
758 d220292f Sofia Papagiannaki
        page = request.GET.get('%s_page' % k, 1)
759 789bcaf9 Sofia Papagiannaki
        sorting = globals()['%s_sorting' % k] = request.GET.get('%s_sorting' % k)
760 789bcaf9 Sofia Papagiannaki
        if sorting:
761 789bcaf9 Sofia Papagiannaki
            sort_form = AstakosGroupSortForm({'sort_by': sorting})
762 789bcaf9 Sofia Papagiannaki
            if sort_form.is_valid():
763 789bcaf9 Sofia Papagiannaki
                l.sort(key=lambda i: getattr(i, sorting))
764 789bcaf9 Sofia Papagiannaki
                globals()['%s_sorting' % k] = sorting
765 789bcaf9 Sofia Papagiannaki
        paginator = Paginator(l, PAGINATE_BY)
766 789bcaf9 Sofia Papagiannaki
        
767 d220292f Sofia Papagiannaki
        try:
768 d220292f Sofia Papagiannaki
            page_number = int(page)
769 d220292f Sofia Papagiannaki
        except ValueError:
770 d220292f Sofia Papagiannaki
            if page == 'last':
771 d220292f Sofia Papagiannaki
                page_number = paginator.num_pages
772 d220292f Sofia Papagiannaki
            else:
773 d220292f Sofia Papagiannaki
                # Page is not 'last', nor can it be converted to an int.
774 d220292f Sofia Papagiannaki
                raise Http404
775 d220292f Sofia Papagiannaki
        try:
776 789bcaf9 Sofia Papagiannaki
            page_obj = globals()['%s_page_obj' % k] = paginator.page(page_number)
777 d220292f Sofia Papagiannaki
        except InvalidPage:
778 d220292f Sofia Papagiannaki
            raise Http404
779 789bcaf9 Sofia Papagiannaki
    return object_list(request, queryset=none,
780 d220292f Sofia Papagiannaki
                       extra_context={'is_search':False,
781 789bcaf9 Sofia Papagiannaki
                                      'mine': own_page_obj,
782 789bcaf9 Sofia Papagiannaki
                                      'other': other_page_obj,
783 fc9ce5b3 Olga Brani
                                      'own_sorting': own_sorting,
784 789bcaf9 Sofia Papagiannaki
                                      'other_sorting': other_sorting
785 789bcaf9 Sofia Papagiannaki
                                      })
786 5ce3ce4f Sofia Papagiannaki
787 8e45d6fd Sofia Papagiannaki
788 8e45d6fd Sofia Papagiannaki
@signed_terms_required
789 8e45d6fd Sofia Papagiannaki
@login_required
790 8e45d6fd Sofia Papagiannaki
def group_detail(request, group_id):
791 8e45d6fd Sofia Papagiannaki
    try:
792 8e45d6fd Sofia Papagiannaki
        group = AstakosGroup.objects.select_related().get(id=group_id)
793 8e45d6fd Sofia Papagiannaki
    except AstakosGroup.DoesNotExist:
794 6ff7a7ca Sofia Papagiannaki
        return HttpResponseBadRequest(_('Invalid group.'))
795 51c57c9c Sofia Papagiannaki
    form = AstakosGroupUpdateForm(instance=group)
796 a4233484 Sofia Papagiannaki
    search_form = AddGroupMembersForm()
797 8e45d6fd Sofia Papagiannaki
    return object_detail(request,
798 5ce3ce4f Sofia Papagiannaki
                         AstakosGroup.objects.all(),
799 5ce3ce4f Sofia Papagiannaki
                         object_id=group_id,
800 51c57c9c Sofia Papagiannaki
                         extra_context={'quota': group.quota,
801 a4233484 Sofia Papagiannaki
                                        'form': form,
802 a4233484 Sofia Papagiannaki
                                        'search_form': search_form}
803 5ce3ce4f Sofia Papagiannaki
                         )
804 5ce3ce4f Sofia Papagiannaki
805 8e45d6fd Sofia Papagiannaki
806 5c1ad9e3 Sofia Papagiannaki
@signed_terms_required
807 5c1ad9e3 Sofia Papagiannaki
@login_required
808 51c57c9c Sofia Papagiannaki
def group_update(request, group_id):
809 51c57c9c Sofia Papagiannaki
    if request.method != 'POST':
810 51c57c9c Sofia Papagiannaki
        return HttpResponseBadRequest('Method not allowed.')
811 51c57c9c Sofia Papagiannaki
    try:
812 51c57c9c Sofia Papagiannaki
        group = AstakosGroup.objects.select_related().get(id=group_id)
813 51c57c9c Sofia Papagiannaki
    except AstakosGroup.DoesNotExist:
814 51c57c9c Sofia Papagiannaki
        return HttpResponseBadRequest(_('Invalid group.'))
815 51c57c9c Sofia Papagiannaki
    form = AstakosGroupUpdateForm(request.POST, instance=group)
816 51c57c9c Sofia Papagiannaki
    if form.is_valid():
817 51c57c9c Sofia Papagiannaki
        form.save()
818 a4233484 Sofia Papagiannaki
    search_form = AddGroupMembersForm()
819 5c1ad9e3 Sofia Papagiannaki
    return object_detail(request,
820 5c1ad9e3 Sofia Papagiannaki
                         AstakosGroup.objects.all(),
821 5c1ad9e3 Sofia Papagiannaki
                         object_id=group_id,
822 5c1ad9e3 Sofia Papagiannaki
                         extra_context={'quota': group.quota,
823 a4233484 Sofia Papagiannaki
                                        'form': form,
824 a4233484 Sofia Papagiannaki
                                        'search_form': search_form})
825 5ce3ce4f Sofia Papagiannaki
826 01ac12d5 Sofia Papagiannaki
@signed_terms_required
827 01ac12d5 Sofia Papagiannaki
@login_required
828 95a51cdc Sofia Papagiannaki
def group_search(request, extra_context=None, **kwargs):
829 d220292f Sofia Papagiannaki
    q = request.GET.get('q')
830 01ac12d5 Sofia Papagiannaki
    if request.method == 'GET':
831 d220292f Sofia Papagiannaki
        form = AstakosGroupSearchForm({'q': q} if q else None)
832 01ac12d5 Sofia Papagiannaki
    else:
833 01ac12d5 Sofia Papagiannaki
        form = AstakosGroupSearchForm(get_query(request))
834 01ac12d5 Sofia Papagiannaki
        if form.is_valid():
835 01ac12d5 Sofia Papagiannaki
            q = form.cleaned_data['q'].strip()
836 d220292f Sofia Papagiannaki
    if q:
837 789bcaf9 Sofia Papagiannaki
        queryset = AstakosGroup.objects.select_related()
838 789bcaf9 Sofia Papagiannaki
        queryset = queryset.filter(name__contains=q)
839 789bcaf9 Sofia Papagiannaki
        queryset = queryset.filter(approval_date__isnull=False)
840 789bcaf9 Sofia Papagiannaki
        queryset = queryset.extra(select={
841 789bcaf9 Sofia Papagiannaki
                'groupname': DB_REPLACE_GROUP_SCHEME,
842 789bcaf9 Sofia Papagiannaki
                'kindname': "im_groupkind.name",
843 789bcaf9 Sofia Papagiannaki
                'approved_members_num': """
844 789bcaf9 Sofia Papagiannaki
                    SELECT COUNT(*) FROM im_membership
845 789bcaf9 Sofia Papagiannaki
                    WHERE group_id = im_astakosgroup.group_ptr_id
846 789bcaf9 Sofia Papagiannaki
                    AND date_joined IS NOT NULL""",
847 789bcaf9 Sofia Papagiannaki
                'membership_approval_date': """
848 789bcaf9 Sofia Papagiannaki
                    SELECT date_joined FROM im_membership
849 789bcaf9 Sofia Papagiannaki
                    WHERE group_id = im_astakosgroup.group_ptr_id
850 789bcaf9 Sofia Papagiannaki
                    AND person_id = %s""" % request.user.id,
851 789bcaf9 Sofia Papagiannaki
                'is_member': """
852 789bcaf9 Sofia Papagiannaki
                    SELECT CASE WHEN EXISTS(
853 789bcaf9 Sofia Papagiannaki
                    SELECT date_joined FROM im_membership
854 789bcaf9 Sofia Papagiannaki
                    WHERE group_id = im_astakosgroup.group_ptr_id
855 789bcaf9 Sofia Papagiannaki
                    AND person_id = %s)
856 789bcaf9 Sofia Papagiannaki
                    THEN 1 ELSE 0 END""" % request.user.id})
857 d220292f Sofia Papagiannaki
    else:
858 d220292f Sofia Papagiannaki
        queryset = AstakosGroup.objects.none()
859 d220292f Sofia Papagiannaki
    return object_list(
860 d220292f Sofia Papagiannaki
        request,
861 d220292f Sofia Papagiannaki
        queryset,
862 d220292f Sofia Papagiannaki
        paginate_by=PAGINATE_BY,
863 d220292f Sofia Papagiannaki
        page=request.GET.get('page') or 1,
864 d220292f Sofia Papagiannaki
        template_name='im/astakosgroup_list.html',
865 d220292f Sofia Papagiannaki
        extra_context=dict(form=form,
866 d220292f Sofia Papagiannaki
                           is_search=True,
867 d220292f Sofia Papagiannaki
                           q=q))
868 5ce3ce4f Sofia Papagiannaki
869 df67421c Sofia Papagiannaki
@signed_terms_required
870 df67421c Sofia Papagiannaki
@login_required
871 df67421c Sofia Papagiannaki
def group_all(request, extra_context=None, **kwargs):
872 789bcaf9 Sofia Papagiannaki
    q = AstakosGroup.objects.select_related()
873 789bcaf9 Sofia Papagiannaki
    q = q.filter(approval_date__isnull=False)
874 789bcaf9 Sofia Papagiannaki
    q = q.extra(select={
875 789bcaf9 Sofia Papagiannaki
                'groupname': DB_REPLACE_GROUP_SCHEME,
876 789bcaf9 Sofia Papagiannaki
                'kindname': "im_groupkind.name",
877 789bcaf9 Sofia Papagiannaki
                'approved_members_num': """
878 789bcaf9 Sofia Papagiannaki
                    SELECT COUNT(*) FROM im_membership
879 789bcaf9 Sofia Papagiannaki
                    WHERE group_id = im_astakosgroup.group_ptr_id
880 789bcaf9 Sofia Papagiannaki
                    AND date_joined IS NOT NULL""",
881 789bcaf9 Sofia Papagiannaki
                'membership_approval_date': """
882 789bcaf9 Sofia Papagiannaki
                    SELECT date_joined FROM im_membership
883 789bcaf9 Sofia Papagiannaki
                    WHERE group_id = im_astakosgroup.group_ptr_id
884 789bcaf9 Sofia Papagiannaki
                    AND person_id = %s""" % request.user.id,
885 789bcaf9 Sofia Papagiannaki
                'is_member': """
886 789bcaf9 Sofia Papagiannaki
                    SELECT CASE WHEN EXISTS(
887 789bcaf9 Sofia Papagiannaki
                    SELECT date_joined FROM im_membership
888 789bcaf9 Sofia Papagiannaki
                    WHERE group_id = im_astakosgroup.group_ptr_id
889 789bcaf9 Sofia Papagiannaki
                    AND person_id = %s)
890 789bcaf9 Sofia Papagiannaki
                    THEN 1 ELSE 0 END""" % request.user.id})
891 df67421c Sofia Papagiannaki
    return object_list(
892 df67421c Sofia Papagiannaki
                request,
893 789bcaf9 Sofia Papagiannaki
                q,
894 d220292f Sofia Papagiannaki
                paginate_by=PAGINATE_BY,
895 d220292f Sofia Papagiannaki
                page=request.GET.get('page') or 1,
896 df67421c Sofia Papagiannaki
                template_name='im/astakosgroup_list.html',
897 df67421c Sofia Papagiannaki
                extra_context=dict(form=AstakosGroupSearchForm(),
898 df67421c Sofia Papagiannaki
                                   is_search=True))
899 df67421c Sofia Papagiannaki
900 01ac12d5 Sofia Papagiannaki
901 01ac12d5 Sofia Papagiannaki
@signed_terms_required
902 01ac12d5 Sofia Papagiannaki
@login_required
903 01ac12d5 Sofia Papagiannaki
def group_join(request, group_id):
904 95a51cdc Sofia Papagiannaki
    m = Membership(group_id=group_id,
905 5ce3ce4f Sofia Papagiannaki
                   person=request.user,
906 789bcaf9 Sofia Papagiannaki
                   date_requested=datetime.now())
907 95a51cdc Sofia Papagiannaki
    try:
908 95a51cdc Sofia Papagiannaki
        m.save()
909 0f4fa26d Sofia Papagiannaki
        post_save_redirect = reverse(
910 0f4fa26d Sofia Papagiannaki
            'group_detail',
911 789bcaf9 Sofia Papagiannaki
            kwargs=dict(group_id=group_id))
912 95a51cdc Sofia Papagiannaki
        return HttpResponseRedirect(post_save_redirect)
913 95a51cdc Sofia Papagiannaki
    except IntegrityError, e:
914 95a51cdc Sofia Papagiannaki
        logger.exception(e)
915 95a51cdc Sofia Papagiannaki
        msg = _('Failed to join group.')
916 95a51cdc Sofia Papagiannaki
        messages.error(request, msg)
917 95a51cdc Sofia Papagiannaki
        return group_search(request)
918 01ac12d5 Sofia Papagiannaki
919 5ce3ce4f Sofia Papagiannaki
920 01ac12d5 Sofia Papagiannaki
@signed_terms_required
921 01ac12d5 Sofia Papagiannaki
@login_required
922 01ac12d5 Sofia Papagiannaki
def group_leave(request, group_id):
923 01ac12d5 Sofia Papagiannaki
    try:
924 0f4fa26d Sofia Papagiannaki
        m = Membership.objects.select_related().get(
925 0f4fa26d Sofia Papagiannaki
            group__id=group_id,
926 0f4fa26d Sofia Papagiannaki
            person=request.user
927 0f4fa26d Sofia Papagiannaki
        )
928 01ac12d5 Sofia Papagiannaki
    except Membership.DoesNotExist:
929 01ac12d5 Sofia Papagiannaki
        return HttpResponseBadRequest(_('Invalid membership.'))
930 01ac12d5 Sofia Papagiannaki
    if request.user in m.group.owner.all():
931 01ac12d5 Sofia Papagiannaki
        return HttpResponseForbidden(_('Owner can not leave the group.'))
932 0f4fa26d Sofia Papagiannaki
    return delete_object(
933 0f4fa26d Sofia Papagiannaki
        request,
934 0f4fa26d Sofia Papagiannaki
        model=Membership,
935 5ce3ce4f Sofia Papagiannaki
        object_id=m.id,
936 0f4fa26d Sofia Papagiannaki
        template_name='im/astakosgroup_list.html',
937 5ce3ce4f Sofia Papagiannaki
        post_delete_redirect=reverse(
938 0f4fa26d Sofia Papagiannaki
            'group_detail',
939 0f4fa26d Sofia Papagiannaki
            kwargs=dict(group_id=group_id)
940 0f4fa26d Sofia Papagiannaki
        )
941 0f4fa26d Sofia Papagiannaki
    )
942 01ac12d5 Sofia Papagiannaki
943 5ce3ce4f Sofia Papagiannaki
944 1eaeb5b6 Sofia Papagiannaki
def handle_membership(func):
945 1eaeb5b6 Sofia Papagiannaki
    @wraps(func)
946 1eaeb5b6 Sofia Papagiannaki
    def wrapper(request, group_id, user_id):
947 1eaeb5b6 Sofia Papagiannaki
        try:
948 1eaeb5b6 Sofia Papagiannaki
            m = Membership.objects.select_related().get(
949 1eaeb5b6 Sofia Papagiannaki
                group__id=group_id,
950 1eaeb5b6 Sofia Papagiannaki
                person__id=user_id
951 1eaeb5b6 Sofia Papagiannaki
            )
952 1eaeb5b6 Sofia Papagiannaki
        except Membership.DoesNotExist:
953 1eaeb5b6 Sofia Papagiannaki
            return HttpResponseBadRequest(_('Invalid membership.'))
954 1eaeb5b6 Sofia Papagiannaki
        else:
955 1eaeb5b6 Sofia Papagiannaki
            if request.user not in m.group.owner.all():
956 1eaeb5b6 Sofia Papagiannaki
                return HttpResponseForbidden(_('User is not a group owner.'))
957 1eaeb5b6 Sofia Papagiannaki
            func(request, m)
958 1eaeb5b6 Sofia Papagiannaki
            return render_response(
959 1eaeb5b6 Sofia Papagiannaki
                template='im/astakosgroup_detail.html',
960 1eaeb5b6 Sofia Papagiannaki
                context_instance=get_context(request),
961 1eaeb5b6 Sofia Papagiannaki
                object=m.group,
962 1eaeb5b6 Sofia Papagiannaki
                quota=m.group.quota
963 1eaeb5b6 Sofia Papagiannaki
            )
964 1eaeb5b6 Sofia Papagiannaki
    return wrapper
965 01ac12d5 Sofia Papagiannaki
966 5ce3ce4f Sofia Papagiannaki
967 01ac12d5 Sofia Papagiannaki
@signed_terms_required
968 01ac12d5 Sofia Papagiannaki
@login_required
969 1eaeb5b6 Sofia Papagiannaki
@handle_membership
970 01ac12d5 Sofia Papagiannaki
def approve_member(request, membership):
971 01ac12d5 Sofia Papagiannaki
    try:
972 01ac12d5 Sofia Papagiannaki
        membership.approve()
973 01ac12d5 Sofia Papagiannaki
        realname = membership.person.realname
974 01ac12d5 Sofia Papagiannaki
        msg = _('%s has been successfully joined the group.' % realname)
975 01ac12d5 Sofia Papagiannaki
        messages.success(request, msg)
976 01ac12d5 Sofia Papagiannaki
    except BaseException, e:
977 01ac12d5 Sofia Papagiannaki
        logger.exception(e)
978 01ac12d5 Sofia Papagiannaki
        msg = _('Something went wrong during %s\'s approval.' % realname)
979 01ac12d5 Sofia Papagiannaki
        messages.error(request, msg)
980 5ce3ce4f Sofia Papagiannaki
981 5ce3ce4f Sofia Papagiannaki
982 01ac12d5 Sofia Papagiannaki
@signed_terms_required
983 01ac12d5 Sofia Papagiannaki
@login_required
984 1eaeb5b6 Sofia Papagiannaki
@handle_membership
985 01ac12d5 Sofia Papagiannaki
def disapprove_member(request, membership):
986 01ac12d5 Sofia Papagiannaki
    try:
987 01ac12d5 Sofia Papagiannaki
        membership.disapprove()
988 01ac12d5 Sofia Papagiannaki
        realname = membership.person.realname
989 01ac12d5 Sofia Papagiannaki
        msg = _('%s has been successfully removed from the group.' % realname)
990 01ac12d5 Sofia Papagiannaki
        messages.success(request, msg)
991 01ac12d5 Sofia Papagiannaki
    except BaseException, e:
992 01ac12d5 Sofia Papagiannaki
        logger.exception(e)
993 01ac12d5 Sofia Papagiannaki
        msg = _('Something went wrong during %s\'s disapproval.' % realname)
994 01ac12d5 Sofia Papagiannaki
        messages.error(request, msg)
995 ffb1e7a8 Sofia Papagiannaki
996 5ce3ce4f Sofia Papagiannaki
997 a4233484 Sofia Papagiannaki
998 a4233484 Sofia Papagiannaki
999 a4233484 Sofia Papagiannaki
@signed_terms_required
1000 a4233484 Sofia Papagiannaki
@login_required
1001 a4233484 Sofia Papagiannaki
def add_members(request, group_id):
1002 a4233484 Sofia Papagiannaki
    if request.method != 'POST':
1003 a4233484 Sofia Papagiannaki
        return HttpResponseBadRequest(_('Bad method'))
1004 a4233484 Sofia Papagiannaki
    try:
1005 a4233484 Sofia Papagiannaki
        group = AstakosGroup.objects.select_related().get(id=group_id)
1006 a4233484 Sofia Papagiannaki
    except AstakosGroup.DoesNotExist:
1007 a4233484 Sofia Papagiannaki
        return HttpResponseBadRequest(_('Invalid group.'))
1008 a4233484 Sofia Papagiannaki
    search_form = AddGroupMembersForm(request.POST)
1009 a4233484 Sofia Papagiannaki
    if search_form.is_valid():
1010 a4233484 Sofia Papagiannaki
        users = search_form.get_valid_users()
1011 a4233484 Sofia Papagiannaki
        map(group.approve_member, users)
1012 a4233484 Sofia Papagiannaki
        search_form = AddGroupMembersForm()
1013 a4233484 Sofia Papagiannaki
    form = AstakosGroupUpdateForm(instance=group)
1014 a4233484 Sofia Papagiannaki
    return object_detail(request,
1015 a4233484 Sofia Papagiannaki
                         AstakosGroup.objects.all(),
1016 a4233484 Sofia Papagiannaki
                         object_id=group_id,
1017 a4233484 Sofia Papagiannaki
                         extra_context={'quota': group.quota,
1018 a4233484 Sofia Papagiannaki
                                        'form': form,
1019 789bcaf9 Sofia Papagiannaki
                                        'search_form' : search_form})
1020 a4233484 Sofia Papagiannaki
1021 a4233484 Sofia Papagiannaki
1022 ffb1e7a8 Sofia Papagiannaki
@signed_terms_required
1023 ffb1e7a8 Sofia Papagiannaki
@login_required
1024 ffb1e7a8 Sofia Papagiannaki
def resource_list(request):
1025 0f4fa26d Sofia Papagiannaki
    return render_response(
1026 0f4fa26d Sofia Papagiannaki
        template='im/astakosuserquota_list.html',
1027 0f4fa26d Sofia Papagiannaki
        context_instance=get_context(request),
1028 0f4fa26d Sofia Papagiannaki
        quota=request.user.quota
1029 4b7d68f0 Olga Brani
    )
1030 5ce3ce4f Sofia Papagiannaki
1031 5ce3ce4f Sofia Papagiannaki
1032 4b7d68f0 Olga Brani
def group_create_list(request):
1033 4b7d68f0 Olga Brani
    return render_response(
1034 4b7d68f0 Olga Brani
        template='im/astakosgroup_create_list.html',
1035 4b7d68f0 Olga Brani
        context_instance=get_context(request),
1036 6e029beb Sofia Papagiannaki
    )
1037 6e029beb Sofia Papagiannaki
1038 5ce3ce4f Sofia Papagiannaki
1039 6e029beb Sofia Papagiannaki
@signed_terms_required
1040 6e029beb Sofia Papagiannaki
@login_required
1041 6e029beb Sofia Papagiannaki
def billing(request):
1042 5056da3d Olga Brani
    
1043 6e029beb Sofia Papagiannaki
    today = datetime.today()
1044 5056da3d Olga Brani
    month_last_day= calendar.monthrange(today.year, today.month)[1]
1045 5056da3d Olga Brani
    
1046 5056da3d Olga Brani
    start = request.POST.get('datefrom', None)
1047 5056da3d Olga Brani
    if start:
1048 5056da3d Olga Brani
        today = datetime.fromtimestamp(int(start))
1049 5056da3d Olga Brani
        month_last_day= calendar.monthrange(today.year, today.month)[1]
1050 5056da3d Olga Brani
    
1051 6e029beb Sofia Papagiannaki
    start = datetime(today.year, today.month, 1).strftime("%s")
1052 6e029beb Sofia Papagiannaki
    end = datetime(today.year, today.month, month_last_day).strftime("%s")
1053 4de59eac Olga Brani
    r = request_billing.apply(args=('pgerakios@grnet.gr',
1054 5ce3ce4f Sofia Papagiannaki
                                    int(start) * 1000,
1055 5056da3d Olga Brani
                                    int(end) * 1000))
1056 5056da3d Olga Brani
    data = {}
1057 5056da3d Olga Brani
    
1058 6e029beb Sofia Papagiannaki
    try:
1059 6e029beb Sofia Papagiannaki
        status, data = r.result
1060 5056da3d Olga Brani
        data=clear_billing_data(data)
1061 6e029beb Sofia Papagiannaki
        if status != 200:
1062 6e029beb Sofia Papagiannaki
            messages.error(request, _('Service response status: %d' % status))
1063 6e029beb Sofia Papagiannaki
    except:
1064 6e029beb Sofia Papagiannaki
        messages.error(request, r.result)
1065 5056da3d Olga Brani
    
1066 5056da3d Olga Brani
    print type(start)
1067 5056da3d Olga Brani
    
1068 6e029beb Sofia Papagiannaki
    return render_response(
1069 6e029beb Sofia Papagiannaki
        template='im/billing.html',
1070 6e029beb Sofia Papagiannaki
        context_instance=get_context(request),
1071 5056da3d Olga Brani
        data=data,
1072 5056da3d Olga Brani
        zerodate=datetime(month=1,year=1970, day=1),
1073 5056da3d Olga Brani
        today=today,
1074 5056da3d Olga Brani
        start=int(start),
1075 5056da3d Olga Brani
        month_last_day=month_last_day)  
1076 5056da3d Olga Brani
    
1077 5056da3d Olga Brani
def clear_billing_data(data):
1078 5056da3d Olga Brani
    
1079 5056da3d Olga Brani
    # remove addcredits entries
1080 5056da3d Olga Brani
    def isnotcredit(e):
1081 5056da3d Olga Brani
        return e['serviceName'] != "addcredits"
1082 5056da3d Olga Brani
    
1083 5056da3d Olga Brani
    
1084 5056da3d Olga Brani
    
1085 5056da3d Olga Brani
    # separate services    
1086 5056da3d Olga Brani
    def servicefilter(service_name):
1087 5056da3d Olga Brani
        service = service_name
1088 5056da3d Olga Brani
        def fltr(e):
1089 5056da3d Olga Brani
            return e['serviceName'] == service
1090 5056da3d Olga Brani
        return fltr
1091 5056da3d Olga Brani
        
1092 5056da3d Olga Brani
    
1093 5056da3d Olga Brani
    data['bill_nocredits'] = filter(isnotcredit, data['bill'])
1094 5056da3d Olga Brani
    data['bill_vmtime'] = filter(servicefilter('vmtime'), data['bill'])
1095 5056da3d Olga Brani
    data['bill_diskspace'] = filter(servicefilter('diskspace'), data['bill'])
1096 4de59eac Olga Brani
    data['bill_addcredits'] = filter(servicefilter('addcredits'), data['bill'])
1097 5056da3d Olga Brani
        
1098 c3a00daf Olga Brani
    return data    
1099 54213d7a Sofia Papagiannaki
1100 3bcad004 Sofia Papagiannaki
@signed_terms_required
1101 3bcad004 Sofia Papagiannaki
@login_required
1102 54213d7a Sofia Papagiannaki
def timeline(request):
1103 88305cf0 root
#    data = {'entity':request.user.email}
1104 2925e285 root
    timeline_body = ()
1105 2925e285 root
    timeline_header = ()
1106 88305cf0 root
#    form = TimelineForm(data)
1107 88305cf0 root
    form = TimelineForm()
1108 54213d7a Sofia Papagiannaki
    if request.method == 'POST':
1109 54213d7a Sofia Papagiannaki
        data = request.POST
1110 2925e285 root
        form = TimelineForm(data)
1111 2925e285 root
        if form.is_valid():
1112 2925e285 root
            data = form.cleaned_data
1113 2925e285 root
            timeline_header = ('entity', 'resource',
1114 2925e285 root
                               'event name', 'event date',
1115 2925e285 root
                               'incremental cost', 'total cost')
1116 2925e285 root
            timeline_body = timeline_charge(
1117 2925e285 root
                                    data['entity'],     data['resource'],
1118 2925e285 root
                                    data['start_date'], data['end_date'],
1119 2925e285 root
                                    data['details'],    data['operation'])
1120 2925e285 root
        
1121 54213d7a Sofia Papagiannaki
    return render_response(template='im/timeline.html',
1122 54213d7a Sofia Papagiannaki
                           context_instance=get_context(request),
1123 54213d7a Sofia Papagiannaki
                           form=form,
1124 c3f6cdf1 root
                           timeline_header=timeline_header,
1125 c3f6cdf1 root
                           timeline_body=timeline_body)