Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / views / im.py @ 9fb7a900

History | View | Annotate | Download (32.2 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 9a06d96f Olga Brani
import inflect
36 9a06d96f Olga Brani
37 9a06d96f Olga Brani
engine = inflect.engine()
38 64cd4730 Antony Chazapis
39 0905ccd2 Sofia Papagiannaki
from urllib import quote
40 a5cef8d0 Kostas Papadimitriou
41 c630fee6 Kostas Papadimitriou
from django.shortcuts import get_object_or_404
42 890b0eaf Sofia Papagiannaki
from django.contrib import messages
43 01ac12d5 Sofia Papagiannaki
from django.contrib.auth.decorators import login_required
44 0be81d73 Sofia Papagiannaki
from django.contrib.auth.models import User
45 01ac12d5 Sofia Papagiannaki
from django.core.urlresolvers import reverse
46 01ac12d5 Sofia Papagiannaki
from django.db import transaction
47 3e0a032d Sofia Papagiannaki
from django.http import HttpResponse, HttpResponseRedirect, Http404
48 01ac12d5 Sofia Papagiannaki
from django.shortcuts import redirect
49 01ac12d5 Sofia Papagiannaki
from django.utils.translation import ugettext as _
50 3e0a032d Sofia Papagiannaki
from django.core.exceptions import PermissionDenied
51 9a06d96f Olga Brani
from django.views.decorators.http import require_http_methods
52 96b44c04 Sofia Papagiannaki
from django.utils import simplejson as json
53 734107ef Kostas Papadimitriou
54 c630fee6 Kostas Papadimitriou
import astakos.im.messages as astakos_messages
55 c630fee6 Kostas Papadimitriou
56 e7cb4085 Kostas Papadimitriou
from astakos.im import activation_backends
57 3e0a032d Sofia Papagiannaki
from astakos.im.models import AstakosUser, ApprovalTerms, EmailChange, \
58 3e0a032d Sofia Papagiannaki
    AstakosUserAuthProvider, PendingThirdPartyUser, Service
59 3e0a032d Sofia Papagiannaki
from astakos.im.util import get_context, prepare_response, get_query, \
60 3e0a032d Sofia Papagiannaki
    restrict_next
61 3e0a032d Sofia Papagiannaki
from astakos.im.forms import LoginForm, InvitationForm, FeedbackForm, \
62 3e0a032d Sofia Papagiannaki
    SignApprovalTermsForm, EmailChangeForm
63 f7400729 Kostas Papadimitriou
from astakos.im.forms import ExtendedProfileForm as ProfileForm
64 3e0a032d Sofia Papagiannaki
from astakos.im.functions import send_feedback, logout as auth_logout, \
65 3e0a032d Sofia Papagiannaki
    invite as invite_func
66 e7cb4085 Kostas Papadimitriou
from astakos.im import settings
67 8998f09a Sofia Papagiannaki
from astakos.im import presentation
68 9d20fe23 Kostas Papadimitriou
from astakos.im import auth_providers as auth
69 4e03ba30 Kostas Papadimitriou
from astakos.im import quotas
70 70e11eaa Sofia Papagiannaki
from astakos.im.views.util import render_response, _resources_catalog
71 70e11eaa Sofia Papagiannaki
from astakos.im.views.decorators import cookie_fix, signed_terms_required,\
72 70e11eaa Sofia Papagiannaki
    required_auth_methods_assigned, valid_astakos_user_required
73 ae497612 Olga Brani
74 e015e9e6 Sofia Papagiannaki
logger = logging.getLogger(__name__)
75 e015e9e6 Sofia Papagiannaki
76 9a06d96f Olga Brani
77 9a06d96f Olga Brani
@require_http_methods(["GET", "POST"])
78 222305b7 Sofia Papagiannaki
@cookie_fix
79 270dd48d Sofia Papagiannaki
@signed_terms_required
80 1f3b4b39 Sofia Papagiannaki
def index(request, login_template_name='im/login.html', profile_template_name='im/profile.html', extra_context=None):
81 890b0eaf Sofia Papagiannaki
    """
82 dcf55476 Sofia Papagiannaki
    If there is logged on user renders the profile page otherwise renders login page.
83 176023aa Kostas Papadimitriou

84 890b0eaf Sofia Papagiannaki
    **Arguments**
85 176023aa Kostas Papadimitriou

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

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

94 890b0eaf Sofia Papagiannaki
    ``extra_context``
95 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
96 176023aa Kostas Papadimitriou

97 890b0eaf Sofia Papagiannaki
    **Template:**
98 176023aa Kostas Papadimitriou

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

101 890b0eaf Sofia Papagiannaki
    """
102 1f3b4b39 Sofia Papagiannaki
    extra_context = extra_context or {}
103 dcf55476 Sofia Papagiannaki
    template_name = login_template_name
104 dcf55476 Sofia Papagiannaki
    if request.user.is_authenticated():
105 f534fb96 Sofia Papagiannaki
        return HttpResponseRedirect(reverse('astakos.im.views.edit_profile'))
106 792c2f3b Olga Brani
107 f7cf5257 Kostas Papadimitriou
    third_party_token = request.GET.get('key', False)
108 f7cf5257 Kostas Papadimitriou
    if third_party_token:
109 f7cf5257 Kostas Papadimitriou
        messages.info(request, astakos_messages.AUTH_PROVIDER_LOGIN_TO_ADD)
110 f7cf5257 Kostas Papadimitriou
111 ef20ea07 Sofia Papagiannaki
    return render_response(
112 ef20ea07 Sofia Papagiannaki
        template_name,
113 ef20ea07 Sofia Papagiannaki
        login_form = LoginForm(request=request),
114 ef20ea07 Sofia Papagiannaki
        context_instance = get_context(request, extra_context)
115 ef20ea07 Sofia Papagiannaki
    )
116 5ce3ce4f Sofia Papagiannaki
117 64cd4730 Antony Chazapis
118 0504f010 Kostas Papadimitriou
@require_http_methods(["POST"])
119 222305b7 Sofia Papagiannaki
@cookie_fix
120 0504f010 Kostas Papadimitriou
@valid_astakos_user_required
121 0504f010 Kostas Papadimitriou
def update_token(request):
122 0504f010 Kostas Papadimitriou
    """
123 0504f010 Kostas Papadimitriou
    Update api token view.
124 0504f010 Kostas Papadimitriou
    """
125 0504f010 Kostas Papadimitriou
    user = request.user
126 0504f010 Kostas Papadimitriou
    user.renew_token()
127 0504f010 Kostas Papadimitriou
    user.save()
128 0504f010 Kostas Papadimitriou
    messages.success(request, astakos_messages.TOKEN_UPDATED)
129 0504f010 Kostas Papadimitriou
    return HttpResponseRedirect(reverse('edit_profile'))
130 0504f010 Kostas Papadimitriou
131 0504f010 Kostas Papadimitriou
132 9a06d96f Olga Brani
@require_http_methods(["GET", "POST"])
133 222305b7 Sofia Papagiannaki
@cookie_fix
134 badcb2a9 Kostas Papadimitriou
@valid_astakos_user_required
135 890b0eaf Sofia Papagiannaki
@transaction.commit_manually
136 aab4d540 Sofia Papagiannaki
def invite(request, template_name='im/invitations.html', extra_context=None):
137 890b0eaf Sofia Papagiannaki
    """
138 890b0eaf Sofia Papagiannaki
    Allows a user to invite somebody else.
139 176023aa Kostas Papadimitriou

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

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

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

149 890b0eaf Sofia Papagiannaki
    **Arguments**
150 176023aa Kostas Papadimitriou

151 890b0eaf Sofia Papagiannaki
    ``template_name``
152 890b0eaf Sofia Papagiannaki
        A custom template to use. This is optional; if not specified,
153 1e685275 Sofia Papagiannaki
        this will default to ``im/invitations.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/invitations.html or ``template_name`` keyword argument.
161 176023aa Kostas Papadimitriou

162 890b0eaf Sofia Papagiannaki
    **Settings:**
163 176023aa Kostas Papadimitriou

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

166 890b0eaf Sofia Papagiannaki
    * LOGIN_URL: login uri
167 890b0eaf Sofia Papagiannaki
    """
168 1f3b4b39 Sofia Papagiannaki
    extra_context = extra_context or {}
169 64cd4730 Antony Chazapis
    status = None
170 64cd4730 Antony Chazapis
    message = None
171 8f5a3a06 Sofia Papagiannaki
    form = InvitationForm()
172 5ce3ce4f Sofia Papagiannaki
173 18ffbee1 Sofia Papagiannaki
    inviter = request.user
174 64cd4730 Antony Chazapis
    if request.method == 'POST':
175 8f5a3a06 Sofia Papagiannaki
        form = InvitationForm(request.POST)
176 64cd4730 Antony Chazapis
        if inviter.invitations > 0:
177 8f5a3a06 Sofia Papagiannaki
            if form.is_valid():
178 8f5a3a06 Sofia Papagiannaki
                try:
179 9a06d96f Olga Brani
                    email = form.cleaned_data.get('username')
180 9a06d96f Olga Brani
                    realname = form.cleaned_data.get('realname')
181 9cdb86fd Sofia Papagiannaki
                    invite_func(inviter, email, realname)
182 ae497612 Olga Brani
                    message = _(astakos_messages.INVITATION_SENT) % locals()
183 24406ae3 Sofia Papagiannaki
                    messages.success(request, message)
184 e7cb4085 Kostas Papadimitriou
                except Exception, e:
185 18ffbee1 Sofia Papagiannaki
                    transaction.rollback()
186 e7cb4085 Kostas Papadimitriou
                    raise
187 18ffbee1 Sofia Papagiannaki
                else:
188 18ffbee1 Sofia Papagiannaki
                    transaction.commit()
189 64cd4730 Antony Chazapis
        else:
190 ae497612 Olga Brani
            message = _(astakos_messages.MAX_INVITATION_NUMBER_REACHED)
191 24406ae3 Sofia Papagiannaki
            messages.error(request, message)
192 176023aa Kostas Papadimitriou
193 a196eb7e Sofia Papagiannaki
    sent = [{'email': inv.username,
194 d6ae71a2 root
             'realname': inv.realname,
195 d6ae71a2 root
             'is_consumed': inv.is_consumed}
196 5ce3ce4f Sofia Papagiannaki
            for inv in request.user.invitations_sent.all()]
197 77e2ad52 root
    kwargs = {'inviter': inviter,
198 5ce3ce4f Sofia Papagiannaki
              'sent': sent}
199 0905ccd2 Sofia Papagiannaki
    context = get_context(request, extra_context, **kwargs)
200 0905ccd2 Sofia Papagiannaki
    return render_response(template_name,
201 5ce3ce4f Sofia Papagiannaki
                           invitation_form=form,
202 5ce3ce4f Sofia Papagiannaki
                           context_instance=context)
203 5ce3ce4f Sofia Papagiannaki
204 64cd4730 Antony Chazapis
205 9a06d96f Olga Brani
@require_http_methods(["GET", "POST"])
206 9d20fe23 Kostas Papadimitriou
@required_auth_methods_assigned(allow_access=True)
207 890b0eaf Sofia Papagiannaki
@login_required
208 222305b7 Sofia Papagiannaki
@cookie_fix
209 270dd48d Sofia Papagiannaki
@signed_terms_required
210 aab4d540 Sofia Papagiannaki
def edit_profile(request, template_name='im/profile.html', extra_context=None):
211 890b0eaf Sofia Papagiannaki
    """
212 890b0eaf Sofia Papagiannaki
    Allows a user to edit his/her profile.
213 176023aa Kostas Papadimitriou

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

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

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

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

226 890b0eaf Sofia Papagiannaki
    ``extra_context``
227 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
228 176023aa Kostas Papadimitriou

229 890b0eaf Sofia Papagiannaki
    **Template:**
230 176023aa Kostas Papadimitriou

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

233 92defad4 Sofia Papagiannaki
    **Settings:**
234 176023aa Kostas Papadimitriou

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

237 92defad4 Sofia Papagiannaki
    * LOGIN_URL: login uri
238 890b0eaf Sofia Papagiannaki
    """
239 aab4d540 Sofia Papagiannaki
    extra_context = extra_context or {}
240 bf0c6de5 Sofia Papagiannaki
    form = ProfileForm(
241 bf0c6de5 Sofia Papagiannaki
        instance=request.user,
242 bf0c6de5 Sofia Papagiannaki
        session_key=request.session.session_key
243 bf0c6de5 Sofia Papagiannaki
    )
244 15efc749 Sofia Papagiannaki
    extra_context['next'] = request.GET.get('next')
245 64cd4730 Antony Chazapis
    if request.method == 'POST':
246 bf0c6de5 Sofia Papagiannaki
        form = ProfileForm(
247 bf0c6de5 Sofia Papagiannaki
            request.POST,
248 bf0c6de5 Sofia Papagiannaki
            instance=request.user,
249 bf0c6de5 Sofia Papagiannaki
            session_key=request.session.session_key
250 bf0c6de5 Sofia Papagiannaki
        )
251 890b0eaf Sofia Papagiannaki
        if form.is_valid():
252 64cd4730 Antony Chazapis
            try:
253 c301698f Sofia Papagiannaki
                prev_token = request.user.auth_token
254 3fbf7863 Kostas Papadimitriou
                user = form.save(request=request)
255 217994f8 Sofia Papagiannaki
                next = restrict_next(
256 217994f8 Sofia Papagiannaki
                    request.POST.get('next'),
257 8998f09a Sofia Papagiannaki
                    domain=settings.COOKIE_DOMAIN
258 217994f8 Sofia Papagiannaki
                )
259 ae497612 Olga Brani
                msg = _(astakos_messages.PROFILE_UPDATED)
260 24406ae3 Sofia Papagiannaki
                messages.success(request, msg)
261 2da6f56b Kostas Papadimitriou
262 2da6f56b Kostas Papadimitriou
                if form.email_changed:
263 2da6f56b Kostas Papadimitriou
                    msg = _(astakos_messages.EMAIL_CHANGE_REGISTERED)
264 2da6f56b Kostas Papadimitriou
                    messages.success(request, msg)
265 2da6f56b Kostas Papadimitriou
                if form.password_changed:
266 2da6f56b Kostas Papadimitriou
                    msg = _(astakos_messages.PASSWORD_CHANGED)
267 2da6f56b Kostas Papadimitriou
                    messages.success(request, msg)
268 2da6f56b Kostas Papadimitriou
269 f7400729 Kostas Papadimitriou
                if next:
270 f7400729 Kostas Papadimitriou
                    return redirect(next)
271 f7400729 Kostas Papadimitriou
                else:
272 f7400729 Kostas Papadimitriou
                    return redirect(reverse('edit_profile'))
273 890b0eaf Sofia Papagiannaki
            except ValueError, ve:
274 24406ae3 Sofia Papagiannaki
                messages.success(request, ve)
275 23447441 Sofia Papagiannaki
    elif request.method == "GET":
276 792c2f3b Olga Brani
        request.user.is_verified = True
277 792c2f3b Olga Brani
        request.user.save()
278 792c2f3b Olga Brani
279 792c2f3b Olga Brani
    # existing providers
280 9d20fe23 Kostas Papadimitriou
    user_providers = request.user.get_enabled_auth_providers()
281 9d20fe23 Kostas Papadimitriou
    user_disabled_providers = request.user.get_disabled_auth_providers()
282 792c2f3b Olga Brani
283 792c2f3b Olga Brani
    # providers that user can add
284 792c2f3b Olga Brani
    user_available_providers = request.user.get_available_auth_providers()
285 792c2f3b Olga Brani
286 79b5d61b Sofia Papagiannaki
    extra_context['services'] = Service.catalog().values()
287 0905ccd2 Sofia Papagiannaki
    return render_response(template_name,
288 e7cb4085 Kostas Papadimitriou
                           profile_form=form,
289 e7cb4085 Kostas Papadimitriou
                           user_providers=user_providers,
290 e7cb4085 Kostas Papadimitriou
                           user_disabled_providers=user_disabled_providers,
291 e7cb4085 Kostas Papadimitriou
                           user_available_providers=user_available_providers,
292 e7cb4085 Kostas Papadimitriou
                           context_instance=get_context(request,
293 c301698f Sofia Papagiannaki
                                                          extra_context))
294 5ce3ce4f Sofia Papagiannaki
295 64cd4730 Antony Chazapis
296 10ed0073 Sofia Papagiannaki
@transaction.commit_manually
297 9a06d96f Olga Brani
@require_http_methods(["GET", "POST"])
298 222305b7 Sofia Papagiannaki
@cookie_fix
299 e7cb4085 Kostas Papadimitriou
def signup(request, template_name='im/signup.html', on_success='index',
300 e7cb4085 Kostas Papadimitriou
           extra_context=None, activation_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 e7cb4085 Kostas Papadimitriou
    The user activation will be delegated to the backend specified by the
308 e7cb4085 Kostas Papadimitriou
    ``activation_backend`` keyword argument if present, otherwise to the
309 e7cb4085 Kostas Papadimitriou
    ``astakos.im.activation_backends.InvitationBackend`` if
310 e7cb4085 Kostas Papadimitriou
    settings.ASTAKOS_INVITATIONS_ENABLED is True or
311 e7cb4085 Kostas Papadimitriou
    ``astakos.im.activation_backends.SimpleBackend`` if not (see
312 e7cb4085 Kostas Papadimitriou
    activation_backends);
313 5ce3ce4f Sofia Papagiannaki

314 e7cb4085 Kostas Papadimitriou
    Upon successful user creation, if ``next`` url parameter is present the
315 e7cb4085 Kostas Papadimitriou
    user is redirected there otherwise renders the same page with a success
316 e7cb4085 Kostas Papadimitriou
    message.
317 5ce3ce4f Sofia Papagiannaki

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

320 890b0eaf Sofia Papagiannaki
    **Arguments**
321 5ce3ce4f Sofia Papagiannaki

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

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

329 43332a76 Kostas Papadimitriou
    ``on_success``
330 43332a76 Kostas Papadimitriou
        Resolvable view name to redirect on registration success.
331 43332a76 Kostas Papadimitriou

332 890b0eaf Sofia Papagiannaki
    **Template:**
333 5ce3ce4f Sofia Papagiannaki

334 8f5a3a06 Sofia Papagiannaki
    im/signup.html or ``template_name`` keyword argument.
335 890b0eaf Sofia Papagiannaki
    """
336 1f3b4b39 Sofia Papagiannaki
    extra_context = extra_context or {}
337 0d02a287 Sofia Papagiannaki
    if request.user.is_authenticated():
338 e7cb4085 Kostas Papadimitriou
        logger.info("%s already signed in, redirect to index",
339 e7cb4085 Kostas Papadimitriou
                    request.user.log_display)
340 e7cb4085 Kostas Papadimitriou
        return HttpResponseRedirect(reverse('index'))
341 5ce3ce4f Sofia Papagiannaki
342 0a569195 Sofia Papagiannaki
    provider = get_query(request).get('provider', 'local')
343 9d20fe23 Kostas Papadimitriou
    if not auth.get_provider(provider).get_create_policy:
344 e7cb4085 Kostas Papadimitriou
        logger.error("%s provider not available for signup", provider)
345 279d6e51 Olga Brani
        raise PermissionDenied
346 279d6e51 Olga Brani
347 e7cb4085 Kostas Papadimitriou
    instance = None
348 6c8a3f7c Sofia Papagiannaki
349 e7cb4085 Kostas Papadimitriou
    # user registered using third party provider
350 8ab484ea Kostas Papadimitriou
    third_party_token = request.REQUEST.get('third_party_token', None)
351 9d20fe23 Kostas Papadimitriou
    unverified = None
352 c630fee6 Kostas Papadimitriou
    if third_party_token:
353 e7cb4085 Kostas Papadimitriou
        # retreive third party entry. This was created right after the initial
354 e7cb4085 Kostas Papadimitriou
        # third party provider handshake.
355 c630fee6 Kostas Papadimitriou
        pending = get_object_or_404(PendingThirdPartyUser,
356 c630fee6 Kostas Papadimitriou
                                    token=third_party_token)
357 9d20fe23 Kostas Papadimitriou
358 c630fee6 Kostas Papadimitriou
        provider = pending.provider
359 e7cb4085 Kostas Papadimitriou
360 e7cb4085 Kostas Papadimitriou
        # clone third party instance into the corresponding AstakosUser
361 c630fee6 Kostas Papadimitriou
        instance = pending.get_user_instance()
362 9d20fe23 Kostas Papadimitriou
        get_unverified = AstakosUserAuthProvider.objects.unverified
363 e7cb4085 Kostas Papadimitriou
364 e7cb4085 Kostas Papadimitriou
        # check existing unverified entries
365 9d20fe23 Kostas Papadimitriou
        unverified = get_unverified(pending.provider,
366 9d20fe23 Kostas Papadimitriou
                                    identifier=pending.third_party_identifier)
367 9d20fe23 Kostas Papadimitriou
368 9d20fe23 Kostas Papadimitriou
        if unverified and request.method == 'GET':
369 9d20fe23 Kostas Papadimitriou
            messages.warning(request, unverified.get_pending_registration_msg)
370 e7cb4085 Kostas Papadimitriou
            if unverified.user.moderated:
371 9d20fe23 Kostas Papadimitriou
                messages.warning(request,
372 9d20fe23 Kostas Papadimitriou
                                 unverified.get_pending_resend_activation_msg)
373 9d20fe23 Kostas Papadimitriou
            else:
374 9d20fe23 Kostas Papadimitriou
                messages.warning(request,
375 9d20fe23 Kostas Papadimitriou
                                 unverified.get_pending_moderation_msg)
376 8ab484ea Kostas Papadimitriou
377 e7cb4085 Kostas Papadimitriou
    # prepare activation backend based on current request
378 e7cb4085 Kostas Papadimitriou
    if not activation_backend:
379 e7cb4085 Kostas Papadimitriou
        activation_backend = activation_backends.get_backend()
380 e7cb4085 Kostas Papadimitriou
381 e7cb4085 Kostas Papadimitriou
    form_kwargs = {'instance': instance}
382 e7cb4085 Kostas Papadimitriou
    if third_party_token:
383 e7cb4085 Kostas Papadimitriou
        form_kwargs['third_party_token'] = third_party_token
384 e7cb4085 Kostas Papadimitriou
385 e7cb4085 Kostas Papadimitriou
    form = activation_backend.get_signup_form(
386 e7cb4085 Kostas Papadimitriou
        provider, None, **form_kwargs)
387 9d20fe23 Kostas Papadimitriou
388 8f5a3a06 Sofia Papagiannaki
    if request.method == 'POST':
389 e7cb4085 Kostas Papadimitriou
        form = activation_backend.get_signup_form(
390 e7cb4085 Kostas Papadimitriou
            provider,
391 e7cb4085 Kostas Papadimitriou
            request.POST,
392 e7cb4085 Kostas Papadimitriou
            **form_kwargs)
393 e7cb4085 Kostas Papadimitriou
394 8f5a3a06 Sofia Papagiannaki
        if form.is_valid():
395 e7cb4085 Kostas Papadimitriou
            commited = False
396 e7cb4085 Kostas Papadimitriou
            try:
397 e7cb4085 Kostas Papadimitriou
                user = form.save(commit=False)
398 43332a76 Kostas Papadimitriou
399 e7cb4085 Kostas Papadimitriou
                # delete previously unverified accounts
400 e7cb4085 Kostas Papadimitriou
                if AstakosUser.objects.user_exists(user.email):
401 e7cb4085 Kostas Papadimitriou
                    AstakosUser.objects.get_by_identifier(user.email).delete()
402 43332a76 Kostas Papadimitriou
403 e7cb4085 Kostas Papadimitriou
                # store_user so that user auth providers get initialized
404 9d20fe23 Kostas Papadimitriou
                form.store_user(user, request)
405 e7cb4085 Kostas Papadimitriou
                result = activation_backend.handle_registration(user)
406 e7cb4085 Kostas Papadimitriou
                if result.status == \
407 e7cb4085 Kostas Papadimitriou
                        activation_backend.Result.PENDING_MODERATION:
408 e7cb4085 Kostas Papadimitriou
                    # user should be warned that his account is not active yet
409 e7cb4085 Kostas Papadimitriou
                    status = messages.WARNING
410 e7cb4085 Kostas Papadimitriou
                else:
411 e7cb4085 Kostas Papadimitriou
                    status = messages.SUCCESS
412 18ffbee1 Sofia Papagiannaki
                message = result.message
413 e7cb4085 Kostas Papadimitriou
                activation_backend.send_result_notifications(result, user)
414 792c2f3b Olga Brani
415 e7cb4085 Kostas Papadimitriou
                # commit user entry
416 e7cb4085 Kostas Papadimitriou
                transaction.commit()
417 e7cb4085 Kostas Papadimitriou
                # commited flag
418 e7cb4085 Kostas Papadimitriou
                # in case an exception get raised from this point
419 e7cb4085 Kostas Papadimitriou
                commited = True
420 43332a76 Kostas Papadimitriou
421 8f5a3a06 Sofia Papagiannaki
                if user and user.is_active:
422 e7cb4085 Kostas Papadimitriou
                    # activation backend directly activated the user
423 e7cb4085 Kostas Papadimitriou
                    # log him in
424 8f5a3a06 Sofia Papagiannaki
                    next = request.POST.get('next', '')
425 40a0cd8b Sofia Papagiannaki
                    response = prepare_response(request, user, next=next)
426 40a0cd8b Sofia Papagiannaki
                    return response
427 43332a76 Kostas Papadimitriou
428 43332a76 Kostas Papadimitriou
                messages.add_message(request, status, message)
429 43332a76 Kostas Papadimitriou
                return HttpResponseRedirect(reverse(on_success))
430 e7cb4085 Kostas Papadimitriou
            except Exception, e:
431 e7cb4085 Kostas Papadimitriou
                if not commited:
432 e7cb4085 Kostas Papadimitriou
                    transaction.rollback()
433 e7cb4085 Kostas Papadimitriou
                raise
434 43332a76 Kostas Papadimitriou
435 8f5a3a06 Sofia Papagiannaki
    return render_response(template_name,
436 5ce3ce4f Sofia Papagiannaki
                           signup_form=form,
437 8ab484ea Kostas Papadimitriou
                           third_party_token=third_party_token,
438 5ce3ce4f Sofia Papagiannaki
                           provider=provider,
439 890b0eaf Sofia Papagiannaki
                           context_instance=get_context(request, extra_context))
440 64cd4730 Antony Chazapis
441 5ce3ce4f Sofia Papagiannaki
442 9a06d96f Olga Brani
@require_http_methods(["GET", "POST"])
443 9d20fe23 Kostas Papadimitriou
@required_auth_methods_assigned(allow_access=True)
444 890b0eaf Sofia Papagiannaki
@login_required
445 222305b7 Sofia Papagiannaki
@cookie_fix
446 270dd48d Sofia Papagiannaki
@signed_terms_required
447 aab4d540 Sofia Papagiannaki
def feedback(request, template_name='im/feedback.html', email_template_name='im/feedback_mail.txt', extra_context=None):
448 890b0eaf Sofia Papagiannaki
    """
449 890b0eaf Sofia Papagiannaki
    Allows a user to send feedback.
450 176023aa Kostas Papadimitriou

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

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

456 890b0eaf Sofia Papagiannaki
    **Arguments**
457 176023aa Kostas Papadimitriou

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

462 890b0eaf Sofia Papagiannaki
    ``extra_context``
463 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
464 176023aa Kostas Papadimitriou

465 890b0eaf Sofia Papagiannaki
    **Template:**
466 176023aa Kostas Papadimitriou

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

469 890b0eaf Sofia Papagiannaki
    **Settings:**
470 176023aa Kostas Papadimitriou

471 92defad4 Sofia Papagiannaki
    * LOGIN_URL: login uri
472 890b0eaf Sofia Papagiannaki
    """
473 1f3b4b39 Sofia Papagiannaki
    extra_context = extra_context or {}
474 64cd4730 Antony Chazapis
    if request.method == 'GET':
475 890b0eaf Sofia Papagiannaki
        form = FeedbackForm()
476 890b0eaf Sofia Papagiannaki
    if request.method == 'POST':
477 890b0eaf Sofia Papagiannaki
        if not request.user:
478 890b0eaf Sofia Papagiannaki
            return HttpResponse('Unauthorized', status=401)
479 176023aa Kostas Papadimitriou
480 890b0eaf Sofia Papagiannaki
        form = FeedbackForm(request.POST)
481 890b0eaf Sofia Papagiannaki
        if form.is_valid():
482 e9083112 Sofia Papagiannaki
            msg = form.cleaned_data['feedback_msg']
483 8f5a3a06 Sofia Papagiannaki
            data = form.cleaned_data['feedback_data']
484 860bb9f7 Sofia Papagiannaki
            send_feedback(msg, data, request.user, email_template_name)
485 860bb9f7 Sofia Papagiannaki
            message = _(astakos_messages.FEEDBACK_SENT)
486 860bb9f7 Sofia Papagiannaki
            messages.success(request, message)
487 b9f8f48a Kostas Papadimitriou
            return HttpResponseRedirect(reverse('feedback'))
488 e7cb4085 Kostas Papadimitriou
489 890b0eaf Sofia Papagiannaki
    return render_response(template_name,
490 5ce3ce4f Sofia Papagiannaki
                           feedback_form=form,
491 e7cb4085 Kostas Papadimitriou
                           context_instance=get_context(request,
492 e7cb4085 Kostas Papadimitriou
                                                        extra_context))
493 5ce3ce4f Sofia Papagiannaki
494 15efc749 Sofia Papagiannaki
495 217994f8 Sofia Papagiannaki
@require_http_methods(["GET"])
496 222305b7 Sofia Papagiannaki
@cookie_fix
497 e7cb4085 Kostas Papadimitriou
def logout(request, template='registration/logged_out.html',
498 e7cb4085 Kostas Papadimitriou
           extra_context=None):
499 63ecdd20 Sofia Papagiannaki
    """
500 b2ffa772 Sofia Papagiannaki
    Wraps `django.contrib.auth.logout`.
501 63ecdd20 Sofia Papagiannaki
    """
502 1f3b4b39 Sofia Papagiannaki
    extra_context = extra_context or {}
503 7482228b Sofia Papagiannaki
    response = HttpResponse()
504 8e45d6fd Sofia Papagiannaki
    if request.user.is_authenticated():
505 8e45d6fd Sofia Papagiannaki
        email = request.user.email
506 8e45d6fd Sofia Papagiannaki
        auth_logout(request)
507 c630fee6 Kostas Papadimitriou
    else:
508 c630fee6 Kostas Papadimitriou
        response['Location'] = reverse('index')
509 c630fee6 Kostas Papadimitriou
        response.status_code = 301
510 c630fee6 Kostas Papadimitriou
        return response
511 c630fee6 Kostas Papadimitriou
512 217994f8 Sofia Papagiannaki
    next = restrict_next(
513 217994f8 Sofia Papagiannaki
        request.GET.get('next'),
514 8998f09a Sofia Papagiannaki
        domain=settings.COOKIE_DOMAIN
515 217994f8 Sofia Papagiannaki
    )
516 c630fee6 Kostas Papadimitriou
517 63ecdd20 Sofia Papagiannaki
    if next:
518 63ecdd20 Sofia Papagiannaki
        response['Location'] = next
519 63ecdd20 Sofia Papagiannaki
        response.status_code = 302
520 8998f09a Sofia Papagiannaki
    elif settings.LOGOUT_NEXT:
521 8998f09a Sofia Papagiannaki
        response['Location'] = settings.LOGOUT_NEXT
522 0d02a287 Sofia Papagiannaki
        response.status_code = 301
523 b2ffa772 Sofia Papagiannaki
    else:
524 9d20fe23 Kostas Papadimitriou
        last_provider = request.COOKIES.get('astakos_last_login_method', 'local')
525 9d20fe23 Kostas Papadimitriou
        provider = auth.get_provider(last_provider)
526 9d20fe23 Kostas Papadimitriou
        message = provider.get_logout_success_msg
527 9d20fe23 Kostas Papadimitriou
        extra = provider.get_logout_success_extra_msg
528 9d20fe23 Kostas Papadimitriou
        if extra:
529 9d20fe23 Kostas Papadimitriou
            message += "<br />"  + extra
530 d21d422a Kostas Papadimitriou
        messages.success(request, message)
531 c630fee6 Kostas Papadimitriou
        response['Location'] = reverse('index')
532 c630fee6 Kostas Papadimitriou
        response.status_code = 301
533 49df775e Sofia Papagiannaki
    return response
534 2126d85d Sofia Papagiannaki
535 5ce3ce4f Sofia Papagiannaki
536 9a06d96f Olga Brani
@require_http_methods(["GET", "POST"])
537 222305b7 Sofia Papagiannaki
@cookie_fix
538 683cf244 Sofia Papagiannaki
@transaction.commit_manually
539 3bb604eb Sofia Papagiannaki
def activate(request, greeting_email_template_name='im/welcome_email.txt',
540 3bb604eb Sofia Papagiannaki
             helpdesk_email_template_name='im/helpdesk_notification.txt'):
541 2126d85d Sofia Papagiannaki
    """
542 e7cb4085 Kostas Papadimitriou
    Activates the user identified by the ``auth`` request parameter, sends a
543 e7cb4085 Kostas Papadimitriou
    welcome email and renews the user token.
544 176023aa Kostas Papadimitriou

545 e7cb4085 Kostas Papadimitriou
    The view uses commit_manually decorator in order to ensure the user state
546 e7cb4085 Kostas Papadimitriou
    will be updated only if the email will be send successfully.
547 2126d85d Sofia Papagiannaki
    """
548 2126d85d Sofia Papagiannaki
    token = request.GET.get('auth')
549 2126d85d Sofia Papagiannaki
    next = request.GET.get('next')
550 5ce3ce4f Sofia Papagiannaki
551 e7cb4085 Kostas Papadimitriou
    if request.user.is_authenticated():
552 e7cb4085 Kostas Papadimitriou
        message = _(astakos_messages.LOGGED_IN_WARNING)
553 24406ae3 Sofia Papagiannaki
        messages.error(request, message)
554 92a8abc9 Kostas Papadimitriou
        return HttpResponseRedirect(reverse('index'))
555 5ce3ce4f Sofia Papagiannaki
556 e7cb4085 Kostas Papadimitriou
    try:
557 e7cb4085 Kostas Papadimitriou
        user = AstakosUser.objects.get(verification_code=token)
558 e7cb4085 Kostas Papadimitriou
    except AstakosUser.DoesNotExist:
559 e7cb4085 Kostas Papadimitriou
        raise Http404
560 e7cb4085 Kostas Papadimitriou
561 e7cb4085 Kostas Papadimitriou
    if user.email_verified:
562 e7cb4085 Kostas Papadimitriou
        message = _(astakos_messages.ACCOUNT_ALREADY_VERIFIED)
563 89d959c9 Kostas Papadimitriou
        messages.error(request, message)
564 89d959c9 Kostas Papadimitriou
        return HttpResponseRedirect(reverse('index'))
565 89d959c9 Kostas Papadimitriou
566 0a569195 Sofia Papagiannaki
    try:
567 e7cb4085 Kostas Papadimitriou
        backend = activation_backends.get_backend()
568 e7cb4085 Kostas Papadimitriou
        result = backend.handle_verification(user, token)
569 e7cb4085 Kostas Papadimitriou
        backend.send_result_notifications(result, user)
570 8998f09a Sofia Papagiannaki
        next = settings.ACTIVATION_REDIRECT_URL or next
571 e7cb4085 Kostas Papadimitriou
        response = HttpResponseRedirect(reverse('index'))
572 e7cb4085 Kostas Papadimitriou
        if user.is_active:
573 e7cb4085 Kostas Papadimitriou
            response = prepare_response(request, user, next, renew=True)
574 e7cb4085 Kostas Papadimitriou
            messages.success(request, _(result.message))
575 e7cb4085 Kostas Papadimitriou
        else:
576 e7cb4085 Kostas Papadimitriou
            messages.warning(request, _(result.message))
577 e7cb4085 Kostas Papadimitriou
    except Exception:
578 e7cb4085 Kostas Papadimitriou
        transaction.rollback()
579 e7cb4085 Kostas Papadimitriou
        raise
580 e7cb4085 Kostas Papadimitriou
    else:
581 ef20ea07 Sofia Papagiannaki
        transaction.commit()
582 279d6e51 Olga Brani
        return response
583 270dd48d Sofia Papagiannaki
584 5ce3ce4f Sofia Papagiannaki
585 9a06d96f Olga Brani
@require_http_methods(["GET", "POST"])
586 222305b7 Sofia Papagiannaki
@cookie_fix
587 e7cb4085 Kostas Papadimitriou
def approval_terms(request, term_id=None,
588 e7cb4085 Kostas Papadimitriou
                   template_name='im/approval_terms.html', extra_context=None):
589 1f3b4b39 Sofia Papagiannaki
    extra_context = extra_context or {}
590 270dd48d Sofia Papagiannaki
    term = None
591 270dd48d Sofia Papagiannaki
    terms = None
592 270dd48d Sofia Papagiannaki
    if not term_id:
593 270dd48d Sofia Papagiannaki
        try:
594 270dd48d Sofia Papagiannaki
            term = ApprovalTerms.objects.order_by('-id')[0]
595 270dd48d Sofia Papagiannaki
        except IndexError:
596 270dd48d Sofia Papagiannaki
            pass
597 270dd48d Sofia Papagiannaki
    else:
598 270dd48d Sofia Papagiannaki
        try:
599 aab4d540 Sofia Papagiannaki
            term = ApprovalTerms.objects.get(id=term_id)
600 aab4d540 Sofia Papagiannaki
        except ApprovalTerms.DoesNotExist, e:
601 270dd48d Sofia Papagiannaki
            pass
602 176023aa Kostas Papadimitriou
603 270dd48d Sofia Papagiannaki
    if not term:
604 ae497612 Olga Brani
        messages.error(request, _(astakos_messages.NO_APPROVAL_TERMS))
605 6ff7a7ca Sofia Papagiannaki
        return HttpResponseRedirect(reverse('index'))
606 64b5136c Sofia Papagiannaki
    try:
607 64b5136c Sofia Papagiannaki
        f = open(term.location, 'r')
608 64b5136c Sofia Papagiannaki
    except IOError:
609 64b5136c Sofia Papagiannaki
        messages.error(request, _(astakos_messages.GENERIC_ERROR))
610 64b5136c Sofia Papagiannaki
        return render_response(
611 e7cb4085 Kostas Papadimitriou
            template_name, context_instance=get_context(request,
612 e7cb4085 Kostas Papadimitriou
                                                        extra_context))
613 64b5136c Sofia Papagiannaki
614 270dd48d Sofia Papagiannaki
    terms = f.read()
615 176023aa Kostas Papadimitriou
616 270dd48d Sofia Papagiannaki
    if request.method == 'POST':
617 217994f8 Sofia Papagiannaki
        next = restrict_next(
618 217994f8 Sofia Papagiannaki
            request.POST.get('next'),
619 8998f09a Sofia Papagiannaki
            domain=settings.COOKIE_DOMAIN
620 217994f8 Sofia Papagiannaki
        )
621 270dd48d Sofia Papagiannaki
        if not next:
622 6ff7a7ca Sofia Papagiannaki
            next = reverse('index')
623 270dd48d Sofia Papagiannaki
        form = SignApprovalTermsForm(request.POST, instance=request.user)
624 270dd48d Sofia Papagiannaki
        if not form.is_valid():
625 270dd48d Sofia Papagiannaki
            return render_response(template_name,
626 5ce3ce4f Sofia Papagiannaki
                                   terms=terms,
627 5ce3ce4f Sofia Papagiannaki
                                   approval_terms_form=form,
628 e7cb4085 Kostas Papadimitriou
                                   context_instance=get_context(request,
629 e7cb4085 Kostas Papadimitriou
                                                                extra_context))
630 270dd48d Sofia Papagiannaki
        user = form.save()
631 270dd48d Sofia Papagiannaki
        return HttpResponseRedirect(next)
632 270dd48d Sofia Papagiannaki
    else:
633 586967c0 Sofia Papagiannaki
        form = None
634 fcf90160 Sofia Papagiannaki
        if request.user.is_authenticated() and not request.user.signed_terms:
635 586967c0 Sofia Papagiannaki
            form = SignApprovalTermsForm(instance=request.user)
636 270dd48d Sofia Papagiannaki
        return render_response(template_name,
637 5ce3ce4f Sofia Papagiannaki
                               terms=terms,
638 5ce3ce4f Sofia Papagiannaki
                               approval_terms_form=form,
639 e7cb4085 Kostas Papadimitriou
                               context_instance=get_context(request,
640 e7cb4085 Kostas Papadimitriou
                                                            extra_context))
641 5ce3ce4f Sofia Papagiannaki
642 270dd48d Sofia Papagiannaki
643 9a06d96f Olga Brani
@require_http_methods(["GET", "POST"])
644 222305b7 Sofia Papagiannaki
@cookie_fix
645 49790d9d Sofia Papagiannaki
@transaction.commit_manually
646 49790d9d Sofia Papagiannaki
def change_email(request, activation_key=None,
647 49790d9d Sofia Papagiannaki
                 email_template_name='registration/email_change_email.txt',
648 49790d9d Sofia Papagiannaki
                 form_template_name='registration/email_change_form.html',
649 49790d9d Sofia Papagiannaki
                 confirm_template_name='registration/email_change_done.html',
650 aab4d540 Sofia Papagiannaki
                 extra_context=None):
651 1f3b4b39 Sofia Papagiannaki
    extra_context = extra_context or {}
652 53e0b8fe Kostas Papadimitriou
653 e7cb4085 Kostas Papadimitriou
    if not settings.EMAILCHANGE_ENABLED:
654 17ad5d37 Kostas Papadimitriou
        raise PermissionDenied
655 17ad5d37 Kostas Papadimitriou
656 49790d9d Sofia Papagiannaki
    if activation_key:
657 49790d9d Sofia Papagiannaki
        try:
658 0b817216 Kostas Papadimitriou
            try:
659 0b817216 Kostas Papadimitriou
                email_change = EmailChange.objects.get(
660 0b817216 Kostas Papadimitriou
                    activation_key=activation_key)
661 0b817216 Kostas Papadimitriou
            except EmailChange.DoesNotExist:
662 0b817216 Kostas Papadimitriou
                transaction.rollback()
663 0b817216 Kostas Papadimitriou
                logger.error("[change-email] Invalid or used activation "
664 0b817216 Kostas Papadimitriou
                             "code, %s", activation_key)
665 0b817216 Kostas Papadimitriou
                raise Http404
666 0b817216 Kostas Papadimitriou
667 0b817216 Kostas Papadimitriou
            if (request.user.is_authenticated() and \
668 0b817216 Kostas Papadimitriou
                request.user == email_change.user) or not \
669 10a870d5 Kostas Papadimitriou
                    request.user.is_authenticated():
670 0b817216 Kostas Papadimitriou
                user = EmailChange.objects.change_email(activation_key)
671 ae497612 Olga Brani
                msg = _(astakos_messages.EMAIL_CHANGED)
672 24406ae3 Sofia Papagiannaki
                messages.success(request, msg)
673 49790d9d Sofia Papagiannaki
                transaction.commit()
674 53e0b8fe Kostas Papadimitriou
                return HttpResponseRedirect(reverse('edit_profile'))
675 0b817216 Kostas Papadimitriou
            else:
676 0b817216 Kostas Papadimitriou
                logger.error("[change-email] Access from invalid user, %s %s",
677 0b817216 Kostas Papadimitriou
                             email_change.user, request.user.log_display)
678 0b817216 Kostas Papadimitriou
                transaction.rollback()
679 0b817216 Kostas Papadimitriou
                raise PermissionDenied
680 49790d9d Sofia Papagiannaki
        except ValueError, e:
681 24406ae3 Sofia Papagiannaki
            messages.error(request, e)
682 53e0b8fe Kostas Papadimitriou
            transaction.rollback()
683 53e0b8fe Kostas Papadimitriou
            return HttpResponseRedirect(reverse('index'))
684 53e0b8fe Kostas Papadimitriou
685 49790d9d Sofia Papagiannaki
        return render_response(confirm_template_name,
686 e7cb4085 Kostas Papadimitriou
                               modified_user=user if 'user' in locals()
687 53e0b8fe Kostas Papadimitriou
                               else None, context_instance=get_context(request,
688 e7cb4085 Kostas Papadimitriou
                               extra_context))
689 5ce3ce4f Sofia Papagiannaki
690 49790d9d Sofia Papagiannaki
    if not request.user.is_authenticated():
691 49790d9d Sofia Papagiannaki
        path = quote(request.get_full_path())
692 6ff7a7ca Sofia Papagiannaki
        url = request.build_absolute_uri(reverse('index'))
693 49790d9d Sofia Papagiannaki
        return HttpResponseRedirect(url + '?next=' + path)
694 53e0b8fe Kostas Papadimitriou
695 53e0b8fe Kostas Papadimitriou
    # clean up expired email changes
696 53e0b8fe Kostas Papadimitriou
    if request.user.email_change_is_pending():
697 53e0b8fe Kostas Papadimitriou
        change = request.user.emailchanges.get()
698 53e0b8fe Kostas Papadimitriou
        if change.activation_key_expired():
699 53e0b8fe Kostas Papadimitriou
            change.delete()
700 53e0b8fe Kostas Papadimitriou
            transaction.commit()
701 53e0b8fe Kostas Papadimitriou
            return HttpResponseRedirect(reverse('email_change'))
702 53e0b8fe Kostas Papadimitriou
703 49790d9d Sofia Papagiannaki
    form = EmailChangeForm(request.POST or None)
704 49790d9d Sofia Papagiannaki
    if request.method == 'POST' and form.is_valid():
705 49790d9d Sofia Papagiannaki
        try:
706 9d20fe23 Kostas Papadimitriou
            ec = form.save(request, email_template_name, request)
707 e7cb4085 Kostas Papadimitriou
        except Exception, e:
708 49790d9d Sofia Papagiannaki
            transaction.rollback()
709 e7cb4085 Kostas Papadimitriou
            raise
710 49790d9d Sofia Papagiannaki
        else:
711 ae497612 Olga Brani
            msg = _(astakos_messages.EMAIL_CHANGE_REGISTERED)
712 24406ae3 Sofia Papagiannaki
            messages.success(request, msg)
713 49790d9d Sofia Papagiannaki
            transaction.commit()
714 53e0b8fe Kostas Papadimitriou
            return HttpResponseRedirect(reverse('edit_profile'))
715 53e0b8fe Kostas Papadimitriou
716 53e0b8fe Kostas Papadimitriou
    if request.user.email_change_is_pending():
717 53e0b8fe Kostas Papadimitriou
        messages.warning(request, astakos_messages.PENDING_EMAIL_CHANGE_REQUEST)
718 53e0b8fe Kostas Papadimitriou
719 c0b26605 Sofia Papagiannaki
    return render_response(
720 c0b26605 Sofia Papagiannaki
        form_template_name,
721 c0b26605 Sofia Papagiannaki
        form=form,
722 c0b26605 Sofia Papagiannaki
        context_instance=get_context(request, extra_context)
723 c0b26605 Sofia Papagiannaki
    )
724 1f3b4b39 Sofia Papagiannaki
725 1f3b4b39 Sofia Papagiannaki
726 222305b7 Sofia Papagiannaki
@cookie_fix
727 e7cb4085 Kostas Papadimitriou
def send_activation(request, user_id, template_name='im/login.html',
728 e7cb4085 Kostas Papadimitriou
                    extra_context=None):
729 792c2f3b Olga Brani
730 badcb2a9 Kostas Papadimitriou
    if request.user.is_authenticated():
731 e7cb4085 Kostas Papadimitriou
        return HttpResponseRedirect(reverse('index'))
732 badcb2a9 Kostas Papadimitriou
733 1f3b4b39 Sofia Papagiannaki
    extra_context = extra_context or {}
734 1f3b4b39 Sofia Papagiannaki
    try:
735 1f3b4b39 Sofia Papagiannaki
        u = AstakosUser.objects.get(id=user_id)
736 1f3b4b39 Sofia Papagiannaki
    except AstakosUser.DoesNotExist:
737 c0b26605 Sofia Papagiannaki
        messages.error(request, _(astakos_messages.ACCOUNT_UNKNOWN))
738 1f3b4b39 Sofia Papagiannaki
    else:
739 e7cb4085 Kostas Papadimitriou
        if u.email_verified:
740 e7cb4085 Kostas Papadimitriou
            logger.warning("[resend activation] Account already verified: %s",
741 e7cb4085 Kostas Papadimitriou
                           u.log_display)
742 e7cb4085 Kostas Papadimitriou
743 e7cb4085 Kostas Papadimitriou
            messages.error(request,
744 e7cb4085 Kostas Papadimitriou
                           _(astakos_messages.ACCOUNT_ALREADY_VERIFIED))
745 e7cb4085 Kostas Papadimitriou
        else:
746 e7cb4085 Kostas Papadimitriou
            activation_backend = activation_backends.get_backend()
747 e7cb4085 Kostas Papadimitriou
            activation_backend.send_user_verification_email(u)
748 e7cb4085 Kostas Papadimitriou
            messages.success(request, astakos_messages.ACTIVATION_SENT)
749 ff81d0d9 Kostas Papadimitriou
750 ff81d0d9 Kostas Papadimitriou
    return HttpResponseRedirect(reverse('index'))
751 5ce3ce4f Sofia Papagiannaki
752 73fbaec4 Sofia Papagiannaki
753 73fbaec4 Sofia Papagiannaki
@require_http_methods(["GET"])
754 222305b7 Sofia Papagiannaki
@cookie_fix
755 badcb2a9 Kostas Papadimitriou
@valid_astakos_user_required
756 666c7490 Sofia Papagiannaki
def resource_usage(request):
757 e9ef5009 Kostas Papadimitriou
758 37d59b27 Kostas Papadimitriou
    resources_meta = presentation.RESOURCES
759 37d59b27 Kostas Papadimitriou
760 4e03ba30 Kostas Papadimitriou
    current_usage = quotas.get_user_quotas(request.user)
761 4e03ba30 Kostas Papadimitriou
    current_usage = json.dumps(current_usage['system'])
762 37d59b27 Kostas Papadimitriou
    resource_catalog, resource_groups = _resources_catalog(for_usage=True)
763 37d59b27 Kostas Papadimitriou
    if resource_catalog is False:
764 37d59b27 Kostas Papadimitriou
        # on fail resource_groups contains the result object
765 37d59b27 Kostas Papadimitriou
        result = resource_groups
766 37d59b27 Kostas Papadimitriou
        messages.error(request, 'Unable to retrieve system resources: %s' %
767 37d59b27 Kostas Papadimitriou
                       result.reason)
768 37d59b27 Kostas Papadimitriou
769 4e03ba30 Kostas Papadimitriou
    resource_catalog = json.dumps(resource_catalog)
770 4e03ba30 Kostas Papadimitriou
    resource_groups = json.dumps(resource_groups)
771 37d59b27 Kostas Papadimitriou
    resources_order = json.dumps(resources_meta.get('resources_order'))
772 401089d8 Kostas Papadimitriou
773 666c7490 Sofia Papagiannaki
    return render_response('im/resource_usage.html',
774 3cbd5e47 Olga Brani
                           context_instance=get_context(request),
775 4e03ba30 Kostas Papadimitriou
                           resource_catalog=resource_catalog,
776 4e03ba30 Kostas Papadimitriou
                           resource_groups=resource_groups,
777 4e03ba30 Kostas Papadimitriou
                           resources_order=resources_order,
778 4e03ba30 Kostas Papadimitriou
                           current_usage=current_usage,
779 e7cb4085 Kostas Papadimitriou
                           token_cookie_name=settings.COOKIE_NAME,
780 4e03ba30 Kostas Papadimitriou
                           usage_update_interval=
781 e7cb4085 Kostas Papadimitriou
                           settings.USAGE_UPDATE_INTERVAL)
782 4e03ba30 Kostas Papadimitriou
783 9a06d96f Olga Brani
784 f432088a Kostas Papadimitriou
# TODO: action only on POST and user should confirm the removal
785 d2633501 Kostas Papadimitriou
@require_http_methods(["GET", "POST"])
786 222305b7 Sofia Papagiannaki
@cookie_fix
787 9d20fe23 Kostas Papadimitriou
@valid_astakos_user_required
788 d2633501 Kostas Papadimitriou
def remove_auth_provider(request, pk):
789 f432088a Kostas Papadimitriou
    try:
790 9d20fe23 Kostas Papadimitriou
        provider = request.user.auth_providers.get(pk=int(pk)).settings
791 f432088a Kostas Papadimitriou
    except AstakosUserAuthProvider.DoesNotExist:
792 f432088a Kostas Papadimitriou
        raise Http404
793 f432088a Kostas Papadimitriou
794 9d20fe23 Kostas Papadimitriou
    if provider.get_remove_policy:
795 9d20fe23 Kostas Papadimitriou
        messages.success(request, provider.get_removed_msg)
796 9d20fe23 Kostas Papadimitriou
        provider.remove_from_user()
797 d2633501 Kostas Papadimitriou
        return HttpResponseRedirect(reverse('edit_profile'))
798 d2633501 Kostas Papadimitriou
    else:
799 f432088a Kostas Papadimitriou
        raise PermissionDenied
800 5ebebb20 Olga Brani
801 792c2f3b Olga Brani
802 9d20fe23 Kostas Papadimitriou
@require_http_methods(["GET"])
803 9d20fe23 Kostas Papadimitriou
@required_auth_methods_assigned(allow_access=True)
804 9d20fe23 Kostas Papadimitriou
@login_required
805 222305b7 Sofia Papagiannaki
@cookie_fix
806 9d20fe23 Kostas Papadimitriou
@signed_terms_required
807 003d8fcf Olga Brani
def landing(request):
808 0156e40c Kostas Papadimitriou
    context = {'services': Service.catalog(orderfor='dashboard')}
809 003d8fcf Olga Brani
    return render_response(
810 003d8fcf Olga Brani
        'im/landing.html',
811 0156e40c Kostas Papadimitriou
        context_instance=get_context(request), **context)
812 b87429e1 Olga Brani
813 ca5148f2 Kostas Papadimitriou
814 b87429e1 Olga Brani
def api_access(request):
815 b87429e1 Olga Brani
    return render_response(
816 b87429e1 Olga Brani
        'im/api_access.html',
817 ca5148f2 Kostas Papadimitriou
        context_instance=get_context(request))
818 0be81d73 Sofia Papagiannaki
819 0be81d73 Sofia Papagiannaki
@cookie_fix
820 0be81d73 Sofia Papagiannaki
def get_menu(request, with_extra_links=False, with_signout=True):
821 0be81d73 Sofia Papagiannaki
    user = request.user
822 0be81d73 Sofia Papagiannaki
    index_url = reverse('index')
823 0be81d73 Sofia Papagiannaki
824 0be81d73 Sofia Papagiannaki
    if isinstance(user, User) and user.is_authenticated():
825 0be81d73 Sofia Papagiannaki
        l = []
826 0be81d73 Sofia Papagiannaki
        append = l.append
827 0be81d73 Sofia Papagiannaki
        item = MenuItem
828 0be81d73 Sofia Papagiannaki
        item.current_path = request.build_absolute_uri(request.path)
829 0be81d73 Sofia Papagiannaki
        append(item(url=request.build_absolute_uri(reverse('index')),
830 0be81d73 Sofia Papagiannaki
                    name=user.email))
831 0be81d73 Sofia Papagiannaki
        if with_extra_links:
832 0be81d73 Sofia Papagiannaki
            append(item(url=request.build_absolute_uri(reverse('landing')),
833 0be81d73 Sofia Papagiannaki
                        name="Overview"))
834 0be81d73 Sofia Papagiannaki
        if with_signout:
835 0be81d73 Sofia Papagiannaki
            append(item(url=request.build_absolute_uri(reverse('landing')),
836 0be81d73 Sofia Papagiannaki
                        name="Dashboard"))
837 0be81d73 Sofia Papagiannaki
        if with_extra_links:
838 0be81d73 Sofia Papagiannaki
            append(item(url=request.build_absolute_uri(reverse('edit_profile')),
839 0be81d73 Sofia Papagiannaki
                        name="Profile"))
840 0be81d73 Sofia Papagiannaki
841 0be81d73 Sofia Papagiannaki
        if with_extra_links:
842 0be81d73 Sofia Papagiannaki
            if settings.INVITATIONS_ENABLED:
843 0be81d73 Sofia Papagiannaki
                append(item(url=request.build_absolute_uri(reverse('invite')),
844 0be81d73 Sofia Papagiannaki
                            name="Invitations"))
845 0be81d73 Sofia Papagiannaki
846 0be81d73 Sofia Papagiannaki
            append(item(url=request.build_absolute_uri(reverse('resource_usage')),
847 0be81d73 Sofia Papagiannaki
                        name="Usage"))
848 0be81d73 Sofia Papagiannaki
849 0be81d73 Sofia Papagiannaki
            if settings.PROJECTS_VISIBLE:
850 0be81d73 Sofia Papagiannaki
                append(item(url=request.build_absolute_uri(reverse('project_list')),
851 0be81d73 Sofia Papagiannaki
                            name="Projects"))
852 0be81d73 Sofia Papagiannaki
853 0be81d73 Sofia Papagiannaki
            append(item(url=request.build_absolute_uri(reverse('feedback')),
854 0be81d73 Sofia Papagiannaki
                        name="Contact"))
855 0be81d73 Sofia Papagiannaki
        if with_signout:
856 0be81d73 Sofia Papagiannaki
            append(item(url=request.build_absolute_uri(reverse('logout')),
857 0be81d73 Sofia Papagiannaki
                        name="Sign out"))
858 0be81d73 Sofia Papagiannaki
    else:
859 0be81d73 Sofia Papagiannaki
        l = [{'url': request.build_absolute_uri(index_url),
860 0be81d73 Sofia Papagiannaki
              'name': _("Sign in")}]
861 0be81d73 Sofia Papagiannaki
862 0be81d73 Sofia Papagiannaki
    callback = request.GET.get('callback', None)
863 0be81d73 Sofia Papagiannaki
    data = json.dumps(tuple(l))
864 0be81d73 Sofia Papagiannaki
    mimetype = 'application/json'
865 0be81d73 Sofia Papagiannaki
866 0be81d73 Sofia Papagiannaki
    if callback:
867 0be81d73 Sofia Papagiannaki
        mimetype = 'application/javascript'
868 0be81d73 Sofia Papagiannaki
        data = '%s(%s)' % (callback, data)
869 0be81d73 Sofia Papagiannaki
870 0be81d73 Sofia Papagiannaki
    return HttpResponse(content=data, mimetype=mimetype)
871 0be81d73 Sofia Papagiannaki
872 0be81d73 Sofia Papagiannaki
873 0be81d73 Sofia Papagiannaki
class MenuItem(dict):
874 0be81d73 Sofia Papagiannaki
    current_path = ''
875 0be81d73 Sofia Papagiannaki
876 0be81d73 Sofia Papagiannaki
    def __init__(self, *args, **kwargs):
877 0be81d73 Sofia Papagiannaki
        super(MenuItem, self).__init__(*args, **kwargs)
878 0be81d73 Sofia Papagiannaki
        if kwargs.get('url') or kwargs.get('submenu'):
879 0be81d73 Sofia Papagiannaki
            self.__set_is_active__()
880 0be81d73 Sofia Papagiannaki
881 0be81d73 Sofia Papagiannaki
    def __setitem__(self, key, value):
882 0be81d73 Sofia Papagiannaki
        super(MenuItem, self).__setitem__(key, value)
883 0be81d73 Sofia Papagiannaki
        if key in ('url', 'submenu'):
884 0be81d73 Sofia Papagiannaki
            self.__set_is_active__()
885 0be81d73 Sofia Papagiannaki
886 0be81d73 Sofia Papagiannaki
    def __set_is_active__(self):
887 0be81d73 Sofia Papagiannaki
        if self.get('is_active'):
888 0be81d73 Sofia Papagiannaki
            return
889 0be81d73 Sofia Papagiannaki
        if self.current_path.startswith(self.get('url')):
890 0be81d73 Sofia Papagiannaki
            self.__setitem__('is_active', True)
891 0be81d73 Sofia Papagiannaki
        else:
892 0be81d73 Sofia Papagiannaki
            submenu = self.get('submenu', ())
893 0be81d73 Sofia Papagiannaki
            current = (i for i in submenu if i.get('url') == self.current_path)
894 0be81d73 Sofia Papagiannaki
            try:
895 0be81d73 Sofia Papagiannaki
                current_node = current.next()
896 0be81d73 Sofia Papagiannaki
                if not current_node.get('is_active'):
897 0be81d73 Sofia Papagiannaki
                    current_node.__setitem__('is_active', True)
898 0be81d73 Sofia Papagiannaki
                self.__setitem__('is_active', True)
899 0be81d73 Sofia Papagiannaki
            except StopIteration:
900 0be81d73 Sofia Papagiannaki
                return
901 0be81d73 Sofia Papagiannaki
902 0be81d73 Sofia Papagiannaki
    def __setattribute__(self, name, value):
903 0be81d73 Sofia Papagiannaki
        super(MenuItem, self).__setattribute__(name, value)
904 0be81d73 Sofia Papagiannaki
        if name == 'current_path':
905 0be81d73 Sofia Papagiannaki
            self.__set_is_active__()