Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / util.py @ f289215d

History | View | Annotate | Download (5.7 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 0905ccd2 Sofia Papagiannaki
import logging
35 63ecdd20 Sofia Papagiannaki
import datetime
36 63ecdd20 Sofia Papagiannaki
37 63ecdd20 Sofia Papagiannaki
from urllib import quote
38 63ecdd20 Sofia Papagiannaki
from urlparse import urlsplit, urlunsplit
39 63ecdd20 Sofia Papagiannaki
from functools import wraps
40 0905ccd2 Sofia Papagiannaki
41 64cd4730 Antony Chazapis
from datetime import tzinfo, timedelta
42 63ecdd20 Sofia Papagiannaki
from django.http import HttpResponse, urlencode
43 0905ccd2 Sofia Papagiannaki
from django.template import RequestContext
44 e2125441 Sofia Papagiannaki
from django.contrib.sites.models import Site
45 15efc749 Sofia Papagiannaki
from django.utils.translation import ugettext as _
46 63ecdd20 Sofia Papagiannaki
from django.contrib.auth import login, authenticate
47 63ecdd20 Sofia Papagiannaki
from django.core.urlresolvers import reverse
48 64cd4730 Antony Chazapis
49 15efc749 Sofia Papagiannaki
from astakos.im.models import AstakosUser, Invitation
50 ca34523e Antony Chazapis
from astakos.im.settings import INVITATIONS_PER_LEVEL, COOKIE_NAME, COOKIE_DOMAIN, COOKIE_SECURE, FORCE_PROFILE_UPDATE
51 64cd4730 Antony Chazapis
52 e015e9e6 Sofia Papagiannaki
logger = logging.getLogger(__name__)
53 e015e9e6 Sofia Papagiannaki
54 64cd4730 Antony Chazapis
class UTC(tzinfo):
55 64cd4730 Antony Chazapis
   def utcoffset(self, dt):
56 64cd4730 Antony Chazapis
       return timedelta(0)
57 64cd4730 Antony Chazapis
58 64cd4730 Antony Chazapis
   def tzname(self, dt):
59 64cd4730 Antony Chazapis
       return 'UTC'
60 64cd4730 Antony Chazapis
61 64cd4730 Antony Chazapis
   def dst(self, dt):
62 64cd4730 Antony Chazapis
       return timedelta(0)
63 64cd4730 Antony Chazapis
64 64cd4730 Antony Chazapis
def isoformat(d):
65 64cd4730 Antony Chazapis
   """Return an ISO8601 date string that includes a timezone."""
66 64cd4730 Antony Chazapis
67 64cd4730 Antony Chazapis
   return d.replace(tzinfo=UTC()).isoformat()
68 0905ccd2 Sofia Papagiannaki
69 b90b602c Sofia Papagiannaki
def get_or_create_user(email, realname='', first_name='', last_name='', affiliation='', level=0, provider='local', password=''):
70 0905ccd2 Sofia Papagiannaki
    """Find or register a user into the internal database
71 0905ccd2 Sofia Papagiannaki
       and issue a token for subsequent requests.
72 0905ccd2 Sofia Papagiannaki
    """
73 b90b602c Sofia Papagiannaki
    user, created = AstakosUser.objects.get_or_create(email=email,
74 0905ccd2 Sofia Papagiannaki
        defaults={
75 0905ccd2 Sofia Papagiannaki
            'password':password,
76 0905ccd2 Sofia Papagiannaki
            'affiliation':affiliation,
77 0905ccd2 Sofia Papagiannaki
            'level':level,
78 92defad4 Sofia Papagiannaki
            'invitations':INVITATIONS_PER_LEVEL[level],
79 0905ccd2 Sofia Papagiannaki
            'provider':provider,
80 0905ccd2 Sofia Papagiannaki
            'realname':realname,
81 0905ccd2 Sofia Papagiannaki
            'first_name':first_name,
82 0905ccd2 Sofia Papagiannaki
            'last_name':last_name
83 0905ccd2 Sofia Papagiannaki
        })
84 0905ccd2 Sofia Papagiannaki
    if created:
85 0905ccd2 Sofia Papagiannaki
        user.renew_token()
86 0905ccd2 Sofia Papagiannaki
        user.save()
87 e015e9e6 Sofia Papagiannaki
        logger.info('Created user %s', user)
88 0905ccd2 Sofia Papagiannaki
    
89 0905ccd2 Sofia Papagiannaki
    return user
90 0905ccd2 Sofia Papagiannaki
91 0905ccd2 Sofia Papagiannaki
def get_context(request, extra_context={}, **kwargs):
92 0905ccd2 Sofia Papagiannaki
    if not extra_context:
93 0905ccd2 Sofia Papagiannaki
        extra_context = {}
94 0905ccd2 Sofia Papagiannaki
    extra_context.update(kwargs)
95 0905ccd2 Sofia Papagiannaki
    return RequestContext(request, extra_context)
96 e2125441 Sofia Papagiannaki
97 15efc749 Sofia Papagiannaki
def get_invitation(request):
98 15efc749 Sofia Papagiannaki
    """
99 15efc749 Sofia Papagiannaki
    Returns the invitation identified by the ``code``.
100 15efc749 Sofia Papagiannaki
    
101 15efc749 Sofia Papagiannaki
    Raises Invitation.DoesNotExist and Exception if the invitation is consumed
102 15efc749 Sofia Papagiannaki
    """
103 15efc749 Sofia Papagiannaki
    code = request.GET.get('code')
104 15efc749 Sofia Papagiannaki
    if request.method == 'POST':
105 15efc749 Sofia Papagiannaki
        code = request.POST.get('code')
106 15efc749 Sofia Papagiannaki
    if not code:
107 15efc749 Sofia Papagiannaki
        if 'invitation_code' in request.session:
108 15efc749 Sofia Papagiannaki
            code = request.session.pop('invitation_code')
109 15efc749 Sofia Papagiannaki
    if not code:
110 15efc749 Sofia Papagiannaki
        return
111 15efc749 Sofia Papagiannaki
    invitation = Invitation.objects.get(code = code)
112 15efc749 Sofia Papagiannaki
    if invitation.is_consumed:
113 1fefe48c Sofia Papagiannaki
        raise ValueError(_('Invitation is used'))
114 15efc749 Sofia Papagiannaki
    try:
115 15efc749 Sofia Papagiannaki
        AstakosUser.objects.get(email = invitation.username)
116 15efc749 Sofia Papagiannaki
        raise ValueError(_('Email: %s is reserved' % invitation.username))
117 15efc749 Sofia Papagiannaki
    except AstakosUser.DoesNotExist:
118 15efc749 Sofia Papagiannaki
        pass
119 63ecdd20 Sofia Papagiannaki
    return invitation
120 63ecdd20 Sofia Papagiannaki
121 8fbf5367 root
def prepare_response(request, user, next='', renew=False):
122 63ecdd20 Sofia Papagiannaki
    """Return the unique username and the token
123 63ecdd20 Sofia Papagiannaki
       as 'X-Auth-User' and 'X-Auth-Token' headers,
124 63ecdd20 Sofia Papagiannaki
       or redirect to the URL provided in 'next'
125 63ecdd20 Sofia Papagiannaki
       with the 'user' and 'token' as parameters.
126 63ecdd20 Sofia Papagiannaki
       
127 63ecdd20 Sofia Papagiannaki
       Reissue the token even if it has not yet
128 63ecdd20 Sofia Papagiannaki
       expired, if the 'renew' parameter is present
129 63ecdd20 Sofia Papagiannaki
       or user has not a valid token.
130 63ecdd20 Sofia Papagiannaki
    """
131 63ecdd20 Sofia Papagiannaki
    
132 63ecdd20 Sofia Papagiannaki
    renew = renew or (not user.auth_token)
133 63ecdd20 Sofia Papagiannaki
    renew = renew or (user.auth_token_expires and user.auth_token_expires < datetime.datetime.now())
134 63ecdd20 Sofia Papagiannaki
    if renew:
135 63ecdd20 Sofia Papagiannaki
        user.renew_token()
136 63ecdd20 Sofia Papagiannaki
        user.save()
137 63ecdd20 Sofia Papagiannaki
    
138 92defad4 Sofia Papagiannaki
    if FORCE_PROFILE_UPDATE and not user.is_verified and not user.is_superuser:
139 63ecdd20 Sofia Papagiannaki
        params = ''
140 63ecdd20 Sofia Papagiannaki
        if next:
141 63ecdd20 Sofia Papagiannaki
            params = '?' + urlencode({'next': next})
142 63ecdd20 Sofia Papagiannaki
        next = reverse('astakos.im.views.edit_profile') + params
143 63ecdd20 Sofia Papagiannaki
    
144 63ecdd20 Sofia Papagiannaki
    response = HttpResponse()
145 63ecdd20 Sofia Papagiannaki
    
146 8fbf5367 root
    # authenticate before login
147 8fbf5367 root
    user = authenticate(email=user.email, auth_token=user.auth_token)
148 8fbf5367 root
    login(request, user)
149 c301698f Sofia Papagiannaki
    set_cookie(response, user)
150 63ecdd20 Sofia Papagiannaki
    
151 63ecdd20 Sofia Papagiannaki
    if not next:
152 63ecdd20 Sofia Papagiannaki
        next = reverse('astakos.im.views.index')
153 63ecdd20 Sofia Papagiannaki
    
154 63ecdd20 Sofia Papagiannaki
    response['Location'] = next
155 63ecdd20 Sofia Papagiannaki
    response.status_code = 302
156 8fbf5367 root
    return response
157 c301698f Sofia Papagiannaki
158 c301698f Sofia Papagiannaki
def set_cookie(response, user):
159 c301698f Sofia Papagiannaki
    expire_fmt = user.auth_token_expires.strftime('%a, %d-%b-%Y %H:%M:%S %Z')
160 c301698f Sofia Papagiannaki
    cookie_value = quote(user.email + '|' + user.auth_token)
161 c301698f Sofia Papagiannaki
    response.set_cookie(COOKIE_NAME, value=cookie_value,
162 c301698f Sofia Papagiannaki
                        expires=expire_fmt, path='/',
163 ca34523e Antony Chazapis
                        domain=COOKIE_DOMAIN, secure=COOKIE_SECURE)