Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / views.py @ 8f5a3a06

History | View | Annotate | Download (18.3 kB)

1 aba1e498 Antony Chazapis
# Copyright 2011-2012 GRNET S.A. All rights reserved.
2 64cd4730 Antony Chazapis
# 
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 64cd4730 Antony Chazapis
# 
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 64cd4730 Antony Chazapis
# 
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 64cd4730 Antony Chazapis
# 
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 64cd4730 Antony Chazapis
# 
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 63ecdd20 Sofia Papagiannaki
from django.http import HttpResponse
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 64cd4730 Antony Chazapis
56 270dd48d Sofia Papagiannaki
from astakos.im.models import AstakosUser, Invitation, ApprovalTerms
57 8f5a3a06 Sofia Papagiannaki
from astakos.im.activation_backends import get_backend
58 270dd48d Sofia Papagiannaki
from astakos.im.util import get_context, prepare_response, set_cookie, has_signed_terms
59 15efc749 Sofia Papagiannaki
from astakos.im.forms import *
60 8f5a3a06 Sofia Papagiannaki
from astakos.im.functions import send_greeting, send_feedback, SendMailError
61 0d02a287 Sofia Papagiannaki
from astakos.im.settings import DEFAULT_CONTACT_EMAIL, DEFAULT_FROM_EMAIL, COOKIE_NAME, COOKIE_DOMAIN, IM_MODULES, SITENAME, BASEURL, LOGOUT_NEXT
62 f36af44a Antony Chazapis
from astakos.im.functions import invite as invite_func
63 64cd4730 Antony Chazapis
64 e015e9e6 Sofia Papagiannaki
logger = logging.getLogger(__name__)
65 e015e9e6 Sofia Papagiannaki
66 c301698f Sofia Papagiannaki
def render_response(template, tab=None, status=200, reset_cookie=False, context_instance=None, **kwargs):
67 890b0eaf Sofia Papagiannaki
    """
68 890b0eaf Sofia Papagiannaki
    Calls ``django.template.loader.render_to_string`` with an additional ``tab``
69 890b0eaf Sofia Papagiannaki
    keyword argument and returns an ``django.http.HttpResponse`` with the
70 890b0eaf Sofia Papagiannaki
    specified ``status``.
71 890b0eaf Sofia Papagiannaki
    """
72 64cd4730 Antony Chazapis
    if tab is None:
73 881c856c Sofia Papagiannaki
        tab = template.partition('_')[0].partition('.html')[0]
74 64cd4730 Antony Chazapis
    kwargs.setdefault('tab', tab)
75 0905ccd2 Sofia Papagiannaki
    html = render_to_string(template, kwargs, context_instance=context_instance)
76 c301698f Sofia Papagiannaki
    response = HttpResponse(html, status=status)
77 c301698f Sofia Papagiannaki
    if reset_cookie:
78 c301698f Sofia Papagiannaki
        set_cookie(response, context_instance['request'].user)
79 c301698f Sofia Papagiannaki
    return response
80 64cd4730 Antony Chazapis
81 63ecdd20 Sofia Papagiannaki
82 63ecdd20 Sofia Papagiannaki
def requires_anonymous(func):
83 63ecdd20 Sofia Papagiannaki
    """
84 270dd48d Sofia Papagiannaki
    Decorator checkes whether the request.user is not Anonymous and in that case
85 7482228b Sofia Papagiannaki
    redirects to `logout`.
86 63ecdd20 Sofia Papagiannaki
    """
87 63ecdd20 Sofia Papagiannaki
    @wraps(func)
88 63ecdd20 Sofia Papagiannaki
    def wrapper(request, *args):
89 63ecdd20 Sofia Papagiannaki
        if not request.user.is_anonymous():
90 63ecdd20 Sofia Papagiannaki
            next = urlencode({'next': request.build_absolute_uri()})
91 270dd48d Sofia Papagiannaki
            logout_uri = reverse(logout) + '?' + next
92 270dd48d Sofia Papagiannaki
            return HttpResponseRedirect(logout_uri)
93 63ecdd20 Sofia Papagiannaki
        return func(request, *args)
94 63ecdd20 Sofia Papagiannaki
    return wrapper
95 63ecdd20 Sofia Papagiannaki
96 270dd48d Sofia Papagiannaki
def signed_terms_required(func):
97 270dd48d Sofia Papagiannaki
    """
98 270dd48d Sofia Papagiannaki
    Decorator checkes whether the request.user is Anonymous and in that case
99 270dd48d Sofia Papagiannaki
    redirects to `logout`.
100 270dd48d Sofia Papagiannaki
    """
101 270dd48d Sofia Papagiannaki
    @wraps(func)
102 270dd48d Sofia Papagiannaki
    def wrapper(request, *args, **kwargs):
103 270dd48d Sofia Papagiannaki
        if request.user.is_authenticated() and not has_signed_terms(request.user):
104 270dd48d Sofia Papagiannaki
            params = urlencode({'next': request.build_absolute_uri(),
105 270dd48d Sofia Papagiannaki
                              'show_form':''})
106 270dd48d Sofia Papagiannaki
            terms_uri = reverse('latest_terms') + '?' + params
107 270dd48d Sofia Papagiannaki
            return HttpResponseRedirect(terms_uri)
108 270dd48d Sofia Papagiannaki
        return func(request, *args, **kwargs)
109 270dd48d Sofia Papagiannaki
    return wrapper
110 270dd48d Sofia Papagiannaki
111 270dd48d Sofia Papagiannaki
@signed_terms_required
112 1e685275 Sofia Papagiannaki
def index(request, login_template_name='im/login.html', profile_template_name='im/profile.html', extra_context={}):
113 890b0eaf Sofia Papagiannaki
    """
114 dcf55476 Sofia Papagiannaki
    If there is logged on user renders the profile page otherwise renders login page.
115 64cd4730 Antony Chazapis
    
116 890b0eaf Sofia Papagiannaki
    **Arguments**
117 64cd4730 Antony Chazapis
    
118 dcf55476 Sofia Papagiannaki
    ``login_template_name``
119 dcf55476 Sofia Papagiannaki
        A custom login template to use. This is optional; if not specified,
120 1e685275 Sofia Papagiannaki
        this will default to ``im/login.html``.
121 dcf55476 Sofia Papagiannaki
    
122 dcf55476 Sofia Papagiannaki
    ``profile_template_name``
123 dcf55476 Sofia Papagiannaki
        A custom profile template to use. This is optional; if not specified,
124 1e685275 Sofia Papagiannaki
        this will default to ``im/profile.html``.
125 64cd4730 Antony Chazapis
    
126 890b0eaf Sofia Papagiannaki
    ``extra_context``
127 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
128 64cd4730 Antony Chazapis
    
129 890b0eaf Sofia Papagiannaki
    **Template:**
130 64cd4730 Antony Chazapis
    
131 1e685275 Sofia Papagiannaki
    im/profile.html or im/login.html or ``template_name`` keyword argument.
132 64cd4730 Antony Chazapis
    
133 890b0eaf Sofia Papagiannaki
    """
134 dcf55476 Sofia Papagiannaki
    template_name = login_template_name
135 dcf55476 Sofia Papagiannaki
    if request.user.is_authenticated():
136 f534fb96 Sofia Papagiannaki
        return HttpResponseRedirect(reverse('astakos.im.views.edit_profile'))
137 0905ccd2 Sofia Papagiannaki
    return render_response(template_name,
138 8f5a3a06 Sofia Papagiannaki
                           login_form = LoginForm(),
139 0905ccd2 Sofia Papagiannaki
                           context_instance = get_context(request, extra_context))
140 64cd4730 Antony Chazapis
141 890b0eaf Sofia Papagiannaki
@login_required
142 270dd48d Sofia Papagiannaki
@signed_terms_required
143 890b0eaf Sofia Papagiannaki
@transaction.commit_manually
144 1e685275 Sofia Papagiannaki
def invite(request, template_name='im/invitations.html', extra_context={}):
145 890b0eaf Sofia Papagiannaki
    """
146 890b0eaf Sofia Papagiannaki
    Allows a user to invite somebody else.
147 890b0eaf Sofia Papagiannaki
    
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 890b0eaf Sofia Papagiannaki
    
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 890b0eaf Sofia Papagiannaki
    
155 2cbaacd5 Sofia Papagiannaki
    If the user isn't logged in, redirects to settings.LOGIN_URL.
156 890b0eaf Sofia Papagiannaki
    
157 890b0eaf Sofia Papagiannaki
    **Arguments**
158 890b0eaf Sofia Papagiannaki
    
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 890b0eaf Sofia Papagiannaki
    
163 890b0eaf Sofia Papagiannaki
    ``extra_context``
164 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
165 890b0eaf Sofia Papagiannaki
    
166 890b0eaf Sofia Papagiannaki
    **Template:**
167 890b0eaf Sofia Papagiannaki
    
168 1e685275 Sofia Papagiannaki
    im/invitations.html or ``template_name`` keyword argument.
169 890b0eaf Sofia Papagiannaki
    
170 890b0eaf Sofia Papagiannaki
    **Settings:**
171 890b0eaf Sofia Papagiannaki
    
172 890b0eaf Sofia Papagiannaki
    The view expectes the following settings are defined:
173 890b0eaf Sofia Papagiannaki
    
174 890b0eaf Sofia Papagiannaki
    * LOGIN_URL: login uri
175 2cbaacd5 Sofia Papagiannaki
    * ASTAKOS_DEFAULT_CONTACT_EMAIL: service support email
176 2cbaacd5 Sofia Papagiannaki
    * ASTAKOS_DEFAULT_FROM_EMAIL: from email
177 890b0eaf Sofia Papagiannaki
    """
178 64cd4730 Antony Chazapis
    status = None
179 64cd4730 Antony Chazapis
    message = None
180 5ed6816e Sofia Papagiannaki
    inviter = AstakosUser.objects.get(username = request.user.username)
181 8f5a3a06 Sofia Papagiannaki
    form = InvitationForm()
182 5ed6816e Sofia Papagiannaki
    
183 64cd4730 Antony Chazapis
    if request.method == 'POST':
184 8f5a3a06 Sofia Papagiannaki
        form = InvitationForm(request.POST)
185 64cd4730 Antony Chazapis
        
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
                    invitation.inviter = inviter
191 8f5a3a06 Sofia Papagiannaki
                    invite_func(invitation, inviter)
192 8f5a3a06 Sofia Papagiannaki
                    status = messages.SUCCESS
193 8f5a3a06 Sofia Papagiannaki
                    message = _('Invitation sent to %s' % invitation.username)
194 8f5a3a06 Sofia Papagiannaki
                    transaction.commit()
195 8f5a3a06 Sofia Papagiannaki
                except SendMailError, e:
196 8f5a3a06 Sofia Papagiannaki
                    message = e.message
197 8f5a3a06 Sofia Papagiannaki
                    transaction.rollback()
198 64cd4730 Antony Chazapis
        else:
199 890b0eaf Sofia Papagiannaki
            status = messages.ERROR
200 64cd4730 Antony Chazapis
            message = _('No invitations left')
201 890b0eaf Sofia Papagiannaki
    messages.add_message(request, status, message)
202 890b0eaf Sofia Papagiannaki
    
203 a196eb7e Sofia Papagiannaki
    sent = [{'email': inv.username,
204 d6ae71a2 root
             'realname': inv.realname,
205 d6ae71a2 root
             'is_consumed': inv.is_consumed}
206 d6ae71a2 root
             for inv in inviter.invitations_sent.all()]
207 77e2ad52 root
    kwargs = {'inviter': inviter,
208 a196eb7e Sofia Papagiannaki
              'sent':sent}
209 0905ccd2 Sofia Papagiannaki
    context = get_context(request, extra_context, **kwargs)
210 0905ccd2 Sofia Papagiannaki
    return render_response(template_name,
211 8f5a3a06 Sofia Papagiannaki
                           invitation_form = form,
212 0905ccd2 Sofia Papagiannaki
                           context_instance = context)
213 64cd4730 Antony Chazapis
214 890b0eaf Sofia Papagiannaki
@login_required
215 270dd48d Sofia Papagiannaki
@signed_terms_required
216 1e685275 Sofia Papagiannaki
def edit_profile(request, template_name='im/profile.html', extra_context={}):
217 890b0eaf Sofia Papagiannaki
    """
218 890b0eaf Sofia Papagiannaki
    Allows a user to edit his/her profile.
219 64cd4730 Antony Chazapis
    
220 890b0eaf Sofia Papagiannaki
    In case of GET request renders a form for displaying the user information.
221 ce86cd44 Sofia Papagiannaki
    In case of POST updates the user informantion and redirects to ``next``
222 ce86cd44 Sofia Papagiannaki
    url parameter if exists.
223 890b0eaf Sofia Papagiannaki
    
224 2cbaacd5 Sofia Papagiannaki
    If the user isn't logged in, redirects to settings.LOGIN_URL.
225 890b0eaf Sofia Papagiannaki
    
226 890b0eaf Sofia Papagiannaki
    **Arguments**
227 890b0eaf Sofia Papagiannaki
    
228 890b0eaf Sofia Papagiannaki
    ``template_name``
229 890b0eaf Sofia Papagiannaki
        A custom template to use. This is optional; if not specified,
230 1e685275 Sofia Papagiannaki
        this will default to ``im/profile.html``.
231 890b0eaf Sofia Papagiannaki
    
232 890b0eaf Sofia Papagiannaki
    ``extra_context``
233 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
234 890b0eaf Sofia Papagiannaki
    
235 890b0eaf Sofia Papagiannaki
    **Template:**
236 890b0eaf Sofia Papagiannaki
    
237 1e685275 Sofia Papagiannaki
    im/profile.html or ``template_name`` keyword argument.
238 92defad4 Sofia Papagiannaki
    
239 92defad4 Sofia Papagiannaki
    **Settings:**
240 92defad4 Sofia Papagiannaki
    
241 92defad4 Sofia Papagiannaki
    The view expectes the following settings are defined:
242 92defad4 Sofia Papagiannaki
    
243 92defad4 Sofia Papagiannaki
    * LOGIN_URL: login uri
244 890b0eaf Sofia Papagiannaki
    """
245 15efc749 Sofia Papagiannaki
    form = ProfileForm(instance=request.user)
246 15efc749 Sofia Papagiannaki
    extra_context['next'] = request.GET.get('next')
247 c301698f Sofia Papagiannaki
    reset_cookie = False
248 64cd4730 Antony Chazapis
    if request.method == 'POST':
249 15efc749 Sofia Papagiannaki
        form = ProfileForm(request.POST, instance=request.user)
250 890b0eaf Sofia Papagiannaki
        if form.is_valid():
251 64cd4730 Antony Chazapis
            try:
252 c301698f Sofia Papagiannaki
                prev_token = request.user.auth_token
253 c301698f Sofia Papagiannaki
                user = form.save()
254 c301698f Sofia Papagiannaki
                reset_cookie = user.auth_token != prev_token
255 c301698f Sofia Papagiannaki
                form = ProfileForm(instance=user)
256 1a3675a0 Sofia Papagiannaki
                next = request.POST.get('next')
257 1a3675a0 Sofia Papagiannaki
                if next:
258 1a3675a0 Sofia Papagiannaki
                    return redirect(next)
259 890b0eaf Sofia Papagiannaki
                msg = _('Profile has been updated successfully')
260 890b0eaf Sofia Papagiannaki
                messages.add_message(request, messages.SUCCESS, msg)
261 890b0eaf Sofia Papagiannaki
            except ValueError, ve:
262 890b0eaf Sofia Papagiannaki
                messages.add_message(request, messages.ERROR, ve)
263 0905ccd2 Sofia Papagiannaki
    return render_response(template_name,
264 c301698f Sofia Papagiannaki
                           reset_cookie = reset_cookie,
265 8f5a3a06 Sofia Papagiannaki
                           profile_form = form,
266 0905ccd2 Sofia Papagiannaki
                           context_instance = get_context(request,
267 c301698f Sofia Papagiannaki
                                                          extra_context))
268 64cd4730 Antony Chazapis
269 8f5a3a06 Sofia Papagiannaki
@transaction.commit_manually
270 8f5a3a06 Sofia Papagiannaki
def signup(request, template_name='im/signup.html', on_success='im/signup_complete.html', extra_context={}, backend=None):
271 890b0eaf Sofia Papagiannaki
    """
272 890b0eaf Sofia Papagiannaki
    Allows a user to create a local account.
273 64cd4730 Antony Chazapis
    
274 890b0eaf Sofia Papagiannaki
    In case of GET request renders a form for providing the user information.
275 890b0eaf Sofia Papagiannaki
    In case of POST handles the signup.
276 890b0eaf Sofia Papagiannaki
    
277 890b0eaf Sofia Papagiannaki
    The user activation will be delegated to the backend specified by the ``backend`` keyword argument
278 8f5a3a06 Sofia Papagiannaki
    if present, otherwise to the ``astakos.im.activation_backends.InvitationBackend``
279 8f5a3a06 Sofia Papagiannaki
    if settings.ASTAKOS_INVITATIONS_ENABLED is True or ``astakos.im.activation_backends.SimpleBackend`` if not
280 8f5a3a06 Sofia Papagiannaki
    (see activation_backends);
281 890b0eaf Sofia Papagiannaki
    
282 890b0eaf Sofia Papagiannaki
    Upon successful user creation if ``next`` url parameter is present the user is redirected there
283 890b0eaf Sofia Papagiannaki
    otherwise renders the same page with a success message.
284 64cd4730 Antony Chazapis
    
285 8f5a3a06 Sofia Papagiannaki
    On unsuccessful creation, renders ``template_name`` with an error message.
286 890b0eaf Sofia Papagiannaki
    
287 890b0eaf Sofia Papagiannaki
    **Arguments**
288 890b0eaf Sofia Papagiannaki
    
289 8f5a3a06 Sofia Papagiannaki
    ``template_name``
290 8f5a3a06 Sofia Papagiannaki
        A custom template to render. This is optional;
291 1e685275 Sofia Papagiannaki
        if not specified, this will default to ``im/signup.html``.
292 f7e8a159 Sofia Papagiannaki
    
293 f7e8a159 Sofia Papagiannaki
    
294 f7e8a159 Sofia Papagiannaki
    ``on_success``
295 f7e8a159 Sofia Papagiannaki
        A custom template to render in case of success. This is optional;
296 1e685275 Sofia Papagiannaki
        if not specified, this will default to ``im/signup_complete.html``.
297 890b0eaf Sofia Papagiannaki
    
298 890b0eaf Sofia Papagiannaki
    ``extra_context``
299 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
300 890b0eaf Sofia Papagiannaki
    
301 890b0eaf Sofia Papagiannaki
    **Template:**
302 890b0eaf Sofia Papagiannaki
    
303 8f5a3a06 Sofia Papagiannaki
    im/signup.html or ``template_name`` keyword argument.
304 1e685275 Sofia Papagiannaki
    im/signup_complete.html or ``on_success`` keyword argument. 
305 890b0eaf Sofia Papagiannaki
    """
306 0d02a287 Sofia Papagiannaki
    if request.user.is_authenticated():
307 0d02a287 Sofia Papagiannaki
        return HttpResponseRedirect(reverse('astakos.im.views.index'))
308 8f5a3a06 Sofia Papagiannaki
    if not backend:
309 8f5a3a06 Sofia Papagiannaki
        backend = get_backend(request)
310 890b0eaf Sofia Papagiannaki
    try:
311 8f5a3a06 Sofia Papagiannaki
        query_dict = request.__getattribute__(request.method)
312 8f5a3a06 Sofia Papagiannaki
        provider = query_dict.get('provider', 'local')
313 8f5a3a06 Sofia Papagiannaki
        form = backend.get_signup_form(provider)
314 15efc749 Sofia Papagiannaki
    except (Invitation.DoesNotExist, ValueError), e:
315 890b0eaf Sofia Papagiannaki
        messages.add_message(request, messages.ERROR, e)
316 8f5a3a06 Sofia Papagiannaki
    if request.method == 'POST':
317 8f5a3a06 Sofia Papagiannaki
        if form.is_valid():
318 8f5a3a06 Sofia Papagiannaki
            user = form.save()
319 8f5a3a06 Sofia Papagiannaki
            try:
320 8f5a3a06 Sofia Papagiannaki
                result = backend.handle_activation(user)
321 8f5a3a06 Sofia Papagiannaki
            except SendMailError, e:
322 8f5a3a06 Sofia Papagiannaki
                message = e.message
323 8f5a3a06 Sofia Papagiannaki
                status = messages.ERROR
324 8f5a3a06 Sofia Papagiannaki
                transaction.rollback()
325 8f5a3a06 Sofia Papagiannaki
            else:
326 8f5a3a06 Sofia Papagiannaki
                message = result.message
327 8f5a3a06 Sofia Papagiannaki
                status = messages.SUCCESS
328 8f5a3a06 Sofia Papagiannaki
                transaction.commit()
329 8f5a3a06 Sofia Papagiannaki
                if user and user.is_active:
330 8f5a3a06 Sofia Papagiannaki
                    next = request.POST.get('next', '')
331 8f5a3a06 Sofia Papagiannaki
                    return prepare_response(request, user, next=next)
332 8f5a3a06 Sofia Papagiannaki
                messages.add_message(request, status, message)
333 8f5a3a06 Sofia Papagiannaki
                return render_response(on_success,
334 8f5a3a06 Sofia Papagiannaki
                                       context_instance=get_context(request, extra_context))
335 8f5a3a06 Sofia Papagiannaki
    return render_response(template_name,
336 8f5a3a06 Sofia Papagiannaki
                           local_signup_form = form,
337 890b0eaf Sofia Papagiannaki
                           context_instance=get_context(request, extra_context))
338 64cd4730 Antony Chazapis
339 890b0eaf Sofia Papagiannaki
@login_required
340 270dd48d Sofia Papagiannaki
@signed_terms_required
341 8f5a3a06 Sofia Papagiannaki
def feedback(request, template_name='im/feedback.html', email_template_name='im/feedback_mail.txt', extra_context={}):
342 890b0eaf Sofia Papagiannaki
    """
343 890b0eaf Sofia Papagiannaki
    Allows a user to send feedback.
344 890b0eaf Sofia Papagiannaki
    
345 890b0eaf Sofia Papagiannaki
    In case of GET request renders a form for providing the feedback information.
346 890b0eaf Sofia Papagiannaki
    In case of POST sends an email to support team.
347 890b0eaf Sofia Papagiannaki
    
348 2cbaacd5 Sofia Papagiannaki
    If the user isn't logged in, redirects to settings.LOGIN_URL.
349 890b0eaf Sofia Papagiannaki
    
350 890b0eaf Sofia Papagiannaki
    **Arguments**
351 890b0eaf Sofia Papagiannaki
    
352 890b0eaf Sofia Papagiannaki
    ``template_name``
353 890b0eaf Sofia Papagiannaki
        A custom template to use. This is optional; if not specified,
354 1e685275 Sofia Papagiannaki
        this will default to ``im/feedback.html``.
355 890b0eaf Sofia Papagiannaki
    
356 890b0eaf Sofia Papagiannaki
    ``extra_context``
357 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
358 890b0eaf Sofia Papagiannaki
    
359 890b0eaf Sofia Papagiannaki
    **Template:**
360 64cd4730 Antony Chazapis
    
361 1e685275 Sofia Papagiannaki
    im/signup.html or ``template_name`` keyword argument.
362 890b0eaf Sofia Papagiannaki
    
363 890b0eaf Sofia Papagiannaki
    **Settings:**
364 890b0eaf Sofia Papagiannaki
    
365 92defad4 Sofia Papagiannaki
    * LOGIN_URL: login uri
366 2cbaacd5 Sofia Papagiannaki
    * ASTAKOS_DEFAULT_CONTACT_EMAIL: List of feedback recipients
367 890b0eaf Sofia Papagiannaki
    """
368 64cd4730 Antony Chazapis
    if request.method == 'GET':
369 890b0eaf Sofia Papagiannaki
        form = FeedbackForm()
370 890b0eaf Sofia Papagiannaki
    if request.method == 'POST':
371 890b0eaf Sofia Papagiannaki
        if not request.user:
372 890b0eaf Sofia Papagiannaki
            return HttpResponse('Unauthorized', status=401)
373 64cd4730 Antony Chazapis
        
374 890b0eaf Sofia Papagiannaki
        form = FeedbackForm(request.POST)
375 890b0eaf Sofia Papagiannaki
        if form.is_valid():
376 8f5a3a06 Sofia Papagiannaki
            msg = form.cleaned_data['feedback_msg'],
377 8f5a3a06 Sofia Papagiannaki
            data = form.cleaned_data['feedback_data']
378 538ccdd5 Sofia Papagiannaki
            try:
379 8f5a3a06 Sofia Papagiannaki
                send_feedback(msg, data, request.user, email_template_name)
380 8f5a3a06 Sofia Papagiannaki
            except SendMailError, e:
381 8f5a3a06 Sofia Papagiannaki
                message = e.message
382 8f5a3a06 Sofia Papagiannaki
                status = messages.ERROR
383 8f5a3a06 Sofia Papagiannaki
            else:
384 538ccdd5 Sofia Papagiannaki
                message = _('Feedback successfully sent')
385 538ccdd5 Sofia Papagiannaki
                status = messages.SUCCESS
386 538ccdd5 Sofia Papagiannaki
            messages.add_message(request, status, message)
387 890b0eaf Sofia Papagiannaki
    return render_response(template_name,
388 8f5a3a06 Sofia Papagiannaki
                           feedback_form = form,
389 6b4f9fb2 Sofia Papagiannaki
                           context_instance = get_context(request, extra_context))
390 15efc749 Sofia Papagiannaki
391 7482228b Sofia Papagiannaki
def logout(request, template='registration/logged_out.html', extra_context={}):
392 63ecdd20 Sofia Papagiannaki
    """
393 7482228b Sofia Papagiannaki
    Wraps `django.contrib.auth.logout` and delete the cookie.
394 63ecdd20 Sofia Papagiannaki
    """
395 7482228b Sofia Papagiannaki
    auth_logout(request)
396 7482228b Sofia Papagiannaki
    response = HttpResponse()
397 28ff5b5d Antony Chazapis
    response.delete_cookie(COOKIE_NAME, path='/', domain=COOKIE_DOMAIN)
398 63ecdd20 Sofia Papagiannaki
    next = request.GET.get('next')
399 63ecdd20 Sofia Papagiannaki
    if next:
400 63ecdd20 Sofia Papagiannaki
        response['Location'] = next
401 63ecdd20 Sofia Papagiannaki
        response.status_code = 302
402 63ecdd20 Sofia Papagiannaki
        return response
403 0d02a287 Sofia Papagiannaki
    elif LOGOUT_NEXT:
404 0d02a287 Sofia Papagiannaki
        response['Location'] = LOGOUT_NEXT
405 0d02a287 Sofia Papagiannaki
        response.status_code = 301
406 0d02a287 Sofia Papagiannaki
        return response
407 0d02a287 Sofia Papagiannaki
    messages.add_message(request, messages.SUCCESS, _('You have successfully logged out.'))
408 49df775e Sofia Papagiannaki
    context = get_context(request, extra_context)
409 49df775e Sofia Papagiannaki
    response.write(render_to_string(template, context_instance=context))
410 49df775e Sofia Papagiannaki
    return response
411 2126d85d Sofia Papagiannaki
412 683cf244 Sofia Papagiannaki
@transaction.commit_manually
413 683cf244 Sofia Papagiannaki
def activate(request, email_template_name='im/welcome_email.txt', on_failure=''):
414 2126d85d Sofia Papagiannaki
    """
415 683cf244 Sofia Papagiannaki
    Activates the user identified by the ``auth`` request parameter, sends a welcome email
416 683cf244 Sofia Papagiannaki
    and renews the user token.
417 683cf244 Sofia Papagiannaki
    
418 683cf244 Sofia Papagiannaki
    The view uses commit_manually decorator in order to ensure the user state will be updated
419 683cf244 Sofia Papagiannaki
    only if the email will be send successfully.
420 2126d85d Sofia Papagiannaki
    """
421 2126d85d Sofia Papagiannaki
    token = request.GET.get('auth')
422 2126d85d Sofia Papagiannaki
    next = request.GET.get('next')
423 2126d85d Sofia Papagiannaki
    try:
424 2126d85d Sofia Papagiannaki
        user = AstakosUser.objects.get(auth_token=token)
425 2126d85d Sofia Papagiannaki
    except AstakosUser.DoesNotExist:
426 683cf244 Sofia Papagiannaki
        return HttpResponseBadRequest(_('No such user'))
427 2126d85d Sofia Papagiannaki
    
428 2126d85d Sofia Papagiannaki
    user.is_active = True
429 8316698a Sofia Papagiannaki
    user.email_verified = True
430 2126d85d Sofia Papagiannaki
    user.save()
431 683cf244 Sofia Papagiannaki
    try:
432 683cf244 Sofia Papagiannaki
        send_greeting(user, email_template_name)
433 683cf244 Sofia Papagiannaki
        response = prepare_response(request, user, next, renew=True)
434 683cf244 Sofia Papagiannaki
        transaction.commit()
435 683cf244 Sofia Papagiannaki
        return response
436 8f5a3a06 Sofia Papagiannaki
    except SendEmailError, e:
437 8f5a3a06 Sofia Papagiannaki
        message = e.message
438 683cf244 Sofia Papagiannaki
        messages.add_message(request, messages.ERROR, message)
439 683cf244 Sofia Papagiannaki
        transaction.rollback()
440 683cf244 Sofia Papagiannaki
        return signup(request, on_failure='im/signup.html')
441 270dd48d Sofia Papagiannaki
442 270dd48d Sofia Papagiannaki
def approval_terms(request, term_id=None, template_name='im/approval_terms.html', extra_context={}):
443 270dd48d Sofia Papagiannaki
    term = None
444 270dd48d Sofia Papagiannaki
    terms = None
445 270dd48d Sofia Papagiannaki
    if not term_id:
446 270dd48d Sofia Papagiannaki
        try:
447 270dd48d Sofia Papagiannaki
            term = ApprovalTerms.objects.order_by('-id')[0]
448 270dd48d Sofia Papagiannaki
        except IndexError:
449 270dd48d Sofia Papagiannaki
            pass
450 270dd48d Sofia Papagiannaki
    else:
451 270dd48d Sofia Papagiannaki
        try:
452 270dd48d Sofia Papagiannaki
             term = ApprovalTerms.objects.get(id=term_id)
453 270dd48d Sofia Papagiannaki
        except ApprovalTermDoesNotExist, e:
454 270dd48d Sofia Papagiannaki
            pass
455 270dd48d Sofia Papagiannaki
    
456 270dd48d Sofia Papagiannaki
    if not term:
457 270dd48d Sofia Papagiannaki
        return HttpResponseBadRequest(_('No approval terms found.'))
458 270dd48d Sofia Papagiannaki
    f = open(term.location, 'r')
459 270dd48d Sofia Papagiannaki
    terms = f.read()
460 270dd48d Sofia Papagiannaki
    
461 270dd48d Sofia Papagiannaki
    if request.method == 'POST':
462 270dd48d Sofia Papagiannaki
        next = request.POST.get('next')
463 270dd48d Sofia Papagiannaki
        if not next:
464 8f5a3a06 Sofia Papagiannaki
            next = reverse('astakos.im.views.index')
465 270dd48d Sofia Papagiannaki
        form = SignApprovalTermsForm(request.POST, instance=request.user)
466 270dd48d Sofia Papagiannaki
        if not form.is_valid():
467 270dd48d Sofia Papagiannaki
            return render_response(template_name,
468 270dd48d Sofia Papagiannaki
                           terms = terms,
469 8f5a3a06 Sofia Papagiannaki
                           approval_terms_form = form,
470 270dd48d Sofia Papagiannaki
                           context_instance = get_context(request, extra_context))
471 270dd48d Sofia Papagiannaki
        user = form.save()
472 270dd48d Sofia Papagiannaki
        return HttpResponseRedirect(next)
473 270dd48d Sofia Papagiannaki
    else:
474 586967c0 Sofia Papagiannaki
        form = None
475 586967c0 Sofia Papagiannaki
        if request.user.is_authenticated() and not has_signed_terms(request.user):
476 586967c0 Sofia Papagiannaki
            form = SignApprovalTermsForm(instance=request.user)
477 270dd48d Sofia Papagiannaki
        return render_response(template_name,
478 270dd48d Sofia Papagiannaki
                               terms = terms,
479 8f5a3a06 Sofia Papagiannaki
                               approval_terms_form = form,
480 270dd48d Sofia Papagiannaki
                               context_instance = get_context(request, extra_context))
481 270dd48d Sofia Papagiannaki
482 270dd48d Sofia Papagiannaki
@signed_terms_required
483 270dd48d Sofia Papagiannaki
def change_password(request):
484 270dd48d Sofia Papagiannaki
    return password_change(request, post_change_redirect=reverse('astakos.im.views.edit_profile'))