Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / views.py @ 270dd48d

History | View | Annotate | Download (18.9 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 0905ccd2 Sofia Papagiannaki
from astakos.im.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 683cf244 Sofia Papagiannaki
from astakos.im.functions import send_greeting
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
    formclass = 'LoginForm'
136 dcf55476 Sofia Papagiannaki
    kwargs = {}
137 dcf55476 Sofia Papagiannaki
    if request.user.is_authenticated():
138 f534fb96 Sofia Papagiannaki
        return HttpResponseRedirect(reverse('astakos.im.views.edit_profile'))
139 0905ccd2 Sofia Papagiannaki
    return render_response(template_name,
140 dcf55476 Sofia Papagiannaki
                           form = globals()[formclass](**kwargs),
141 0905ccd2 Sofia Papagiannaki
                           context_instance = get_context(request, extra_context))
142 64cd4730 Antony Chazapis
143 890b0eaf Sofia Papagiannaki
@login_required
144 270dd48d Sofia Papagiannaki
@signed_terms_required
145 890b0eaf Sofia Papagiannaki
@transaction.commit_manually
146 1e685275 Sofia Papagiannaki
def invite(request, template_name='im/invitations.html', extra_context={}):
147 890b0eaf Sofia Papagiannaki
    """
148 890b0eaf Sofia Papagiannaki
    Allows a user to invite somebody else.
149 890b0eaf Sofia Papagiannaki
    
150 890b0eaf Sofia Papagiannaki
    In case of GET request renders a form for providing the invitee information.
151 890b0eaf Sofia Papagiannaki
    In case of POST checks whether the user has not run out of invitations and then
152 890b0eaf Sofia Papagiannaki
    sends an invitation email to singup to the service.
153 890b0eaf Sofia Papagiannaki
    
154 890b0eaf Sofia Papagiannaki
    The view uses commit_manually decorator in order to ensure the number of the
155 890b0eaf Sofia Papagiannaki
    user invitations is going to be updated only if the email has been successfully sent.
156 890b0eaf Sofia Papagiannaki
    
157 2cbaacd5 Sofia Papagiannaki
    If the user isn't logged in, redirects to settings.LOGIN_URL.
158 890b0eaf Sofia Papagiannaki
    
159 890b0eaf Sofia Papagiannaki
    **Arguments**
160 890b0eaf Sofia Papagiannaki
    
161 890b0eaf Sofia Papagiannaki
    ``template_name``
162 890b0eaf Sofia Papagiannaki
        A custom template to use. This is optional; if not specified,
163 1e685275 Sofia Papagiannaki
        this will default to ``im/invitations.html``.
164 890b0eaf Sofia Papagiannaki
    
165 890b0eaf Sofia Papagiannaki
    ``extra_context``
166 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
167 890b0eaf Sofia Papagiannaki
    
168 890b0eaf Sofia Papagiannaki
    **Template:**
169 890b0eaf Sofia Papagiannaki
    
170 1e685275 Sofia Papagiannaki
    im/invitations.html or ``template_name`` keyword argument.
171 890b0eaf Sofia Papagiannaki
    
172 890b0eaf Sofia Papagiannaki
    **Settings:**
173 890b0eaf Sofia Papagiannaki
    
174 890b0eaf Sofia Papagiannaki
    The view expectes the following settings are defined:
175 890b0eaf Sofia Papagiannaki
    
176 890b0eaf Sofia Papagiannaki
    * LOGIN_URL: login uri
177 2cbaacd5 Sofia Papagiannaki
    * ASTAKOS_DEFAULT_CONTACT_EMAIL: service support email
178 2cbaacd5 Sofia Papagiannaki
    * ASTAKOS_DEFAULT_FROM_EMAIL: from email
179 890b0eaf Sofia Papagiannaki
    """
180 64cd4730 Antony Chazapis
    status = None
181 64cd4730 Antony Chazapis
    message = None
182 5ed6816e Sofia Papagiannaki
    inviter = AstakosUser.objects.get(username = request.user.username)
183 5ed6816e Sofia Papagiannaki
    
184 64cd4730 Antony Chazapis
    if request.method == 'POST':
185 0905ccd2 Sofia Papagiannaki
        username = request.POST.get('uniq')
186 64cd4730 Antony Chazapis
        realname = request.POST.get('realname')
187 64cd4730 Antony Chazapis
        
188 64cd4730 Antony Chazapis
        if inviter.invitations > 0:
189 64cd4730 Antony Chazapis
            try:
190 374611bc Sofia Papagiannaki
                invite_func(inviter, username, realname)
191 890b0eaf Sofia Papagiannaki
                status = messages.SUCCESS
192 0905ccd2 Sofia Papagiannaki
                message = _('Invitation sent to %s' % username)
193 890b0eaf Sofia Papagiannaki
                transaction.commit()
194 64cd4730 Antony Chazapis
            except (SMTPException, socket.error) as e:
195 890b0eaf Sofia Papagiannaki
                status = messages.ERROR
196 64cd4730 Antony Chazapis
                message = getattr(e, 'strerror', '')
197 890b0eaf Sofia Papagiannaki
                transaction.rollback()
198 8316698a Sofia Papagiannaki
            except IntegrityError, e:
199 8316698a Sofia Papagiannaki
                status = messages.ERROR
200 8316698a Sofia Papagiannaki
                message = _('There is already invitation for %s' % username)
201 8316698a Sofia Papagiannaki
                transaction.rollback()
202 64cd4730 Antony Chazapis
        else:
203 890b0eaf Sofia Papagiannaki
            status = messages.ERROR
204 64cd4730 Antony Chazapis
            message = _('No invitations left')
205 890b0eaf Sofia Papagiannaki
    messages.add_message(request, status, message)
206 890b0eaf Sofia Papagiannaki
    
207 a196eb7e Sofia Papagiannaki
    sent = [{'email': inv.username,
208 d6ae71a2 root
             'realname': inv.realname,
209 d6ae71a2 root
             'is_consumed': inv.is_consumed}
210 d6ae71a2 root
             for inv in inviter.invitations_sent.all()]
211 77e2ad52 root
    kwargs = {'inviter': inviter,
212 a196eb7e Sofia Papagiannaki
              'sent':sent}
213 0905ccd2 Sofia Papagiannaki
    context = get_context(request, extra_context, **kwargs)
214 0905ccd2 Sofia Papagiannaki
    return render_response(template_name,
215 0905ccd2 Sofia Papagiannaki
                           context_instance = context)
216 64cd4730 Antony Chazapis
217 890b0eaf Sofia Papagiannaki
@login_required
218 270dd48d Sofia Papagiannaki
@signed_terms_required
219 1e685275 Sofia Papagiannaki
def edit_profile(request, template_name='im/profile.html', extra_context={}):
220 890b0eaf Sofia Papagiannaki
    """
221 890b0eaf Sofia Papagiannaki
    Allows a user to edit his/her profile.
222 64cd4730 Antony Chazapis
    
223 890b0eaf Sofia Papagiannaki
    In case of GET request renders a form for displaying the user information.
224 ce86cd44 Sofia Papagiannaki
    In case of POST updates the user informantion and redirects to ``next``
225 ce86cd44 Sofia Papagiannaki
    url parameter if exists.
226 890b0eaf Sofia Papagiannaki
    
227 2cbaacd5 Sofia Papagiannaki
    If the user isn't logged in, redirects to settings.LOGIN_URL.
228 890b0eaf Sofia Papagiannaki
    
229 890b0eaf Sofia Papagiannaki
    **Arguments**
230 890b0eaf Sofia Papagiannaki
    
231 890b0eaf Sofia Papagiannaki
    ``template_name``
232 890b0eaf Sofia Papagiannaki
        A custom template to use. This is optional; if not specified,
233 1e685275 Sofia Papagiannaki
        this will default to ``im/profile.html``.
234 890b0eaf Sofia Papagiannaki
    
235 890b0eaf Sofia Papagiannaki
    ``extra_context``
236 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
237 890b0eaf Sofia Papagiannaki
    
238 890b0eaf Sofia Papagiannaki
    **Template:**
239 890b0eaf Sofia Papagiannaki
    
240 1e685275 Sofia Papagiannaki
    im/profile.html or ``template_name`` keyword argument.
241 92defad4 Sofia Papagiannaki
    
242 92defad4 Sofia Papagiannaki
    **Settings:**
243 92defad4 Sofia Papagiannaki
    
244 92defad4 Sofia Papagiannaki
    The view expectes the following settings are defined:
245 92defad4 Sofia Papagiannaki
    
246 92defad4 Sofia Papagiannaki
    * LOGIN_URL: login uri
247 890b0eaf Sofia Papagiannaki
    """
248 15efc749 Sofia Papagiannaki
    form = ProfileForm(instance=request.user)
249 15efc749 Sofia Papagiannaki
    extra_context['next'] = request.GET.get('next')
250 c301698f Sofia Papagiannaki
    reset_cookie = False
251 64cd4730 Antony Chazapis
    if request.method == 'POST':
252 15efc749 Sofia Papagiannaki
        form = ProfileForm(request.POST, instance=request.user)
253 890b0eaf Sofia Papagiannaki
        if form.is_valid():
254 64cd4730 Antony Chazapis
            try:
255 c301698f Sofia Papagiannaki
                prev_token = request.user.auth_token
256 c301698f Sofia Papagiannaki
                user = form.save()
257 c301698f Sofia Papagiannaki
                reset_cookie = user.auth_token != prev_token
258 c301698f Sofia Papagiannaki
                form = ProfileForm(instance=user)
259 1a3675a0 Sofia Papagiannaki
                next = request.POST.get('next')
260 1a3675a0 Sofia Papagiannaki
                if next:
261 1a3675a0 Sofia Papagiannaki
                    return redirect(next)
262 890b0eaf Sofia Papagiannaki
                msg = _('Profile has been updated successfully')
263 890b0eaf Sofia Papagiannaki
                messages.add_message(request, messages.SUCCESS, msg)
264 890b0eaf Sofia Papagiannaki
            except ValueError, ve:
265 890b0eaf Sofia Papagiannaki
                messages.add_message(request, messages.ERROR, ve)
266 0905ccd2 Sofia Papagiannaki
    return render_response(template_name,
267 c301698f Sofia Papagiannaki
                           reset_cookie = reset_cookie,
268 890b0eaf Sofia Papagiannaki
                           form = form,
269 0905ccd2 Sofia Papagiannaki
                           context_instance = get_context(request,
270 c301698f Sofia Papagiannaki
                                                          extra_context))
271 64cd4730 Antony Chazapis
272 1e685275 Sofia Papagiannaki
def signup(request, on_failure='im/signup.html', on_success='im/signup_complete.html', extra_context={}, backend=None):
273 890b0eaf Sofia Papagiannaki
    """
274 890b0eaf Sofia Papagiannaki
    Allows a user to create a local account.
275 64cd4730 Antony Chazapis
    
276 890b0eaf Sofia Papagiannaki
    In case of GET request renders a form for providing the user information.
277 890b0eaf Sofia Papagiannaki
    In case of POST handles the signup.
278 890b0eaf Sofia Papagiannaki
    
279 890b0eaf Sofia Papagiannaki
    The user activation will be delegated to the backend specified by the ``backend`` keyword argument
280 890b0eaf Sofia Papagiannaki
    if present, otherwise to the ``astakos.im.backends.InvitationBackend``
281 92defad4 Sofia Papagiannaki
    if settings.ASTAKOS_INVITATIONS_ENABLED is True or ``astakos.im.backends.SimpleBackend`` if not
282 890b0eaf Sofia Papagiannaki
    (see backends);
283 890b0eaf Sofia Papagiannaki
    
284 890b0eaf Sofia Papagiannaki
    Upon successful user creation if ``next`` url parameter is present the user is redirected there
285 890b0eaf Sofia Papagiannaki
    otherwise renders the same page with a success message.
286 64cd4730 Antony Chazapis
    
287 8316698a Sofia Papagiannaki
    On unsuccessful creation, renders ``on_failure`` with an error message.
288 890b0eaf Sofia Papagiannaki
    
289 890b0eaf Sofia Papagiannaki
    **Arguments**
290 890b0eaf Sofia Papagiannaki
    
291 f7e8a159 Sofia Papagiannaki
    ``on_failure``
292 f7e8a159 Sofia Papagiannaki
        A custom template to render in case of failure. This is optional;
293 1e685275 Sofia Papagiannaki
        if not specified, this will default to ``im/signup.html``.
294 f7e8a159 Sofia Papagiannaki
    
295 f7e8a159 Sofia Papagiannaki
    
296 f7e8a159 Sofia Papagiannaki
    ``on_success``
297 f7e8a159 Sofia Papagiannaki
        A custom template to render in case of success. This is optional;
298 1e685275 Sofia Papagiannaki
        if not specified, this will default to ``im/signup_complete.html``.
299 890b0eaf Sofia Papagiannaki
    
300 890b0eaf Sofia Papagiannaki
    ``extra_context``
301 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
302 890b0eaf Sofia Papagiannaki
    
303 890b0eaf Sofia Papagiannaki
    **Template:**
304 890b0eaf Sofia Papagiannaki
    
305 1e685275 Sofia Papagiannaki
    im/signup.html or ``on_failure`` keyword argument.
306 1e685275 Sofia Papagiannaki
    im/signup_complete.html or ``on_success`` keyword argument. 
307 890b0eaf Sofia Papagiannaki
    """
308 0d02a287 Sofia Papagiannaki
    if request.user.is_authenticated():
309 0d02a287 Sofia Papagiannaki
        return HttpResponseRedirect(reverse('astakos.im.views.index'))
310 890b0eaf Sofia Papagiannaki
    try:
311 81c94f7b Sofia Papagiannaki
        if not backend:
312 81c94f7b Sofia Papagiannaki
            backend = get_backend(request)
313 92defad4 Sofia Papagiannaki
        for provider in IM_MODULES:
314 15efc749 Sofia Papagiannaki
            extra_context['%s_form' % provider] = backend.get_signup_form(provider)
315 890b0eaf Sofia Papagiannaki
        if request.method == 'POST':
316 15efc749 Sofia Papagiannaki
            provider = request.POST.get('provider')
317 15efc749 Sofia Papagiannaki
            next = request.POST.get('next', '')
318 15efc749 Sofia Papagiannaki
            form = extra_context['%s_form' % provider]
319 890b0eaf Sofia Papagiannaki
            if form.is_valid():
320 15efc749 Sofia Papagiannaki
                if provider != 'local':
321 15efc749 Sofia Papagiannaki
                    url = reverse('astakos.im.target.%s.login' % provider)
322 15efc749 Sofia Papagiannaki
                    url = '%s?email=%s&next=%s' % (url, form.data['email'], next)
323 15efc749 Sofia Papagiannaki
                    if backend.invitation:
324 15efc749 Sofia Papagiannaki
                        url = '%s&code=%s' % (url, backend.invitation.code)
325 15efc749 Sofia Papagiannaki
                    return redirect(url)
326 890b0eaf Sofia Papagiannaki
                else:
327 15efc749 Sofia Papagiannaki
                    status, message, user = backend.signup(form)
328 63ecdd20 Sofia Papagiannaki
                    if user and user.is_active:
329 63ecdd20 Sofia Papagiannaki
                        return prepare_response(request, user, next=next)
330 f7e8a159 Sofia Papagiannaki
                    messages.add_message(request, status, message)
331 f7e8a159 Sofia Papagiannaki
                    return render_response(on_success,
332 0d02a287 Sofia Papagiannaki
                                           context_instance=get_context(request, extra_context))
333 15efc749 Sofia Papagiannaki
    except (Invitation.DoesNotExist, ValueError), e:
334 890b0eaf Sofia Papagiannaki
        messages.add_message(request, messages.ERROR, e)
335 92defad4 Sofia Papagiannaki
        for provider in IM_MODULES:
336 15efc749 Sofia Papagiannaki
            main = provider.capitalize() if provider == 'local' else 'ThirdParty'
337 15efc749 Sofia Papagiannaki
            formclass = '%sUserCreationForm' % main
338 15efc749 Sofia Papagiannaki
            extra_context['%s_form' % provider] = globals()[formclass]()
339 f7e8a159 Sofia Papagiannaki
    return render_response(on_failure,
340 890b0eaf Sofia Papagiannaki
                           context_instance=get_context(request, extra_context))
341 64cd4730 Antony Chazapis
342 890b0eaf Sofia Papagiannaki
@login_required
343 270dd48d Sofia Papagiannaki
@signed_terms_required
344 1e685275 Sofia Papagiannaki
def send_feedback(request, template_name='im/feedback.html', email_template_name='im/feedback_mail.txt', extra_context={}):
345 890b0eaf Sofia Papagiannaki
    """
346 890b0eaf Sofia Papagiannaki
    Allows a user to send feedback.
347 890b0eaf Sofia Papagiannaki
    
348 890b0eaf Sofia Papagiannaki
    In case of GET request renders a form for providing the feedback information.
349 890b0eaf Sofia Papagiannaki
    In case of POST sends an email to support team.
350 890b0eaf Sofia Papagiannaki
    
351 2cbaacd5 Sofia Papagiannaki
    If the user isn't logged in, redirects to settings.LOGIN_URL.
352 890b0eaf Sofia Papagiannaki
    
353 890b0eaf Sofia Papagiannaki
    **Arguments**
354 890b0eaf Sofia Papagiannaki
    
355 890b0eaf Sofia Papagiannaki
    ``template_name``
356 890b0eaf Sofia Papagiannaki
        A custom template to use. This is optional; if not specified,
357 1e685275 Sofia Papagiannaki
        this will default to ``im/feedback.html``.
358 890b0eaf Sofia Papagiannaki
    
359 890b0eaf Sofia Papagiannaki
    ``extra_context``
360 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
361 890b0eaf Sofia Papagiannaki
    
362 890b0eaf Sofia Papagiannaki
    **Template:**
363 64cd4730 Antony Chazapis
    
364 1e685275 Sofia Papagiannaki
    im/signup.html or ``template_name`` keyword argument.
365 890b0eaf Sofia Papagiannaki
    
366 890b0eaf Sofia Papagiannaki
    **Settings:**
367 890b0eaf Sofia Papagiannaki
    
368 92defad4 Sofia Papagiannaki
    * LOGIN_URL: login uri
369 2cbaacd5 Sofia Papagiannaki
    * ASTAKOS_DEFAULT_CONTACT_EMAIL: List of feedback recipients
370 890b0eaf Sofia Papagiannaki
    """
371 64cd4730 Antony Chazapis
    if request.method == 'GET':
372 890b0eaf Sofia Papagiannaki
        form = FeedbackForm()
373 890b0eaf Sofia Papagiannaki
    if request.method == 'POST':
374 890b0eaf Sofia Papagiannaki
        if not request.user:
375 890b0eaf Sofia Papagiannaki
            return HttpResponse('Unauthorized', status=401)
376 64cd4730 Antony Chazapis
        
377 890b0eaf Sofia Papagiannaki
        form = FeedbackForm(request.POST)
378 890b0eaf Sofia Papagiannaki
        if form.is_valid():
379 4abc7b29 Sofia Papagiannaki
            subject = _("Feedback from %s alpha2 testing" % SITENAME)
380 890b0eaf Sofia Papagiannaki
            from_email = request.user.email
381 d552ecb7 Antony Chazapis
            recipient_list = [DEFAULT_CONTACT_EMAIL]
382 890b0eaf Sofia Papagiannaki
            content = render_to_string(email_template_name, {
383 538ccdd5 Sofia Papagiannaki
                        'message': form.cleaned_data['feedback_msg'],
384 538ccdd5 Sofia Papagiannaki
                        'data': form.cleaned_data['feedback_data'],
385 890b0eaf Sofia Papagiannaki
                        'request': request})
386 64cd4730 Antony Chazapis
            
387 538ccdd5 Sofia Papagiannaki
            try:
388 538ccdd5 Sofia Papagiannaki
                send_mail(subject, content, from_email, recipient_list)
389 538ccdd5 Sofia Papagiannaki
                message = _('Feedback successfully sent')
390 538ccdd5 Sofia Papagiannaki
                status = messages.SUCCESS
391 538ccdd5 Sofia Papagiannaki
            except (SMTPException, socket.error) as e:
392 538ccdd5 Sofia Papagiannaki
                status = messages.ERROR
393 538ccdd5 Sofia Papagiannaki
                message = getattr(e, 'strerror', '')
394 538ccdd5 Sofia Papagiannaki
            messages.add_message(request, status, message)
395 890b0eaf Sofia Papagiannaki
    return render_response(template_name,
396 890b0eaf Sofia Papagiannaki
                           form = form,
397 6b4f9fb2 Sofia Papagiannaki
                           context_instance = get_context(request, extra_context))
398 15efc749 Sofia Papagiannaki
399 7482228b Sofia Papagiannaki
def logout(request, template='registration/logged_out.html', extra_context={}):
400 63ecdd20 Sofia Papagiannaki
    """
401 7482228b Sofia Papagiannaki
    Wraps `django.contrib.auth.logout` and delete the cookie.
402 63ecdd20 Sofia Papagiannaki
    """
403 7482228b Sofia Papagiannaki
    auth_logout(request)
404 7482228b Sofia Papagiannaki
    response = HttpResponse()
405 28ff5b5d Antony Chazapis
    response.delete_cookie(COOKIE_NAME, path='/', domain=COOKIE_DOMAIN)
406 63ecdd20 Sofia Papagiannaki
    next = request.GET.get('next')
407 63ecdd20 Sofia Papagiannaki
    if next:
408 63ecdd20 Sofia Papagiannaki
        response['Location'] = next
409 63ecdd20 Sofia Papagiannaki
        response.status_code = 302
410 63ecdd20 Sofia Papagiannaki
        return response
411 0d02a287 Sofia Papagiannaki
    elif LOGOUT_NEXT:
412 0d02a287 Sofia Papagiannaki
        response['Location'] = LOGOUT_NEXT
413 0d02a287 Sofia Papagiannaki
        response.status_code = 301
414 0d02a287 Sofia Papagiannaki
        return response
415 0d02a287 Sofia Papagiannaki
    messages.add_message(request, messages.SUCCESS, _('You have successfully logged out.'))
416 49df775e Sofia Papagiannaki
    context = get_context(request, extra_context)
417 49df775e Sofia Papagiannaki
    response.write(render_to_string(template, context_instance=context))
418 49df775e Sofia Papagiannaki
    return response
419 2126d85d Sofia Papagiannaki
420 683cf244 Sofia Papagiannaki
@transaction.commit_manually
421 683cf244 Sofia Papagiannaki
def activate(request, email_template_name='im/welcome_email.txt', on_failure=''):
422 2126d85d Sofia Papagiannaki
    """
423 683cf244 Sofia Papagiannaki
    Activates the user identified by the ``auth`` request parameter, sends a welcome email
424 683cf244 Sofia Papagiannaki
    and renews the user token.
425 683cf244 Sofia Papagiannaki
    
426 683cf244 Sofia Papagiannaki
    The view uses commit_manually decorator in order to ensure the user state will be updated
427 683cf244 Sofia Papagiannaki
    only if the email will be send successfully.
428 2126d85d Sofia Papagiannaki
    """
429 2126d85d Sofia Papagiannaki
    token = request.GET.get('auth')
430 2126d85d Sofia Papagiannaki
    next = request.GET.get('next')
431 2126d85d Sofia Papagiannaki
    try:
432 2126d85d Sofia Papagiannaki
        user = AstakosUser.objects.get(auth_token=token)
433 2126d85d Sofia Papagiannaki
    except AstakosUser.DoesNotExist:
434 683cf244 Sofia Papagiannaki
        return HttpResponseBadRequest(_('No such user'))
435 2126d85d Sofia Papagiannaki
    
436 2126d85d Sofia Papagiannaki
    user.is_active = True
437 8316698a Sofia Papagiannaki
    user.email_verified = True
438 2126d85d Sofia Papagiannaki
    user.save()
439 683cf244 Sofia Papagiannaki
    try:
440 683cf244 Sofia Papagiannaki
        send_greeting(user, email_template_name)
441 683cf244 Sofia Papagiannaki
        response = prepare_response(request, user, next, renew=True)
442 683cf244 Sofia Papagiannaki
        transaction.commit()
443 683cf244 Sofia Papagiannaki
        return response
444 683cf244 Sofia Papagiannaki
    except (SMTPException, socket.error) as e:
445 683cf244 Sofia Papagiannaki
        message = getattr(e, 'name') if hasattr(e, 'name') else e
446 683cf244 Sofia Papagiannaki
        messages.add_message(request, messages.ERROR, message)
447 683cf244 Sofia Papagiannaki
        transaction.rollback()
448 683cf244 Sofia Papagiannaki
        return signup(request, on_failure='im/signup.html')
449 270dd48d Sofia Papagiannaki
450 270dd48d Sofia Papagiannaki
def approval_terms(request, term_id=None, template_name='im/approval_terms.html', extra_context={}):
451 270dd48d Sofia Papagiannaki
    term = None
452 270dd48d Sofia Papagiannaki
    terms = None
453 270dd48d Sofia Papagiannaki
    if not term_id:
454 270dd48d Sofia Papagiannaki
        try:
455 270dd48d Sofia Papagiannaki
            term = ApprovalTerms.objects.order_by('-id')[0]
456 270dd48d Sofia Papagiannaki
        except IndexError:
457 270dd48d Sofia Papagiannaki
            pass
458 270dd48d Sofia Papagiannaki
    else:
459 270dd48d Sofia Papagiannaki
        try:
460 270dd48d Sofia Papagiannaki
             term = ApprovalTerms.objects.get(id=term_id)
461 270dd48d Sofia Papagiannaki
        except ApprovalTermDoesNotExist, e:
462 270dd48d Sofia Papagiannaki
            pass
463 270dd48d Sofia Papagiannaki
    
464 270dd48d Sofia Papagiannaki
    if not term:
465 270dd48d Sofia Papagiannaki
        return HttpResponseBadRequest(_('No approval terms found.'))
466 270dd48d Sofia Papagiannaki
    f = open(term.location, 'r')
467 270dd48d Sofia Papagiannaki
    terms = f.read()
468 270dd48d Sofia Papagiannaki
    
469 270dd48d Sofia Papagiannaki
    if request.method == 'POST':
470 270dd48d Sofia Papagiannaki
        next = request.POST.get('next')
471 270dd48d Sofia Papagiannaki
        if not next:
472 270dd48d Sofia Papagiannaki
            return HttpResponseBadRequest(_('No next param.'))
473 270dd48d Sofia Papagiannaki
        form = SignApprovalTermsForm(request.POST, instance=request.user)
474 270dd48d Sofia Papagiannaki
        if not form.is_valid():
475 270dd48d Sofia Papagiannaki
            return render_response(template_name,
476 270dd48d Sofia Papagiannaki
                           terms = terms,
477 270dd48d Sofia Papagiannaki
                           form = form,
478 270dd48d Sofia Papagiannaki
                           context_instance = get_context(request, extra_context))
479 270dd48d Sofia Papagiannaki
        user = form.save()
480 270dd48d Sofia Papagiannaki
        return HttpResponseRedirect(next)
481 270dd48d Sofia Papagiannaki
    else:
482 270dd48d Sofia Papagiannaki
        form = SignApprovalTermsForm(instance=request.user) if request.user.is_authenticated() else None
483 270dd48d Sofia Papagiannaki
        return render_response(template_name,
484 270dd48d Sofia Papagiannaki
                               terms = terms,
485 270dd48d Sofia Papagiannaki
                               form = form,
486 270dd48d Sofia Papagiannaki
                               context_instance = get_context(request, extra_context))
487 270dd48d Sofia Papagiannaki
488 270dd48d Sofia Papagiannaki
@signed_terms_required
489 270dd48d Sofia Papagiannaki
def change_password(request):
490 270dd48d Sofia Papagiannaki
    return password_change(request, post_change_redirect=reverse('astakos.im.views.edit_profile'))