Statistics
| Branch: | Tag: | Revision:

root / astakos / im / views.py @ 13858d75

History | View | Annotate | Download (15.5 kB)

1 aba1e498 Antony Chazapis
# Copyright 2011-2012 GRNET S.A. All rights reserved.
2 13858d75 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 13858d75 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 13858d75 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 13858d75 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 13858d75 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 json
35 64cd4730 Antony Chazapis
import logging
36 64cd4730 Antony Chazapis
import socket
37 64cd4730 Antony Chazapis
import csv
38 64cd4730 Antony Chazapis
import sys
39 64cd4730 Antony Chazapis
40 64cd4730 Antony Chazapis
from datetime import datetime
41 64cd4730 Antony Chazapis
from functools import wraps
42 64cd4730 Antony Chazapis
from math import ceil
43 64cd4730 Antony Chazapis
from random import randint
44 64cd4730 Antony Chazapis
from smtplib import SMTPException
45 0905ccd2 Sofia Papagiannaki
from hashlib import new as newhasher
46 0905ccd2 Sofia Papagiannaki
from urllib import quote
47 64cd4730 Antony Chazapis
48 64cd4730 Antony Chazapis
from django.conf import settings
49 64cd4730 Antony Chazapis
from django.core.mail import send_mail
50 64cd4730 Antony Chazapis
from django.http import HttpResponse, HttpResponseRedirect, HttpResponseBadRequest
51 64cd4730 Antony Chazapis
from django.shortcuts import redirect
52 64cd4730 Antony Chazapis
from django.template.loader import render_to_string
53 64cd4730 Antony Chazapis
from django.shortcuts import render_to_response
54 64cd4730 Antony Chazapis
from django.utils.http import urlencode
55 64cd4730 Antony Chazapis
from django.utils.translation import ugettext as _
56 64cd4730 Antony Chazapis
from django.core.urlresolvers import reverse
57 890b0eaf Sofia Papagiannaki
from django.contrib.auth.models import AnonymousUser
58 890b0eaf Sofia Papagiannaki
from django.contrib.auth.decorators import login_required
59 dbe090ba root
from django.contrib.sites.models import Site
60 890b0eaf Sofia Papagiannaki
from django.contrib import messages
61 890b0eaf Sofia Papagiannaki
from django.db import transaction
62 890b0eaf Sofia Papagiannaki
from django.contrib.auth.forms import UserCreationForm
63 64cd4730 Antony Chazapis
64 0905ccd2 Sofia Papagiannaki
from astakos.im.models import AstakosUser, Invitation
65 0905ccd2 Sofia Papagiannaki
from astakos.im.backends import get_backend
66 15efc749 Sofia Papagiannaki
from astakos.im.util import get_context, get_current_site, get_invitation
67 15efc749 Sofia Papagiannaki
from astakos.im.forms import *
68 64cd4730 Antony Chazapis
69 0905ccd2 Sofia Papagiannaki
def render_response(template, tab=None, status=200, context_instance=None, **kwargs):
70 890b0eaf Sofia Papagiannaki
    """
71 890b0eaf Sofia Papagiannaki
    Calls ``django.template.loader.render_to_string`` with an additional ``tab``
72 890b0eaf Sofia Papagiannaki
    keyword argument and returns an ``django.http.HttpResponse`` with the
73 890b0eaf Sofia Papagiannaki
    specified ``status``.
74 890b0eaf Sofia Papagiannaki
    """
75 64cd4730 Antony Chazapis
    if tab is None:
76 881c856c Sofia Papagiannaki
        tab = template.partition('_')[0].partition('.html')[0]
77 64cd4730 Antony Chazapis
    kwargs.setdefault('tab', tab)
78 0905ccd2 Sofia Papagiannaki
    html = render_to_string(template, kwargs, context_instance=context_instance)
79 64cd4730 Antony Chazapis
    return HttpResponse(html, status=status)
80 64cd4730 Antony Chazapis
81 dcf55476 Sofia Papagiannaki
def index(request, login_template_name='login.html', profile_template_name='profile.html', extra_context={}):
82 890b0eaf Sofia Papagiannaki
    """
83 dcf55476 Sofia Papagiannaki
    If there is logged on user renders the profile page otherwise renders login page.
84 13858d75 Kostas Papadimitriou

85 890b0eaf Sofia Papagiannaki
    **Arguments**
86 13858d75 Kostas Papadimitriou

87 dcf55476 Sofia Papagiannaki
    ``login_template_name``
88 dcf55476 Sofia Papagiannaki
        A custom login template to use. This is optional; if not specified,
89 dcf55476 Sofia Papagiannaki
        this will default to ``login.html``.
90 13858d75 Kostas Papadimitriou

91 dcf55476 Sofia Papagiannaki
    ``profile_template_name``
92 dcf55476 Sofia Papagiannaki
        A custom profile template to use. This is optional; if not specified,
93 b90b602c Sofia Papagiannaki
        this will default to ``profile.html``.
94 13858d75 Kostas Papadimitriou

95 890b0eaf Sofia Papagiannaki
    ``extra_context``
96 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
97 13858d75 Kostas Papadimitriou

98 890b0eaf Sofia Papagiannaki
    **Template:**
99 13858d75 Kostas Papadimitriou

100 b90b602c Sofia Papagiannaki
    profile.html or login.html or ``template_name`` keyword argument.
101 13858d75 Kostas Papadimitriou

102 890b0eaf Sofia Papagiannaki
    """
103 dcf55476 Sofia Papagiannaki
    template_name = login_template_name
104 dcf55476 Sofia Papagiannaki
    formclass = 'LoginForm'
105 dcf55476 Sofia Papagiannaki
    kwargs = {}
106 dcf55476 Sofia Papagiannaki
    if request.user.is_authenticated():
107 dcf55476 Sofia Papagiannaki
        template_name = profile_template_name
108 dcf55476 Sofia Papagiannaki
        formclass = 'ProfileForm'
109 dcf55476 Sofia Papagiannaki
        kwargs.update({'instance':request.user})
110 0905ccd2 Sofia Papagiannaki
    return render_response(template_name,
111 dcf55476 Sofia Papagiannaki
                           form = globals()[formclass](**kwargs),
112 0905ccd2 Sofia Papagiannaki
                           context_instance = get_context(request, extra_context))
113 64cd4730 Antony Chazapis
114 0905ccd2 Sofia Papagiannaki
def _generate_invitation_code():
115 64cd4730 Antony Chazapis
    while True:
116 64cd4730 Antony Chazapis
        code = randint(1, 2L**63 - 1)
117 64cd4730 Antony Chazapis
        try:
118 64cd4730 Antony Chazapis
            Invitation.objects.get(code=code)
119 64cd4730 Antony Chazapis
            # An invitation with this code already exists, try again
120 64cd4730 Antony Chazapis
        except Invitation.DoesNotExist:
121 64cd4730 Antony Chazapis
            return code
122 64cd4730 Antony Chazapis
123 794852f2 Sofia Papagiannaki
def _send_invitation(request, baseurl, inv):
124 e2125441 Sofia Papagiannaki
    sitename, sitedomain = get_current_site(request, use_https=request.is_secure())
125 e2125441 Sofia Papagiannaki
    subject = _('Invitation to %s' % sitename)
126 e2125441 Sofia Papagiannaki
    url = settings.SIGNUP_TARGET % (baseurl, inv.code, quote(sitedomain))
127 64cd4730 Antony Chazapis
    message = render_to_string('invitation.txt', {
128 64cd4730 Antony Chazapis
                'invitation': inv,
129 64cd4730 Antony Chazapis
                'url': url,
130 64cd4730 Antony Chazapis
                'baseurl': baseurl,
131 e2125441 Sofia Papagiannaki
                'service': sitename,
132 e2125441 Sofia Papagiannaki
                'support': settings.DEFAULT_CONTACT_EMAIL % sitename.lower()})
133 e2125441 Sofia Papagiannaki
    sender = settings.DEFAULT_FROM_EMAIL % sitename
134 0905ccd2 Sofia Papagiannaki
    send_mail(subject, message, sender, [inv.username])
135 64cd4730 Antony Chazapis
    logging.info('Sent invitation %s', inv)
136 64cd4730 Antony Chazapis
137 890b0eaf Sofia Papagiannaki
@login_required
138 890b0eaf Sofia Papagiannaki
@transaction.commit_manually
139 0905ccd2 Sofia Papagiannaki
def invite(request, template_name='invitations.html', extra_context={}):
140 890b0eaf Sofia Papagiannaki
    """
141 890b0eaf Sofia Papagiannaki
    Allows a user to invite somebody else.
142 13858d75 Kostas Papadimitriou

143 890b0eaf Sofia Papagiannaki
    In case of GET request renders a form for providing the invitee information.
144 890b0eaf Sofia Papagiannaki
    In case of POST checks whether the user has not run out of invitations and then
145 890b0eaf Sofia Papagiannaki
    sends an invitation email to singup to the service.
146 13858d75 Kostas Papadimitriou

147 890b0eaf Sofia Papagiannaki
    The view uses commit_manually decorator in order to ensure the number of the
148 890b0eaf Sofia Papagiannaki
    user invitations is going to be updated only if the email has been successfully sent.
149 13858d75 Kostas Papadimitriou

150 890b0eaf Sofia Papagiannaki
    If the user isn't logged in, redirects to settings.LOGIN_URL.
151 13858d75 Kostas Papadimitriou

152 890b0eaf Sofia Papagiannaki
    **Arguments**
153 13858d75 Kostas Papadimitriou

154 890b0eaf Sofia Papagiannaki
    ``template_name``
155 890b0eaf Sofia Papagiannaki
        A custom template to use. This is optional; if not specified,
156 890b0eaf Sofia Papagiannaki
        this will default to ``invitations.html``.
157 13858d75 Kostas Papadimitriou

158 890b0eaf Sofia Papagiannaki
    ``extra_context``
159 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
160 13858d75 Kostas Papadimitriou

161 890b0eaf Sofia Papagiannaki
    **Template:**
162 13858d75 Kostas Papadimitriou

163 890b0eaf Sofia Papagiannaki
    invitations.html or ``template_name`` keyword argument.
164 13858d75 Kostas Papadimitriou

165 890b0eaf Sofia Papagiannaki
    **Settings:**
166 13858d75 Kostas Papadimitriou

167 890b0eaf Sofia Papagiannaki
    The view expectes the following settings are defined:
168 13858d75 Kostas Papadimitriou

169 890b0eaf Sofia Papagiannaki
    * LOGIN_URL: login uri
170 890b0eaf Sofia Papagiannaki
    * SIGNUP_TARGET: Where users should signup with their invitation code
171 890b0eaf Sofia Papagiannaki
    * DEFAULT_CONTACT_EMAIL: service support email
172 890b0eaf Sofia Papagiannaki
    * DEFAULT_FROM_EMAIL: from email
173 890b0eaf Sofia Papagiannaki
    """
174 64cd4730 Antony Chazapis
    status = None
175 64cd4730 Antony Chazapis
    message = None
176 5ed6816e Sofia Papagiannaki
    inviter = AstakosUser.objects.get(username = request.user.username)
177 13858d75 Kostas Papadimitriou
178 64cd4730 Antony Chazapis
    if request.method == 'POST':
179 0905ccd2 Sofia Papagiannaki
        username = request.POST.get('uniq')
180 64cd4730 Antony Chazapis
        realname = request.POST.get('realname')
181 13858d75 Kostas Papadimitriou
182 64cd4730 Antony Chazapis
        if inviter.invitations > 0:
183 0905ccd2 Sofia Papagiannaki
            code = _generate_invitation_code()
184 64cd4730 Antony Chazapis
            invitation, created = Invitation.objects.get_or_create(
185 64cd4730 Antony Chazapis
                inviter=inviter,
186 0905ccd2 Sofia Papagiannaki
                username=username,
187 64cd4730 Antony Chazapis
                defaults={'code': code, 'realname': realname})
188 13858d75 Kostas Papadimitriou
189 64cd4730 Antony Chazapis
            try:
190 794852f2 Sofia Papagiannaki
                baseurl = request.build_absolute_uri('/').rstrip('/')
191 794852f2 Sofia Papagiannaki
                _send_invitation(request, baseurl, invitation)
192 64cd4730 Antony Chazapis
                if created:
193 64cd4730 Antony Chazapis
                    inviter.invitations = max(0, inviter.invitations - 1)
194 64cd4730 Antony Chazapis
                    inviter.save()
195 890b0eaf Sofia Papagiannaki
                status = messages.SUCCESS
196 0905ccd2 Sofia Papagiannaki
                message = _('Invitation sent to %s' % username)
197 890b0eaf Sofia Papagiannaki
                transaction.commit()
198 64cd4730 Antony Chazapis
            except (SMTPException, socket.error) as e:
199 890b0eaf Sofia Papagiannaki
                status = messages.ERROR
200 64cd4730 Antony Chazapis
                message = getattr(e, 'strerror', '')
201 890b0eaf 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 13858d75 Kostas Papadimitriou
207 a196eb7e Sofia Papagiannaki
    sent = [{'email': inv.username,
208 64cd4730 Antony Chazapis
                 'realname': inv.realname,
209 64cd4730 Antony Chazapis
                 'is_accepted': inv.is_accepted}
210 64cd4730 Antony Chazapis
                    for inv in inviter.invitations_sent.all()]
211 a196eb7e Sofia Papagiannaki
    kwargs = {'user': 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 890b0eaf Sofia Papagiannaki
def edit_profile(request, template_name='profile.html', extra_context={}):
219 890b0eaf Sofia Papagiannaki
    """
220 890b0eaf Sofia Papagiannaki
    Allows a user to edit his/her profile.
221 13858d75 Kostas Papadimitriou

222 890b0eaf Sofia Papagiannaki
    In case of GET request renders a form for displaying the user information.
223 ce86cd44 Sofia Papagiannaki
    In case of POST updates the user informantion and redirects to ``next``
224 ce86cd44 Sofia Papagiannaki
    url parameter if exists.
225 13858d75 Kostas Papadimitriou

226 13858d75 Kostas Papadimitriou
    If the user isn't logged in, redirects to settings.LOGIN_URL.
227 13858d75 Kostas Papadimitriou

228 890b0eaf Sofia Papagiannaki
    **Arguments**
229 13858d75 Kostas Papadimitriou

230 890b0eaf Sofia Papagiannaki
    ``template_name``
231 890b0eaf Sofia Papagiannaki
        A custom template to use. This is optional; if not specified,
232 890b0eaf Sofia Papagiannaki
        this will default to ``profile.html``.
233 13858d75 Kostas Papadimitriou

234 890b0eaf Sofia Papagiannaki
    ``extra_context``
235 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
236 13858d75 Kostas Papadimitriou

237 890b0eaf Sofia Papagiannaki
    **Template:**
238 13858d75 Kostas Papadimitriou

239 890b0eaf Sofia Papagiannaki
    profile.html or ``template_name`` keyword argument.
240 890b0eaf Sofia Papagiannaki
    """
241 15efc749 Sofia Papagiannaki
    form = ProfileForm(instance=request.user)
242 15efc749 Sofia Papagiannaki
    extra_context['next'] = request.GET.get('next')
243 64cd4730 Antony Chazapis
    if request.method == 'POST':
244 15efc749 Sofia Papagiannaki
        form = ProfileForm(request.POST, instance=request.user)
245 890b0eaf Sofia Papagiannaki
        if form.is_valid():
246 64cd4730 Antony Chazapis
            try:
247 890b0eaf Sofia Papagiannaki
                form.save()
248 890b0eaf Sofia Papagiannaki
                msg = _('Profile has been updated successfully')
249 890b0eaf Sofia Papagiannaki
                messages.add_message(request, messages.SUCCESS, msg)
250 890b0eaf Sofia Papagiannaki
            except ValueError, ve:
251 890b0eaf Sofia Papagiannaki
                messages.add_message(request, messages.ERROR, ve)
252 ce86cd44 Sofia Papagiannaki
        next = request.POST.get('next')
253 ce86cd44 Sofia Papagiannaki
        if next:
254 ce86cd44 Sofia Papagiannaki
            return redirect(next)
255 0905ccd2 Sofia Papagiannaki
    return render_response(template_name,
256 890b0eaf Sofia Papagiannaki
                           form = form,
257 0905ccd2 Sofia Papagiannaki
                           context_instance = get_context(request,
258 0905ccd2 Sofia Papagiannaki
                                                          extra_context,
259 15efc749 Sofia Papagiannaki
                                                          user=request.user))
260 64cd4730 Antony Chazapis
261 890b0eaf Sofia Papagiannaki
def signup(request, template_name='signup.html', extra_context={}, backend=None):
262 890b0eaf Sofia Papagiannaki
    """
263 890b0eaf Sofia Papagiannaki
    Allows a user to create a local account.
264 13858d75 Kostas Papadimitriou

265 890b0eaf Sofia Papagiannaki
    In case of GET request renders a form for providing the user information.
266 890b0eaf Sofia Papagiannaki
    In case of POST handles the signup.
267 13858d75 Kostas Papadimitriou

268 890b0eaf Sofia Papagiannaki
    The user activation will be delegated to the backend specified by the ``backend`` keyword argument
269 890b0eaf Sofia Papagiannaki
    if present, otherwise to the ``astakos.im.backends.InvitationBackend``
270 890b0eaf Sofia Papagiannaki
    if settings.INVITATIONS_ENABLED is True or ``astakos.im.backends.SimpleBackend`` if not
271 890b0eaf Sofia Papagiannaki
    (see backends);
272 13858d75 Kostas Papadimitriou

273 890b0eaf Sofia Papagiannaki
    Upon successful user creation if ``next`` url parameter is present the user is redirected there
274 890b0eaf Sofia Papagiannaki
    otherwise renders the same page with a success message.
275 13858d75 Kostas Papadimitriou

276 890b0eaf Sofia Papagiannaki
    On unsuccessful creation, renders the same page with an error message.
277 13858d75 Kostas Papadimitriou

278 890b0eaf Sofia Papagiannaki
    **Arguments**
279 13858d75 Kostas Papadimitriou

280 890b0eaf Sofia Papagiannaki
    ``template_name``
281 890b0eaf Sofia Papagiannaki
        A custom template to use. This is optional; if not specified,
282 890b0eaf Sofia Papagiannaki
        this will default to ``signup.html``.
283 13858d75 Kostas Papadimitriou

284 890b0eaf Sofia Papagiannaki
    ``extra_context``
285 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
286 13858d75 Kostas Papadimitriou

287 890b0eaf Sofia Papagiannaki
    **Template:**
288 13858d75 Kostas Papadimitriou

289 890b0eaf Sofia Papagiannaki
    signup.html or ``template_name`` keyword argument.
290 890b0eaf Sofia Papagiannaki
    """
291 890b0eaf Sofia Papagiannaki
    try:
292 81c94f7b Sofia Papagiannaki
        if not backend:
293 81c94f7b Sofia Papagiannaki
            backend = get_backend(request)
294 15efc749 Sofia Papagiannaki
        for provider in settings.IM_MODULES:
295 15efc749 Sofia Papagiannaki
            extra_context['%s_form' % provider] = backend.get_signup_form(provider)
296 890b0eaf Sofia Papagiannaki
        if request.method == 'POST':
297 15efc749 Sofia Papagiannaki
            provider = request.POST.get('provider')
298 15efc749 Sofia Papagiannaki
            next = request.POST.get('next', '')
299 15efc749 Sofia Papagiannaki
            form = extra_context['%s_form' % provider]
300 890b0eaf Sofia Papagiannaki
            if form.is_valid():
301 15efc749 Sofia Papagiannaki
                if provider != 'local':
302 15efc749 Sofia Papagiannaki
                    url = reverse('astakos.im.target.%s.login' % provider)
303 15efc749 Sofia Papagiannaki
                    url = '%s?email=%s&next=%s' % (url, form.data['email'], next)
304 15efc749 Sofia Papagiannaki
                    if backend.invitation:
305 15efc749 Sofia Papagiannaki
                        url = '%s&code=%s' % (url, backend.invitation.code)
306 15efc749 Sofia Papagiannaki
                    return redirect(url)
307 890b0eaf Sofia Papagiannaki
                else:
308 15efc749 Sofia Papagiannaki
                    status, message, user = backend.signup(form)
309 15efc749 Sofia Papagiannaki
                    if status == messages.SUCCESS:
310 15efc749 Sofia Papagiannaki
                        if next:
311 15efc749 Sofia Papagiannaki
                            return redirect(next)
312 13858d75 Kostas Papadimitriou
                    messages.add_message(request, status, message)
313 15efc749 Sofia Papagiannaki
    except (Invitation.DoesNotExist, ValueError), e:
314 890b0eaf Sofia Papagiannaki
        messages.add_message(request, messages.ERROR, e)
315 15efc749 Sofia Papagiannaki
        for provider in settings.IM_MODULES:
316 15efc749 Sofia Papagiannaki
            main = provider.capitalize() if provider == 'local' else 'ThirdParty'
317 15efc749 Sofia Papagiannaki
            formclass = '%sUserCreationForm' % main
318 15efc749 Sofia Papagiannaki
            extra_context['%s_form' % provider] = globals()[formclass]()
319 890b0eaf Sofia Papagiannaki
    return render_response(template_name,
320 890b0eaf Sofia Papagiannaki
                           context_instance=get_context(request, extra_context))
321 64cd4730 Antony Chazapis
322 890b0eaf Sofia Papagiannaki
@login_required
323 890b0eaf Sofia Papagiannaki
def send_feedback(request, template_name='feedback.html', email_template_name='feedback_mail.txt', extra_context={}):
324 890b0eaf Sofia Papagiannaki
    """
325 890b0eaf Sofia Papagiannaki
    Allows a user to send feedback.
326 13858d75 Kostas Papadimitriou

327 890b0eaf Sofia Papagiannaki
    In case of GET request renders a form for providing the feedback information.
328 890b0eaf Sofia Papagiannaki
    In case of POST sends an email to support team.
329 13858d75 Kostas Papadimitriou

330 13858d75 Kostas Papadimitriou
    If the user isn't logged in, redirects to settings.LOGIN_URL.
331 13858d75 Kostas Papadimitriou

332 890b0eaf Sofia Papagiannaki
    **Arguments**
333 13858d75 Kostas Papadimitriou

334 890b0eaf Sofia Papagiannaki
    ``template_name``
335 890b0eaf Sofia Papagiannaki
        A custom template to use. This is optional; if not specified,
336 890b0eaf Sofia Papagiannaki
        this will default to ``feedback.html``.
337 13858d75 Kostas Papadimitriou

338 890b0eaf Sofia Papagiannaki
    ``extra_context``
339 890b0eaf Sofia Papagiannaki
        An dictionary of variables to add to the template context.
340 13858d75 Kostas Papadimitriou

341 890b0eaf Sofia Papagiannaki
    **Template:**
342 13858d75 Kostas Papadimitriou

343 890b0eaf Sofia Papagiannaki
    signup.html or ``template_name`` keyword argument.
344 13858d75 Kostas Papadimitriou

345 890b0eaf Sofia Papagiannaki
    **Settings:**
346 13858d75 Kostas Papadimitriou

347 74f643ad Sofia Papagiannaki
    * DEFAULT_CONTACT_EMAIL: List of feedback recipients
348 890b0eaf Sofia Papagiannaki
    """
349 64cd4730 Antony Chazapis
    if request.method == 'GET':
350 890b0eaf Sofia Papagiannaki
        form = FeedbackForm()
351 890b0eaf Sofia Papagiannaki
    if request.method == 'POST':
352 890b0eaf Sofia Papagiannaki
        if not request.user:
353 890b0eaf Sofia Papagiannaki
            return HttpResponse('Unauthorized', status=401)
354 13858d75 Kostas Papadimitriou
355 890b0eaf Sofia Papagiannaki
        form = FeedbackForm(request.POST)
356 890b0eaf Sofia Papagiannaki
        if form.is_valid():
357 e2125441 Sofia Papagiannaki
            sitename, sitedomain = get_current_site(request, use_https=request.is_secure())
358 e2125441 Sofia Papagiannaki
            subject = _("Feedback from %s" % sitename)
359 890b0eaf Sofia Papagiannaki
            from_email = request.user.email
360 e2125441 Sofia Papagiannaki
            recipient_list = [settings.DEFAULT_CONTACT_EMAIL % sitename.lower()]
361 890b0eaf Sofia Papagiannaki
            content = render_to_string(email_template_name, {
362 538ccdd5 Sofia Papagiannaki
                        'message': form.cleaned_data['feedback_msg'],
363 538ccdd5 Sofia Papagiannaki
                        'data': form.cleaned_data['feedback_data'],
364 890b0eaf Sofia Papagiannaki
                        'request': request})
365 13858d75 Kostas Papadimitriou
366 538ccdd5 Sofia Papagiannaki
            try:
367 538ccdd5 Sofia Papagiannaki
                send_mail(subject, content, from_email, recipient_list)
368 538ccdd5 Sofia Papagiannaki
                message = _('Feedback successfully sent')
369 538ccdd5 Sofia Papagiannaki
                status = messages.SUCCESS
370 538ccdd5 Sofia Papagiannaki
            except (SMTPException, socket.error) as e:
371 538ccdd5 Sofia Papagiannaki
                status = messages.ERROR
372 538ccdd5 Sofia Papagiannaki
                message = getattr(e, 'strerror', '')
373 538ccdd5 Sofia Papagiannaki
            messages.add_message(request, status, message)
374 890b0eaf Sofia Papagiannaki
    return render_response(template_name,
375 890b0eaf Sofia Papagiannaki
                           form = form,
376 6b4f9fb2 Sofia Papagiannaki
                           context_instance = get_context(request, extra_context))
377 15efc749 Sofia Papagiannaki
378 13858d75 Kostas Papadimitriou
def create_user(request, form, backend=None, post_data={}, next = None, template_name='login.html', extra_context={}):
379 15efc749 Sofia Papagiannaki
    try:
380 15efc749 Sofia Papagiannaki
        if not backend:
381 15efc749 Sofia Papagiannaki
            backend = get_backend(request)
382 15efc749 Sofia Papagiannaki
        if form.is_valid():
383 15efc749 Sofia Papagiannaki
            status, message, user = backend.signup(form)
384 15efc749 Sofia Papagiannaki
            if status == messages.SUCCESS:
385 15efc749 Sofia Papagiannaki
                for k,v in post_data.items():
386 15efc749 Sofia Papagiannaki
                    setattr(user,k, v)
387 15efc749 Sofia Papagiannaki
                user.save()
388 15efc749 Sofia Papagiannaki
                if next:
389 15efc749 Sofia Papagiannaki
                    return redirect(next)
390 15efc749 Sofia Papagiannaki
            messages.add_message(request, status, message)
391 15efc749 Sofia Papagiannaki
        else:
392 15efc749 Sofia Papagiannaki
            messages.add_message(request, messages.ERROR, form.errors)
393 15efc749 Sofia Papagiannaki
    except (Invitation.DoesNotExist, ValueError), e:
394 15efc749 Sofia Papagiannaki
        messages.add_message(request, messages.ERROR, e)
395 15efc749 Sofia Papagiannaki
    return render_response(template_name,
396 15efc749 Sofia Papagiannaki
                           form = LocalUserCreationForm(),
397 15efc749 Sofia Papagiannaki
                           context_instance=get_context(request, extra_context))
398 a196eb7e Sofia Papagiannaki
399 a196eb7e Sofia Papagiannaki
def user_logout(request):
400 a196eb7e Sofia Papagiannaki
    response = HttpResponse()
401 a196eb7e Sofia Papagiannaki
    response.delete_cookie(settings.COOKIE_NAME)
402 a196eb7e Sofia Papagiannaki
    response['Location'] = reverse('django.contrib.auth.views.logout')
403 a196eb7e Sofia Papagiannaki
    response.status_code = 302
404 13858d75 Kostas Papadimitriou
    return response