Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / views.py @ 49790d9d

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

117 890b0eaf Sofia Papagiannaki
    **Arguments**
118 176023aa Kostas Papadimitriou

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

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

127 890b0eaf Sofia Papagiannaki
    ``extra_context``
128 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
129 176023aa Kostas Papadimitriou

130 890b0eaf Sofia Papagiannaki
    **Template:**
131 176023aa Kostas Papadimitriou

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

232 890b0eaf Sofia Papagiannaki
    **Arguments**
233 176023aa Kostas Papadimitriou

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

238 890b0eaf Sofia Papagiannaki
    ``extra_context``
239 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
240 176023aa Kostas Papadimitriou

241 890b0eaf Sofia Papagiannaki
    **Template:**
242 176023aa Kostas Papadimitriou

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

245 92defad4 Sofia Papagiannaki
    **Settings:**
246 176023aa Kostas Papadimitriou

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

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

279 890b0eaf Sofia Papagiannaki
    In case of GET request renders a form for providing the user information.
280 890b0eaf Sofia Papagiannaki
    In case of POST handles the signup.
281 176023aa Kostas Papadimitriou

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

298 176023aa Kostas Papadimitriou

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

303 890b0eaf Sofia Papagiannaki
    ``extra_context``
304 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
305 176023aa Kostas Papadimitriou

306 890b0eaf Sofia Papagiannaki
    **Template:**
307 890b0eaf Sofia Papagiannaki
    
308 8f5a3a06 Sofia Papagiannaki
    im/signup.html or ``template_name`` keyword argument.
309 1e685275 Sofia Papagiannaki
    im/signup_complete.html or ``on_success`` keyword argument. 
310 890b0eaf Sofia Papagiannaki
    """
311 0d02a287 Sofia Papagiannaki
    if request.user.is_authenticated():
312 0d02a287 Sofia Papagiannaki
        return HttpResponseRedirect(reverse('astakos.im.views.index'))
313 4e30244e Sofia Papagiannaki
    
314 0a569195 Sofia Papagiannaki
    provider = get_query(request).get('provider', 'local')
315 890b0eaf Sofia Papagiannaki
    try:
316 18ffbee1 Sofia Papagiannaki
        if not backend:
317 18ffbee1 Sofia Papagiannaki
            backend = get_backend(request)
318 8f5a3a06 Sofia Papagiannaki
        form = backend.get_signup_form(provider)
319 0a569195 Sofia Papagiannaki
    except Exception, e:
320 4e30244e Sofia Papagiannaki
        form = SimpleBackend(request).get_signup_form(provider)
321 18ffbee1 Sofia Papagiannaki
        messages.add_message(request, messages.ERROR, e)
322 8f5a3a06 Sofia Papagiannaki
    if request.method == 'POST':
323 8f5a3a06 Sofia Papagiannaki
        if form.is_valid():
324 18ffbee1 Sofia Papagiannaki
            user = form.save(commit=False)
325 8f5a3a06 Sofia Papagiannaki
            try:
326 8f5a3a06 Sofia Papagiannaki
                result = backend.handle_activation(user)
327 8f5a3a06 Sofia Papagiannaki
                status = messages.SUCCESS
328 18ffbee1 Sofia Papagiannaki
                message = result.message
329 18ffbee1 Sofia Papagiannaki
                user.save()
330 8f5a3a06 Sofia Papagiannaki
                if user and user.is_active:
331 8f5a3a06 Sofia Papagiannaki
                    next = request.POST.get('next', '')
332 8f5a3a06 Sofia Papagiannaki
                    return prepare_response(request, user, next=next)
333 8f5a3a06 Sofia Papagiannaki
                messages.add_message(request, status, message)
334 8f5a3a06 Sofia Papagiannaki
                return render_response(on_success,
335 8f5a3a06 Sofia Papagiannaki
                                       context_instance=get_context(request, extra_context))
336 18ffbee1 Sofia Papagiannaki
            except SendMailError, e:
337 18ffbee1 Sofia Papagiannaki
                status = messages.ERROR
338 18ffbee1 Sofia Papagiannaki
                message = e.message
339 18ffbee1 Sofia Papagiannaki
                messages.add_message(request, status, message)
340 18ffbee1 Sofia Papagiannaki
            except BaseException, e:
341 18ffbee1 Sofia Papagiannaki
                status = messages.ERROR
342 18ffbee1 Sofia Papagiannaki
                message = _('Something went wrong.')
343 18ffbee1 Sofia Papagiannaki
                messages.add_message(request, status, message)
344 0a569195 Sofia Papagiannaki
                logger.exception(e)
345 8f5a3a06 Sofia Papagiannaki
    return render_response(template_name,
346 18ffbee1 Sofia Papagiannaki
                           signup_form = form,
347 0a569195 Sofia Papagiannaki
                           provider = provider,
348 890b0eaf Sofia Papagiannaki
                           context_instance=get_context(request, extra_context))
349 64cd4730 Antony Chazapis
350 890b0eaf Sofia Papagiannaki
@login_required
351 270dd48d Sofia Papagiannaki
@signed_terms_required
352 8f5a3a06 Sofia Papagiannaki
def feedback(request, template_name='im/feedback.html', email_template_name='im/feedback_mail.txt', extra_context={}):
353 890b0eaf Sofia Papagiannaki
    """
354 890b0eaf Sofia Papagiannaki
    Allows a user to send feedback.
355 176023aa Kostas Papadimitriou

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

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

361 890b0eaf Sofia Papagiannaki
    **Arguments**
362 176023aa Kostas Papadimitriou

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

367 890b0eaf Sofia Papagiannaki
    ``extra_context``
368 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
369 176023aa Kostas Papadimitriou

370 890b0eaf Sofia Papagiannaki
    **Template:**
371 176023aa Kostas Papadimitriou

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

374 890b0eaf Sofia Papagiannaki
    **Settings:**
375 176023aa Kostas Papadimitriou

376 92defad4 Sofia Papagiannaki
    * LOGIN_URL: login uri
377 2cbaacd5 Sofia Papagiannaki
    * ASTAKOS_DEFAULT_CONTACT_EMAIL: List of feedback recipients
378 890b0eaf Sofia Papagiannaki
    """
379 64cd4730 Antony Chazapis
    if request.method == 'GET':
380 890b0eaf Sofia Papagiannaki
        form = FeedbackForm()
381 890b0eaf Sofia Papagiannaki
    if request.method == 'POST':
382 890b0eaf Sofia Papagiannaki
        if not request.user:
383 890b0eaf Sofia Papagiannaki
            return HttpResponse('Unauthorized', status=401)
384 176023aa Kostas Papadimitriou
385 890b0eaf Sofia Papagiannaki
        form = FeedbackForm(request.POST)
386 890b0eaf Sofia Papagiannaki
        if form.is_valid():
387 8f5a3a06 Sofia Papagiannaki
            msg = form.cleaned_data['feedback_msg'],
388 8f5a3a06 Sofia Papagiannaki
            data = form.cleaned_data['feedback_data']
389 538ccdd5 Sofia Papagiannaki
            try:
390 8f5a3a06 Sofia Papagiannaki
                send_feedback(msg, data, request.user, email_template_name)
391 8f5a3a06 Sofia Papagiannaki
            except SendMailError, e:
392 8f5a3a06 Sofia Papagiannaki
                message = e.message
393 8f5a3a06 Sofia Papagiannaki
                status = messages.ERROR
394 8f5a3a06 Sofia Papagiannaki
            else:
395 538ccdd5 Sofia Papagiannaki
                message = _('Feedback successfully sent')
396 538ccdd5 Sofia Papagiannaki
                status = messages.SUCCESS
397 538ccdd5 Sofia Papagiannaki
            messages.add_message(request, status, message)
398 890b0eaf Sofia Papagiannaki
    return render_response(template_name,
399 8f5a3a06 Sofia Papagiannaki
                           feedback_form = form,
400 6b4f9fb2 Sofia Papagiannaki
                           context_instance = get_context(request, extra_context))
401 15efc749 Sofia Papagiannaki
402 7482228b Sofia Papagiannaki
def logout(request, template='registration/logged_out.html', extra_context={}):
403 63ecdd20 Sofia Papagiannaki
    """
404 7482228b Sofia Papagiannaki
    Wraps `django.contrib.auth.logout` and delete the cookie.
405 63ecdd20 Sofia Papagiannaki
    """
406 7482228b Sofia Papagiannaki
    auth_logout(request)
407 7482228b Sofia Papagiannaki
    response = HttpResponse()
408 28ff5b5d Antony Chazapis
    response.delete_cookie(COOKIE_NAME, path='/', domain=COOKIE_DOMAIN)
409 63ecdd20 Sofia Papagiannaki
    next = request.GET.get('next')
410 63ecdd20 Sofia Papagiannaki
    if next:
411 63ecdd20 Sofia Papagiannaki
        response['Location'] = next
412 63ecdd20 Sofia Papagiannaki
        response.status_code = 302
413 63ecdd20 Sofia Papagiannaki
        return response
414 0d02a287 Sofia Papagiannaki
    elif LOGOUT_NEXT:
415 0d02a287 Sofia Papagiannaki
        response['Location'] = LOGOUT_NEXT
416 0d02a287 Sofia Papagiannaki
        response.status_code = 301
417 0d02a287 Sofia Papagiannaki
        return response
418 0d02a287 Sofia Papagiannaki
    messages.add_message(request, messages.SUCCESS, _('You have successfully logged out.'))
419 49df775e Sofia Papagiannaki
    context = get_context(request, extra_context)
420 49df775e Sofia Papagiannaki
    response.write(render_to_string(template, context_instance=context))
421 49df775e Sofia Papagiannaki
    return response
422 2126d85d Sofia Papagiannaki
423 683cf244 Sofia Papagiannaki
@transaction.commit_manually
424 d186cf77 Sofia Papagiannaki
def activate(request, email_template_name='im/welcome_email.txt', on_failure='im/signup.html'):
425 2126d85d Sofia Papagiannaki
    """
426 683cf244 Sofia Papagiannaki
    Activates the user identified by the ``auth`` request parameter, sends a welcome email
427 683cf244 Sofia Papagiannaki
    and renews the user token.
428 176023aa Kostas Papadimitriou

429 683cf244 Sofia Papagiannaki
    The view uses commit_manually decorator in order to ensure the user state will be updated
430 683cf244 Sofia Papagiannaki
    only if the email will be send successfully.
431 2126d85d Sofia Papagiannaki
    """
432 2126d85d Sofia Papagiannaki
    token = request.GET.get('auth')
433 2126d85d Sofia Papagiannaki
    next = request.GET.get('next')
434 2126d85d Sofia Papagiannaki
    try:
435 2126d85d Sofia Papagiannaki
        user = AstakosUser.objects.get(auth_token=token)
436 2126d85d Sofia Papagiannaki
    except AstakosUser.DoesNotExist:
437 683cf244 Sofia Papagiannaki
        return HttpResponseBadRequest(_('No such user'))
438 0a569195 Sofia Papagiannaki
    
439 0a569195 Sofia Papagiannaki
    try:
440 55a2cc0e root
        local_user = AstakosUser.objects.get(email=user.email, is_active=True)
441 0a569195 Sofia Papagiannaki
    except AstakosUser.DoesNotExist:
442 0a569195 Sofia Papagiannaki
        user.is_active = True
443 0a569195 Sofia Papagiannaki
        user.email_verified = True
444 27e26a41 Sofia Papagiannaki
        try:
445 27e26a41 Sofia Papagiannaki
            user.save()
446 27e26a41 Sofia Papagiannaki
        except ValidationError, e:
447 27e26a41 Sofia Papagiannaki
            return HttpResponseBadRequest(e)
448 0a569195 Sofia Papagiannaki
    else:
449 d186cf77 Sofia Papagiannaki
        # switch the existing account to shibboleth one
450 0a569195 Sofia Papagiannaki
        local_user.provider = 'shibboleth'
451 0a569195 Sofia Papagiannaki
        local_user.set_unusable_password()
452 0a569195 Sofia Papagiannaki
        local_user.third_party_identifier = user.third_party_identifier
453 27e26a41 Sofia Papagiannaki
        try:
454 27e26a41 Sofia Papagiannaki
            local_user.save()
455 27e26a41 Sofia Papagiannaki
        except ValidationError, e:
456 27e26a41 Sofia Papagiannaki
            return HttpResponseBadRequest(e)
457 0a569195 Sofia Papagiannaki
        user.delete()
458 0a569195 Sofia Papagiannaki
        user = local_user
459 0a569195 Sofia Papagiannaki
    
460 683cf244 Sofia Papagiannaki
    try:
461 683cf244 Sofia Papagiannaki
        send_greeting(user, email_template_name)
462 683cf244 Sofia Papagiannaki
        response = prepare_response(request, user, next, renew=True)
463 683cf244 Sofia Papagiannaki
        transaction.commit()
464 683cf244 Sofia Papagiannaki
        return response
465 0a569195 Sofia Papagiannaki
    except SendMailError, e:
466 8f5a3a06 Sofia Papagiannaki
        message = e.message
467 683cf244 Sofia Papagiannaki
        messages.add_message(request, messages.ERROR, message)
468 683cf244 Sofia Papagiannaki
        transaction.rollback()
469 d186cf77 Sofia Papagiannaki
        return render_response(on_failure)
470 18ffbee1 Sofia Papagiannaki
    except BaseException, e:
471 18ffbee1 Sofia Papagiannaki
        status = messages.ERROR
472 18ffbee1 Sofia Papagiannaki
        message = _('Something went wrong.')
473 d186cf77 Sofia Papagiannaki
        messages.add_message(request, messages.ERROR, message)
474 18ffbee1 Sofia Papagiannaki
        logger.exception(e)
475 18ffbee1 Sofia Papagiannaki
        transaction.rollback()
476 d186cf77 Sofia Papagiannaki
        return signup(request, on_failure)
477 270dd48d Sofia Papagiannaki
478 270dd48d Sofia Papagiannaki
def approval_terms(request, term_id=None, template_name='im/approval_terms.html', extra_context={}):
479 270dd48d Sofia Papagiannaki
    term = None
480 270dd48d Sofia Papagiannaki
    terms = None
481 270dd48d Sofia Papagiannaki
    if not term_id:
482 270dd48d Sofia Papagiannaki
        try:
483 270dd48d Sofia Papagiannaki
            term = ApprovalTerms.objects.order_by('-id')[0]
484 270dd48d Sofia Papagiannaki
        except IndexError:
485 270dd48d Sofia Papagiannaki
            pass
486 270dd48d Sofia Papagiannaki
    else:
487 270dd48d Sofia Papagiannaki
        try:
488 270dd48d Sofia Papagiannaki
             term = ApprovalTerms.objects.get(id=term_id)
489 270dd48d Sofia Papagiannaki
        except ApprovalTermDoesNotExist, e:
490 270dd48d Sofia Papagiannaki
            pass
491 176023aa Kostas Papadimitriou
492 270dd48d Sofia Papagiannaki
    if not term:
493 176023aa Kostas Papadimitriou
        return HttpResponseRedirect(reverse('astakos.im.views.index'))
494 270dd48d Sofia Papagiannaki
    f = open(term.location, 'r')
495 270dd48d Sofia Papagiannaki
    terms = f.read()
496 176023aa Kostas Papadimitriou
497 270dd48d Sofia Papagiannaki
    if request.method == 'POST':
498 270dd48d Sofia Papagiannaki
        next = request.POST.get('next')
499 270dd48d Sofia Papagiannaki
        if not next:
500 8f5a3a06 Sofia Papagiannaki
            next = reverse('astakos.im.views.index')
501 270dd48d Sofia Papagiannaki
        form = SignApprovalTermsForm(request.POST, instance=request.user)
502 270dd48d Sofia Papagiannaki
        if not form.is_valid():
503 270dd48d Sofia Papagiannaki
            return render_response(template_name,
504 270dd48d Sofia Papagiannaki
                           terms = terms,
505 8f5a3a06 Sofia Papagiannaki
                           approval_terms_form = form,
506 270dd48d Sofia Papagiannaki
                           context_instance = get_context(request, extra_context))
507 270dd48d Sofia Papagiannaki
        user = form.save()
508 270dd48d Sofia Papagiannaki
        return HttpResponseRedirect(next)
509 270dd48d Sofia Papagiannaki
    else:
510 586967c0 Sofia Papagiannaki
        form = None
511 1662ac2d Sofia Papagiannaki
        if request.user.is_authenticated() and not request.user.signed_terms():
512 586967c0 Sofia Papagiannaki
            form = SignApprovalTermsForm(instance=request.user)
513 270dd48d Sofia Papagiannaki
        return render_response(template_name,
514 270dd48d Sofia Papagiannaki
                               terms = terms,
515 8f5a3a06 Sofia Papagiannaki
                               approval_terms_form = form,
516 270dd48d Sofia Papagiannaki
                               context_instance = get_context(request, extra_context))
517 270dd48d Sofia Papagiannaki
518 270dd48d Sofia Papagiannaki
@signed_terms_required
519 270dd48d Sofia Papagiannaki
def change_password(request):
520 176023aa Kostas Papadimitriou
    return password_change(request, post_change_redirect=reverse('astakos.im.views.edit_profile'))
521 49790d9d Sofia Papagiannaki
522 49790d9d Sofia Papagiannaki
@transaction.commit_manually
523 49790d9d Sofia Papagiannaki
def change_email(request, activation_key=None,
524 49790d9d Sofia Papagiannaki
                 email_template_name='registration/email_change_email.txt',
525 49790d9d Sofia Papagiannaki
                 form_template_name='registration/email_change_form.html',
526 49790d9d Sofia Papagiannaki
                 confirm_template_name='registration/email_change_done.html',
527 49790d9d Sofia Papagiannaki
                 extra_context={}):
528 49790d9d Sofia Papagiannaki
    if activation_key:
529 49790d9d Sofia Papagiannaki
        try:
530 49790d9d Sofia Papagiannaki
            user = EmailChange.objects.change_email(activation_key)
531 49790d9d Sofia Papagiannaki
            if request.user.is_authenticated() and request.user == user:
532 49790d9d Sofia Papagiannaki
                msg = _('Email changed successfully.')
533 49790d9d Sofia Papagiannaki
                messages.add_message(request, messages.SUCCESS, msg)
534 49790d9d Sofia Papagiannaki
                auth_logout(request)
535 49790d9d Sofia Papagiannaki
                response = prepare_response(request, user)
536 49790d9d Sofia Papagiannaki
                transaction.commit()
537 49790d9d Sofia Papagiannaki
                return response
538 49790d9d Sofia Papagiannaki
        except ValueError, e:
539 49790d9d Sofia Papagiannaki
            messages.add_message(request, messages.ERROR, e)
540 49790d9d Sofia Papagiannaki
        return render_response(confirm_template_name,
541 49790d9d Sofia Papagiannaki
                               modified_user = user if 'user' in locals() else None,
542 49790d9d Sofia Papagiannaki
                               context_instance = get_context(request,
543 49790d9d Sofia Papagiannaki
                                                              extra_context))
544 49790d9d Sofia Papagiannaki
    
545 49790d9d Sofia Papagiannaki
    if not request.user.is_authenticated():
546 49790d9d Sofia Papagiannaki
        path = quote(request.get_full_path())
547 49790d9d Sofia Papagiannaki
        url = request.build_absolute_uri(reverse('astakos.im.views.index'))
548 49790d9d Sofia Papagiannaki
        return HttpResponseRedirect(url + '?next=' + path)
549 49790d9d Sofia Papagiannaki
    form = EmailChangeForm(request.POST or None)
550 49790d9d Sofia Papagiannaki
    if request.method == 'POST' and form.is_valid():
551 49790d9d Sofia Papagiannaki
        try:
552 49790d9d Sofia Papagiannaki
            ec = form.save(email_template_name, request)
553 49790d9d Sofia Papagiannaki
        except SendMailError, e:
554 49790d9d Sofia Papagiannaki
            status = messages.ERROR
555 49790d9d Sofia Papagiannaki
            msg = e
556 49790d9d Sofia Papagiannaki
            transaction.rollback()
557 49790d9d Sofia Papagiannaki
        except IntegrityError, e:
558 49790d9d Sofia Papagiannaki
            status = messages.ERROR
559 49790d9d Sofia Papagiannaki
            msg = _('There is already a pending change email request.')
560 49790d9d Sofia Papagiannaki
        else:
561 49790d9d Sofia Papagiannaki
            status = messages.SUCCESS
562 49790d9d Sofia Papagiannaki
            msg = _('Change email request has been registered succefully.\
563 49790d9d Sofia Papagiannaki
                    You are going to receive a verification email in the new address.')
564 49790d9d Sofia Papagiannaki
            transaction.commit()
565 49790d9d Sofia Papagiannaki
        messages.add_message(request, status, msg)
566 49790d9d Sofia Papagiannaki
    return render_response(form_template_name,
567 49790d9d Sofia Papagiannaki
                           form = form,
568 49790d9d Sofia Papagiannaki
                           context_instance = get_context(request,
569 49790d9d Sofia Papagiannaki
                                                          extra_context))