Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (33.8 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 0be81d73 Sofia Papagiannaki
from django.contrib.auth.models import User
44 01ac12d5 Sofia Papagiannaki
from django.core.urlresolvers import reverse
45 01ac12d5 Sofia Papagiannaki
from django.db import transaction
46 3e0a032d Sofia Papagiannaki
from django.http import HttpResponse, HttpResponseRedirect, Http404
47 01ac12d5 Sofia Papagiannaki
from django.shortcuts import redirect
48 01ac12d5 Sofia Papagiannaki
from django.utils.translation import ugettext as _
49 3e0a032d Sofia Papagiannaki
from django.core.exceptions import PermissionDenied
50 9a06d96f Olga Brani
from django.views.decorators.http import require_http_methods
51 96b44c04 Sofia Papagiannaki
from django.utils import simplejson as json
52 734107ef Kostas Papadimitriou
53 7763f5c6 Kostas Papadimitriou
from synnefo.lib import join_urls
54 7763f5c6 Kostas Papadimitriou
55 c630fee6 Kostas Papadimitriou
import astakos.im.messages as astakos_messages
56 c630fee6 Kostas Papadimitriou
57 e7cb4085 Kostas Papadimitriou
from astakos.im import activation_backends
58 3e0a032d Sofia Papagiannaki
from astakos.im.models import AstakosUser, ApprovalTerms, EmailChange, \
59 bea584e1 Giorgos Korfiatis
    AstakosUserAuthProvider, PendingThirdPartyUser, Component
60 3e0a032d Sofia Papagiannaki
from astakos.im.util import get_context, prepare_response, get_query, \
61 3e0a032d Sofia Papagiannaki
    restrict_next
62 3e0a032d Sofia Papagiannaki
from astakos.im.forms import LoginForm, InvitationForm, FeedbackForm, \
63 3e0a032d Sofia Papagiannaki
    SignApprovalTermsForm, EmailChangeForm
64 f7400729 Kostas Papadimitriou
from astakos.im.forms import ExtendedProfileForm as ProfileForm
65 3e0a032d Sofia Papagiannaki
from astakos.im.functions import send_feedback, logout as auth_logout, \
66 3e0a032d Sofia Papagiannaki
    invite as invite_func
67 e7cb4085 Kostas Papadimitriou
from astakos.im import settings
68 8998f09a Sofia Papagiannaki
from astakos.im import presentation
69 9d20fe23 Kostas Papadimitriou
from astakos.im import auth_providers as auth
70 4e03ba30 Kostas Papadimitriou
from astakos.im import quotas
71 70e11eaa Sofia Papagiannaki
from astakos.im.views.util import render_response, _resources_catalog
72 70e11eaa Sofia Papagiannaki
from astakos.im.views.decorators import cookie_fix, signed_terms_required,\
73 b6496f0c Kostas Papadimitriou
    required_auth_methods_assigned, valid_astakos_user_required, login_required
74 ae497612 Olga Brani
75 e015e9e6 Sofia Papagiannaki
logger = logging.getLogger(__name__)
76 e015e9e6 Sofia Papagiannaki
77 9a06d96f Olga Brani
78 9a06d96f Olga Brani
@require_http_methods(["GET", "POST"])
79 222305b7 Sofia Papagiannaki
@cookie_fix
80 270dd48d Sofia Papagiannaki
@signed_terms_required
81 1ecda536 Kostas Papadimitriou
def login(request, template_name='im/login.html', extra_context=None):
82 890b0eaf Sofia Papagiannaki
    """
83 1ecda536 Kostas Papadimitriou
    Renders login page.
84 176023aa Kostas Papadimitriou

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

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

91 890b0eaf Sofia Papagiannaki
    ``extra_context``
92 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
93 890b0eaf Sofia Papagiannaki
    """
94 1ecda536 Kostas Papadimitriou
95 1f3b4b39 Sofia Papagiannaki
    extra_context = extra_context or {}
96 792c2f3b Olga Brani
97 f7cf5257 Kostas Papadimitriou
    third_party_token = request.GET.get('key', False)
98 f7cf5257 Kostas Papadimitriou
    if third_party_token:
99 f7cf5257 Kostas Papadimitriou
        messages.info(request, astakos_messages.AUTH_PROVIDER_LOGIN_TO_ADD)
100 f7cf5257 Kostas Papadimitriou
101 1ecda536 Kostas Papadimitriou
    if request.user.is_authenticated():
102 1ecda536 Kostas Papadimitriou
        return HttpResponseRedirect(reverse('landing'))
103 1ecda536 Kostas Papadimitriou
104 ef20ea07 Sofia Papagiannaki
    return render_response(
105 ef20ea07 Sofia Papagiannaki
        template_name,
106 1ecda536 Kostas Papadimitriou
        login_form=LoginForm(request=request),
107 1ecda536 Kostas Papadimitriou
        context_instance=get_context(request, extra_context)
108 ef20ea07 Sofia Papagiannaki
    )
109 5ce3ce4f Sofia Papagiannaki
110 64cd4730 Antony Chazapis
111 1ecda536 Kostas Papadimitriou
@require_http_methods(["GET", "POST"])
112 1ecda536 Kostas Papadimitriou
@cookie_fix
113 1ecda536 Kostas Papadimitriou
@signed_terms_required
114 1ecda536 Kostas Papadimitriou
def index(request, authenticated_redirect='landing',
115 1ecda536 Kostas Papadimitriou
          anonymous_redirect='login', extra_context=None):
116 1ecda536 Kostas Papadimitriou
    """
117 1ecda536 Kostas Papadimitriou
    If user is authenticated redirect to ``authenticated_redirect`` url.
118 1ecda536 Kostas Papadimitriou
    Otherwise redirects to ``anonymous_redirect`` url.
119 1ecda536 Kostas Papadimitriou

120 1ecda536 Kostas Papadimitriou
    """
121 1ecda536 Kostas Papadimitriou
    if request.user.is_authenticated():
122 1ecda536 Kostas Papadimitriou
        return HttpResponseRedirect(reverse(authenticated_redirect))
123 1ecda536 Kostas Papadimitriou
    return HttpResponseRedirect(reverse(anonymous_redirect))
124 1ecda536 Kostas Papadimitriou
125 1ecda536 Kostas Papadimitriou
126 0504f010 Kostas Papadimitriou
@require_http_methods(["POST"])
127 222305b7 Sofia Papagiannaki
@cookie_fix
128 0504f010 Kostas Papadimitriou
@valid_astakos_user_required
129 0504f010 Kostas Papadimitriou
def update_token(request):
130 0504f010 Kostas Papadimitriou
    """
131 0504f010 Kostas Papadimitriou
    Update api token view.
132 0504f010 Kostas Papadimitriou
    """
133 0504f010 Kostas Papadimitriou
    user = request.user
134 0504f010 Kostas Papadimitriou
    user.renew_token()
135 0504f010 Kostas Papadimitriou
    user.save()
136 0504f010 Kostas Papadimitriou
    messages.success(request, astakos_messages.TOKEN_UPDATED)
137 14c76abe Kostas Papadimitriou
    return HttpResponseRedirect(reverse('api_access'))
138 0504f010 Kostas Papadimitriou
139 0504f010 Kostas Papadimitriou
140 9a06d96f Olga Brani
@require_http_methods(["GET", "POST"])
141 222305b7 Sofia Papagiannaki
@cookie_fix
142 badcb2a9 Kostas Papadimitriou
@valid_astakos_user_required
143 890b0eaf Sofia Papagiannaki
@transaction.commit_manually
144 aab4d540 Sofia Papagiannaki
def invite(request, template_name='im/invitations.html', extra_context=None):
145 890b0eaf Sofia Papagiannaki
    """
146 890b0eaf Sofia Papagiannaki
    Allows a user to invite somebody else.
147 176023aa Kostas Papadimitriou

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

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

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

157 890b0eaf Sofia Papagiannaki
    **Arguments**
158 176023aa Kostas Papadimitriou

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

163 890b0eaf Sofia Papagiannaki
    ``extra_context``
164 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
165 176023aa Kostas Papadimitriou

166 890b0eaf Sofia Papagiannaki
    **Template:**
167 176023aa Kostas Papadimitriou

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

170 890b0eaf Sofia Papagiannaki
    **Settings:**
171 176023aa Kostas Papadimitriou

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

174 890b0eaf Sofia Papagiannaki
    * LOGIN_URL: login uri
175 890b0eaf Sofia Papagiannaki
    """
176 1f3b4b39 Sofia Papagiannaki
    extra_context = extra_context or {}
177 64cd4730 Antony Chazapis
    status = None
178 64cd4730 Antony Chazapis
    message = None
179 8f5a3a06 Sofia Papagiannaki
    form = InvitationForm()
180 5ce3ce4f Sofia Papagiannaki
181 18ffbee1 Sofia Papagiannaki
    inviter = request.user
182 64cd4730 Antony Chazapis
    if request.method == 'POST':
183 8f5a3a06 Sofia Papagiannaki
        form = InvitationForm(request.POST)
184 64cd4730 Antony Chazapis
        if inviter.invitations > 0:
185 8f5a3a06 Sofia Papagiannaki
            if form.is_valid():
186 8f5a3a06 Sofia Papagiannaki
                try:
187 9a06d96f Olga Brani
                    email = form.cleaned_data.get('username')
188 9a06d96f Olga Brani
                    realname = form.cleaned_data.get('realname')
189 9cdb86fd Sofia Papagiannaki
                    invite_func(inviter, email, realname)
190 ae497612 Olga Brani
                    message = _(astakos_messages.INVITATION_SENT) % locals()
191 24406ae3 Sofia Papagiannaki
                    messages.success(request, message)
192 e7cb4085 Kostas Papadimitriou
                except Exception, e:
193 18ffbee1 Sofia Papagiannaki
                    transaction.rollback()
194 e7cb4085 Kostas Papadimitriou
                    raise
195 18ffbee1 Sofia Papagiannaki
                else:
196 18ffbee1 Sofia Papagiannaki
                    transaction.commit()
197 64cd4730 Antony Chazapis
        else:
198 ae497612 Olga Brani
            message = _(astakos_messages.MAX_INVITATION_NUMBER_REACHED)
199 24406ae3 Sofia Papagiannaki
            messages.error(request, message)
200 176023aa Kostas Papadimitriou
201 a196eb7e Sofia Papagiannaki
    sent = [{'email': inv.username,
202 d6ae71a2 root
             'realname': inv.realname,
203 d6ae71a2 root
             'is_consumed': inv.is_consumed}
204 5ce3ce4f Sofia Papagiannaki
            for inv in request.user.invitations_sent.all()]
205 77e2ad52 root
    kwargs = {'inviter': inviter,
206 5ce3ce4f Sofia Papagiannaki
              'sent': sent}
207 0905ccd2 Sofia Papagiannaki
    context = get_context(request, extra_context, **kwargs)
208 0905ccd2 Sofia Papagiannaki
    return render_response(template_name,
209 5ce3ce4f Sofia Papagiannaki
                           invitation_form=form,
210 5ce3ce4f Sofia Papagiannaki
                           context_instance=context)
211 5ce3ce4f Sofia Papagiannaki
212 64cd4730 Antony Chazapis
213 9a06d96f Olga Brani
@require_http_methods(["GET", "POST"])
214 7763f5c6 Kostas Papadimitriou
@required_auth_methods_assigned()
215 7763f5c6 Kostas Papadimitriou
@login_required
216 7763f5c6 Kostas Papadimitriou
@cookie_fix
217 7763f5c6 Kostas Papadimitriou
@signed_terms_required
218 7763f5c6 Kostas Papadimitriou
def api_access(request, template_name='im/api_access.html',
219 7763f5c6 Kostas Papadimitriou
               extra_context=None):
220 7763f5c6 Kostas Papadimitriou
    """
221 7763f5c6 Kostas Papadimitriou
    API access view.
222 7763f5c6 Kostas Papadimitriou
    """
223 7763f5c6 Kostas Papadimitriou
    context = {}
224 7763f5c6 Kostas Papadimitriou
225 d558ca0b Kostas Papadimitriou
    token_url = join_urls(settings.BASE_HOST, reverse('tokens_authenticate'))
226 7763f5c6 Kostas Papadimitriou
    context['services'] = Component.catalog()
227 7763f5c6 Kostas Papadimitriou
    context['token_url'] = token_url
228 7763f5c6 Kostas Papadimitriou
    context['client_url'] = settings.API_CLIENT_URL
229 7763f5c6 Kostas Papadimitriou
230 7763f5c6 Kostas Papadimitriou
    if extra_context:
231 7763f5c6 Kostas Papadimitriou
        context.update(extra_context)
232 7763f5c6 Kostas Papadimitriou
    context_instance = get_context(request, context)
233 7763f5c6 Kostas Papadimitriou
    return render_response(template_name,
234 7763f5c6 Kostas Papadimitriou
                           context_instance=context_instance)
235 7763f5c6 Kostas Papadimitriou
236 7763f5c6 Kostas Papadimitriou
237 7763f5c6 Kostas Papadimitriou
@require_http_methods(["GET", "POST"])
238 9d20fe23 Kostas Papadimitriou
@required_auth_methods_assigned(allow_access=True)
239 890b0eaf Sofia Papagiannaki
@login_required
240 222305b7 Sofia Papagiannaki
@cookie_fix
241 270dd48d Sofia Papagiannaki
@signed_terms_required
242 aab4d540 Sofia Papagiannaki
def edit_profile(request, template_name='im/profile.html', extra_context=None):
243 890b0eaf Sofia Papagiannaki
    """
244 890b0eaf Sofia Papagiannaki
    Allows a user to edit his/her profile.
245 176023aa Kostas Papadimitriou

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

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

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

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

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

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

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

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

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

269 92defad4 Sofia Papagiannaki
    * LOGIN_URL: login uri
270 890b0eaf Sofia Papagiannaki
    """
271 aab4d540 Sofia Papagiannaki
    extra_context = extra_context or {}
272 bf0c6de5 Sofia Papagiannaki
    form = ProfileForm(
273 bf0c6de5 Sofia Papagiannaki
        instance=request.user,
274 bf0c6de5 Sofia Papagiannaki
        session_key=request.session.session_key
275 bf0c6de5 Sofia Papagiannaki
    )
276 15efc749 Sofia Papagiannaki
    extra_context['next'] = request.GET.get('next')
277 64cd4730 Antony Chazapis
    if request.method == 'POST':
278 bf0c6de5 Sofia Papagiannaki
        form = ProfileForm(
279 bf0c6de5 Sofia Papagiannaki
            request.POST,
280 bf0c6de5 Sofia Papagiannaki
            instance=request.user,
281 bf0c6de5 Sofia Papagiannaki
            session_key=request.session.session_key
282 bf0c6de5 Sofia Papagiannaki
        )
283 890b0eaf Sofia Papagiannaki
        if form.is_valid():
284 64cd4730 Antony Chazapis
            try:
285 c301698f Sofia Papagiannaki
                prev_token = request.user.auth_token
286 3fbf7863 Kostas Papadimitriou
                user = form.save(request=request)
287 217994f8 Sofia Papagiannaki
                next = restrict_next(
288 217994f8 Sofia Papagiannaki
                    request.POST.get('next'),
289 8998f09a Sofia Papagiannaki
                    domain=settings.COOKIE_DOMAIN
290 217994f8 Sofia Papagiannaki
                )
291 ae497612 Olga Brani
                msg = _(astakos_messages.PROFILE_UPDATED)
292 24406ae3 Sofia Papagiannaki
                messages.success(request, msg)
293 2da6f56b Kostas Papadimitriou
294 2da6f56b Kostas Papadimitriou
                if form.email_changed:
295 2da6f56b Kostas Papadimitriou
                    msg = _(astakos_messages.EMAIL_CHANGE_REGISTERED)
296 2da6f56b Kostas Papadimitriou
                    messages.success(request, msg)
297 2da6f56b Kostas Papadimitriou
                if form.password_changed:
298 2da6f56b Kostas Papadimitriou
                    msg = _(astakos_messages.PASSWORD_CHANGED)
299 2da6f56b Kostas Papadimitriou
                    messages.success(request, msg)
300 2da6f56b Kostas Papadimitriou
301 f7400729 Kostas Papadimitriou
                if next:
302 f7400729 Kostas Papadimitriou
                    return redirect(next)
303 f7400729 Kostas Papadimitriou
                else:
304 f7400729 Kostas Papadimitriou
                    return redirect(reverse('edit_profile'))
305 890b0eaf Sofia Papagiannaki
            except ValueError, ve:
306 24406ae3 Sofia Papagiannaki
                messages.success(request, ve)
307 23447441 Sofia Papagiannaki
    elif request.method == "GET":
308 792c2f3b Olga Brani
        request.user.is_verified = True
309 792c2f3b Olga Brani
        request.user.save()
310 792c2f3b Olga Brani
311 792c2f3b Olga Brani
    # existing providers
312 9d20fe23 Kostas Papadimitriou
    user_providers = request.user.get_enabled_auth_providers()
313 9d20fe23 Kostas Papadimitriou
    user_disabled_providers = request.user.get_disabled_auth_providers()
314 792c2f3b Olga Brani
315 792c2f3b Olga Brani
    # providers that user can add
316 792c2f3b Olga Brani
    user_available_providers = request.user.get_available_auth_providers()
317 792c2f3b Olga Brani
318 bea584e1 Giorgos Korfiatis
    extra_context['services'] = Component.catalog().values()
319 0905ccd2 Sofia Papagiannaki
    return render_response(template_name,
320 e7cb4085 Kostas Papadimitriou
                           profile_form=form,
321 e7cb4085 Kostas Papadimitriou
                           user_providers=user_providers,
322 e7cb4085 Kostas Papadimitriou
                           user_disabled_providers=user_disabled_providers,
323 e7cb4085 Kostas Papadimitriou
                           user_available_providers=user_available_providers,
324 e7cb4085 Kostas Papadimitriou
                           context_instance=get_context(request,
325 c301698f Sofia Papagiannaki
                                                          extra_context))
326 5ce3ce4f Sofia Papagiannaki
327 64cd4730 Antony Chazapis
328 10ed0073 Sofia Papagiannaki
@transaction.commit_manually
329 9a06d96f Olga Brani
@require_http_methods(["GET", "POST"])
330 222305b7 Sofia Papagiannaki
@cookie_fix
331 e7cb4085 Kostas Papadimitriou
def signup(request, template_name='im/signup.html', on_success='index',
332 e7cb4085 Kostas Papadimitriou
           extra_context=None, activation_backend=None):
333 890b0eaf Sofia Papagiannaki
    """
334 890b0eaf Sofia Papagiannaki
    Allows a user to create a local account.
335 176023aa Kostas Papadimitriou

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

339 e7cb4085 Kostas Papadimitriou
    The user activation will be delegated to the backend specified by the
340 e7cb4085 Kostas Papadimitriou
    ``activation_backend`` keyword argument if present, otherwise to the
341 e7cb4085 Kostas Papadimitriou
    ``astakos.im.activation_backends.InvitationBackend`` if
342 e7cb4085 Kostas Papadimitriou
    settings.ASTAKOS_INVITATIONS_ENABLED is True or
343 e7cb4085 Kostas Papadimitriou
    ``astakos.im.activation_backends.SimpleBackend`` if not (see
344 e7cb4085 Kostas Papadimitriou
    activation_backends);
345 5ce3ce4f Sofia Papagiannaki

346 e7cb4085 Kostas Papadimitriou
    Upon successful user creation, if ``next`` url parameter is present the
347 e7cb4085 Kostas Papadimitriou
    user is redirected there otherwise renders the same page with a success
348 e7cb4085 Kostas Papadimitriou
    message.
349 5ce3ce4f Sofia Papagiannaki

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

352 890b0eaf Sofia Papagiannaki
    **Arguments**
353 5ce3ce4f Sofia Papagiannaki

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

358 890b0eaf Sofia Papagiannaki
    ``extra_context``
359 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
360 176023aa Kostas Papadimitriou

361 43332a76 Kostas Papadimitriou
    ``on_success``
362 43332a76 Kostas Papadimitriou
        Resolvable view name to redirect on registration success.
363 43332a76 Kostas Papadimitriou

364 890b0eaf Sofia Papagiannaki
    **Template:**
365 5ce3ce4f Sofia Papagiannaki

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

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

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

488 890b0eaf Sofia Papagiannaki
    **Arguments**
489 176023aa Kostas Papadimitriou

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

494 890b0eaf Sofia Papagiannaki
    ``extra_context``
495 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
496 176023aa Kostas Papadimitriou

497 890b0eaf Sofia Papagiannaki
    **Template:**
498 176023aa Kostas Papadimitriou

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

501 890b0eaf Sofia Papagiannaki
    **Settings:**
502 176023aa Kostas Papadimitriou

503 92defad4 Sofia Papagiannaki
    * LOGIN_URL: login uri
504 890b0eaf Sofia Papagiannaki
    """
505 1f3b4b39 Sofia Papagiannaki
    extra_context = extra_context or {}
506 64cd4730 Antony Chazapis
    if request.method == 'GET':
507 890b0eaf Sofia Papagiannaki
        form = FeedbackForm()
508 890b0eaf Sofia Papagiannaki
    if request.method == 'POST':
509 890b0eaf Sofia Papagiannaki
        if not request.user:
510 890b0eaf Sofia Papagiannaki
            return HttpResponse('Unauthorized', status=401)
511 176023aa Kostas Papadimitriou
512 890b0eaf Sofia Papagiannaki
        form = FeedbackForm(request.POST)
513 890b0eaf Sofia Papagiannaki
        if form.is_valid():
514 e9083112 Sofia Papagiannaki
            msg = form.cleaned_data['feedback_msg']
515 8f5a3a06 Sofia Papagiannaki
            data = form.cleaned_data['feedback_data']
516 860bb9f7 Sofia Papagiannaki
            send_feedback(msg, data, request.user, email_template_name)
517 860bb9f7 Sofia Papagiannaki
            message = _(astakos_messages.FEEDBACK_SENT)
518 860bb9f7 Sofia Papagiannaki
            messages.success(request, message)
519 b9f8f48a Kostas Papadimitriou
            return HttpResponseRedirect(reverse('feedback'))
520 e7cb4085 Kostas Papadimitriou
521 890b0eaf Sofia Papagiannaki
    return render_response(template_name,
522 5ce3ce4f Sofia Papagiannaki
                           feedback_form=form,
523 e7cb4085 Kostas Papadimitriou
                           context_instance=get_context(request,
524 e7cb4085 Kostas Papadimitriou
                                                        extra_context))
525 5ce3ce4f Sofia Papagiannaki
526 15efc749 Sofia Papagiannaki
527 217994f8 Sofia Papagiannaki
@require_http_methods(["GET"])
528 222305b7 Sofia Papagiannaki
@cookie_fix
529 e7cb4085 Kostas Papadimitriou
def logout(request, template='registration/logged_out.html',
530 e7cb4085 Kostas Papadimitriou
           extra_context=None):
531 63ecdd20 Sofia Papagiannaki
    """
532 b2ffa772 Sofia Papagiannaki
    Wraps `django.contrib.auth.logout`.
533 63ecdd20 Sofia Papagiannaki
    """
534 1f3b4b39 Sofia Papagiannaki
    extra_context = extra_context or {}
535 7482228b Sofia Papagiannaki
    response = HttpResponse()
536 8e45d6fd Sofia Papagiannaki
    if request.user.is_authenticated():
537 8e45d6fd Sofia Papagiannaki
        email = request.user.email
538 8e45d6fd Sofia Papagiannaki
        auth_logout(request)
539 c630fee6 Kostas Papadimitriou
    else:
540 c630fee6 Kostas Papadimitriou
        response['Location'] = reverse('index')
541 c630fee6 Kostas Papadimitriou
        response.status_code = 301
542 c630fee6 Kostas Papadimitriou
        return response
543 c630fee6 Kostas Papadimitriou
544 217994f8 Sofia Papagiannaki
    next = restrict_next(
545 217994f8 Sofia Papagiannaki
        request.GET.get('next'),
546 8998f09a Sofia Papagiannaki
        domain=settings.COOKIE_DOMAIN
547 217994f8 Sofia Papagiannaki
    )
548 c630fee6 Kostas Papadimitriou
549 63ecdd20 Sofia Papagiannaki
    if next:
550 63ecdd20 Sofia Papagiannaki
        response['Location'] = next
551 63ecdd20 Sofia Papagiannaki
        response.status_code = 302
552 8998f09a Sofia Papagiannaki
    elif settings.LOGOUT_NEXT:
553 8998f09a Sofia Papagiannaki
        response['Location'] = settings.LOGOUT_NEXT
554 0d02a287 Sofia Papagiannaki
        response.status_code = 301
555 b2ffa772 Sofia Papagiannaki
    else:
556 9d20fe23 Kostas Papadimitriou
        last_provider = request.COOKIES.get('astakos_last_login_method', 'local')
557 9d20fe23 Kostas Papadimitriou
        provider = auth.get_provider(last_provider)
558 9d20fe23 Kostas Papadimitriou
        message = provider.get_logout_success_msg
559 9d20fe23 Kostas Papadimitriou
        extra = provider.get_logout_success_extra_msg
560 9d20fe23 Kostas Papadimitriou
        if extra:
561 9d20fe23 Kostas Papadimitriou
            message += "<br />"  + extra
562 d21d422a Kostas Papadimitriou
        messages.success(request, message)
563 c630fee6 Kostas Papadimitriou
        response['Location'] = reverse('index')
564 c630fee6 Kostas Papadimitriou
        response.status_code = 301
565 49df775e Sofia Papagiannaki
    return response
566 2126d85d Sofia Papagiannaki
567 5ce3ce4f Sofia Papagiannaki
568 9a06d96f Olga Brani
@require_http_methods(["GET", "POST"])
569 222305b7 Sofia Papagiannaki
@cookie_fix
570 683cf244 Sofia Papagiannaki
@transaction.commit_manually
571 3bb604eb Sofia Papagiannaki
def activate(request, greeting_email_template_name='im/welcome_email.txt',
572 3bb604eb Sofia Papagiannaki
             helpdesk_email_template_name='im/helpdesk_notification.txt'):
573 2126d85d Sofia Papagiannaki
    """
574 e7cb4085 Kostas Papadimitriou
    Activates the user identified by the ``auth`` request parameter, sends a
575 e7cb4085 Kostas Papadimitriou
    welcome email and renews the user token.
576 176023aa Kostas Papadimitriou

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