Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (22.4 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 63ecdd20 Sofia Papagiannaki
from django.utils.http import urlencode
51 683cf244 Sofia Papagiannaki
from django.http import HttpResponseRedirect, HttpResponseBadRequest
52 8316698a Sofia Papagiannaki
from django.db.utils import IntegrityError
53 270dd48d Sofia Papagiannaki
from django.contrib.auth.views import password_change
54 27e26a41 Sofia Papagiannaki
from django.core.exceptions import ValidationError
55 d1757ca7 Sofia Papagiannaki
from django.db.models import Q
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 111f3da6 Sofia Papagiannaki
from astakos.im.functions import send_greeting, send_feedback, SendMailError, \
62 111f3da6 Sofia Papagiannaki
    invite as invite_func, logout as auth_logout
63 4e30244e Sofia Papagiannaki
from astakos.im.settings import DEFAULT_CONTACT_EMAIL, DEFAULT_FROM_EMAIL, COOKIE_NAME, COOKIE_DOMAIN, IM_MODULES, SITENAME, LOGOUT_NEXT
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 23447441 Sofia Papagiannaki
    elif request.method == "GET":
270 23447441 Sofia Papagiannaki
        request.user.is_verified = True
271 23447441 Sofia Papagiannaki
        request.user.save()
272 0905ccd2 Sofia Papagiannaki
    return render_response(template_name,
273 c301698f Sofia Papagiannaki
                           reset_cookie = reset_cookie,
274 8f5a3a06 Sofia Papagiannaki
                           profile_form = form,
275 0905ccd2 Sofia Papagiannaki
                           context_instance = get_context(request,
276 c301698f Sofia Papagiannaki
                                                          extra_context))
277 64cd4730 Antony Chazapis
278 8f5a3a06 Sofia Papagiannaki
def signup(request, template_name='im/signup.html', on_success='im/signup_complete.html', extra_context={}, backend=None):
279 890b0eaf Sofia Papagiannaki
    """
280 890b0eaf Sofia Papagiannaki
    Allows a user to create a local account.
281 176023aa Kostas Papadimitriou

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

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

301 176023aa Kostas Papadimitriou

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

306 890b0eaf Sofia Papagiannaki
    ``extra_context``
307 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
308 176023aa Kostas Papadimitriou

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

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

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

368 890b0eaf Sofia Papagiannaki
    **Arguments**
369 176023aa Kostas Papadimitriou

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

374 890b0eaf Sofia Papagiannaki
    ``extra_context``
375 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
376 176023aa Kostas Papadimitriou

377 890b0eaf Sofia Papagiannaki
    **Template:**
378 176023aa Kostas Papadimitriou

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

381 890b0eaf Sofia Papagiannaki
    **Settings:**
382 176023aa Kostas Papadimitriou

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

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