Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / util.py @ 68ed1683

History | View | Annotate | Download (5.6 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 18ffbee1 Sofia Papagiannaki
import time
37 63ecdd20 Sofia Papagiannaki
38 63ecdd20 Sofia Papagiannaki
from urllib import quote
39 63ecdd20 Sofia Papagiannaki
from urlparse import urlsplit, urlunsplit
40 63ecdd20 Sofia Papagiannaki
from functools import wraps
41 0905ccd2 Sofia Papagiannaki
42 64cd4730 Antony Chazapis
from datetime import tzinfo, timedelta
43 27e26a41 Sofia Papagiannaki
from django.http import HttpResponse, HttpResponseBadRequest, urlencode
44 0905ccd2 Sofia Papagiannaki
from django.template import RequestContext
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 27e26a41 Sofia Papagiannaki
from django.core.exceptions import ValidationError
49 64cd4730 Antony Chazapis
50 270dd48d Sofia Papagiannaki
from astakos.im.models import AstakosUser, Invitation, ApprovalTerms
51 ca34523e Antony Chazapis
from astakos.im.settings import INVITATIONS_PER_LEVEL, COOKIE_NAME, COOKIE_DOMAIN, COOKIE_SECURE, FORCE_PROFILE_UPDATE
52 64cd4730 Antony Chazapis
53 e015e9e6 Sofia Papagiannaki
logger = logging.getLogger(__name__)
54 e015e9e6 Sofia Papagiannaki
55 64cd4730 Antony Chazapis
class UTC(tzinfo):
56 64cd4730 Antony Chazapis
   def utcoffset(self, dt):
57 64cd4730 Antony Chazapis
       return timedelta(0)
58 64cd4730 Antony Chazapis
59 64cd4730 Antony Chazapis
   def tzname(self, dt):
60 64cd4730 Antony Chazapis
       return 'UTC'
61 64cd4730 Antony Chazapis
62 64cd4730 Antony Chazapis
   def dst(self, dt):
63 64cd4730 Antony Chazapis
       return timedelta(0)
64 64cd4730 Antony Chazapis
65 64cd4730 Antony Chazapis
def isoformat(d):
66 64cd4730 Antony Chazapis
   """Return an ISO8601 date string that includes a timezone."""
67 64cd4730 Antony Chazapis
68 64cd4730 Antony Chazapis
   return d.replace(tzinfo=UTC()).isoformat()
69 0905ccd2 Sofia Papagiannaki
70 18ffbee1 Sofia Papagiannaki
def epoch(datetime):
71 18ffbee1 Sofia Papagiannaki
    return int(time.mktime(datetime.timetuple())*1000)
72 18ffbee1 Sofia Papagiannaki
73 0905ccd2 Sofia Papagiannaki
def get_context(request, extra_context={}, **kwargs):
74 0905ccd2 Sofia Papagiannaki
    if not extra_context:
75 0905ccd2 Sofia Papagiannaki
        extra_context = {}
76 0905ccd2 Sofia Papagiannaki
    extra_context.update(kwargs)
77 0905ccd2 Sofia Papagiannaki
    return RequestContext(request, extra_context)
78 e2125441 Sofia Papagiannaki
79 15efc749 Sofia Papagiannaki
def get_invitation(request):
80 15efc749 Sofia Papagiannaki
    """
81 15efc749 Sofia Papagiannaki
    Returns the invitation identified by the ``code``.
82 15efc749 Sofia Papagiannaki
    
83 0a569195 Sofia Papagiannaki
    Raises ValueError if the invitation is consumed or there is another account
84 0a569195 Sofia Papagiannaki
    associated with this email.
85 15efc749 Sofia Papagiannaki
    """
86 15efc749 Sofia Papagiannaki
    code = request.GET.get('code')
87 15efc749 Sofia Papagiannaki
    if request.method == 'POST':
88 15efc749 Sofia Papagiannaki
        code = request.POST.get('code')
89 15efc749 Sofia Papagiannaki
    if not code:
90 15efc749 Sofia Papagiannaki
        return
91 15efc749 Sofia Papagiannaki
    invitation = Invitation.objects.get(code = code)
92 15efc749 Sofia Papagiannaki
    if invitation.is_consumed:
93 1fefe48c Sofia Papagiannaki
        raise ValueError(_('Invitation is used'))
94 0a569195 Sofia Papagiannaki
    if reserved_email(invitation.username):
95 15efc749 Sofia Papagiannaki
        raise ValueError(_('Email: %s is reserved' % invitation.username))
96 63ecdd20 Sofia Papagiannaki
    return invitation
97 63ecdd20 Sofia Papagiannaki
98 8fbf5367 root
def prepare_response(request, user, next='', renew=False):
99 63ecdd20 Sofia Papagiannaki
    """Return the unique username and the token
100 63ecdd20 Sofia Papagiannaki
       as 'X-Auth-User' and 'X-Auth-Token' headers,
101 63ecdd20 Sofia Papagiannaki
       or redirect to the URL provided in 'next'
102 63ecdd20 Sofia Papagiannaki
       with the 'user' and 'token' as parameters.
103 63ecdd20 Sofia Papagiannaki
       
104 63ecdd20 Sofia Papagiannaki
       Reissue the token even if it has not yet
105 63ecdd20 Sofia Papagiannaki
       expired, if the 'renew' parameter is present
106 63ecdd20 Sofia Papagiannaki
       or user has not a valid token.
107 63ecdd20 Sofia Papagiannaki
    """
108 63ecdd20 Sofia Papagiannaki
    renew = renew or (not user.auth_token)
109 63ecdd20 Sofia Papagiannaki
    renew = renew or (user.auth_token_expires and user.auth_token_expires < datetime.datetime.now())
110 63ecdd20 Sofia Papagiannaki
    if renew:
111 63ecdd20 Sofia Papagiannaki
        user.renew_token()
112 27e26a41 Sofia Papagiannaki
        try:
113 27e26a41 Sofia Papagiannaki
            user.save()
114 27e26a41 Sofia Papagiannaki
        except ValidationError, e:
115 27e26a41 Sofia Papagiannaki
            return HttpResponseBadRequest(e) 
116 63ecdd20 Sofia Papagiannaki
    
117 92defad4 Sofia Papagiannaki
    if FORCE_PROFILE_UPDATE and not user.is_verified and not user.is_superuser:
118 63ecdd20 Sofia Papagiannaki
        params = ''
119 63ecdd20 Sofia Papagiannaki
        if next:
120 63ecdd20 Sofia Papagiannaki
            params = '?' + urlencode({'next': next})
121 63ecdd20 Sofia Papagiannaki
        next = reverse('astakos.im.views.edit_profile') + params
122 63ecdd20 Sofia Papagiannaki
    
123 63ecdd20 Sofia Papagiannaki
    response = HttpResponse()
124 63ecdd20 Sofia Papagiannaki
    
125 8fbf5367 root
    # authenticate before login
126 8fbf5367 root
    user = authenticate(email=user.email, auth_token=user.auth_token)
127 8fbf5367 root
    login(request, user)
128 c301698f Sofia Papagiannaki
    set_cookie(response, user)
129 b42b0987 Sofia Papagiannaki
    request.session.set_expiry(user.auth_token_expires)
130 63ecdd20 Sofia Papagiannaki
    
131 63ecdd20 Sofia Papagiannaki
    if not next:
132 63ecdd20 Sofia Papagiannaki
        next = reverse('astakos.im.views.index')
133 63ecdd20 Sofia Papagiannaki
    
134 63ecdd20 Sofia Papagiannaki
    response['Location'] = next
135 63ecdd20 Sofia Papagiannaki
    response.status_code = 302
136 8fbf5367 root
    return response
137 c301698f Sofia Papagiannaki
138 c301698f Sofia Papagiannaki
def set_cookie(response, user):
139 c301698f Sofia Papagiannaki
    expire_fmt = user.auth_token_expires.strftime('%a, %d-%b-%Y %H:%M:%S %Z')
140 c301698f Sofia Papagiannaki
    cookie_value = quote(user.email + '|' + user.auth_token)
141 c301698f Sofia Papagiannaki
    response.set_cookie(COOKIE_NAME, value=cookie_value,
142 c301698f Sofia Papagiannaki
                        expires=expire_fmt, path='/',
143 ca34523e Antony Chazapis
                        domain=COOKIE_DOMAIN, secure=COOKIE_SECURE)
144 270dd48d Sofia Papagiannaki
145 270dd48d Sofia Papagiannaki
class lazy_string(object):
146 270dd48d Sofia Papagiannaki
    def __init__(self, function, *args, **kwargs):
147 270dd48d Sofia Papagiannaki
        self.function=function
148 270dd48d Sofia Papagiannaki
        self.args=args
149 270dd48d Sofia Papagiannaki
        self.kwargs=kwargs
150 270dd48d Sofia Papagiannaki
        
151 270dd48d Sofia Papagiannaki
    def __str__(self):
152 270dd48d Sofia Papagiannaki
        if not hasattr(self, 'str'):
153 270dd48d Sofia Papagiannaki
            self.str=self.function(*self.args, **self.kwargs)
154 270dd48d Sofia Papagiannaki
        return self.str
155 270dd48d Sofia Papagiannaki
156 270dd48d Sofia Papagiannaki
def reverse_lazy(*args, **kwargs):
157 270dd48d Sofia Papagiannaki
    return lazy_string(reverse, *args, **kwargs)
158 270dd48d Sofia Papagiannaki
159 0a569195 Sofia Papagiannaki
def reserved_email(email):
160 0a569195 Sofia Papagiannaki
    return AstakosUser.objects.filter(email = email).count() != 0
161 0a569195 Sofia Papagiannaki
162 0a569195 Sofia Papagiannaki
def get_query(request):
163 0a569195 Sofia Papagiannaki
    return request.__getattribute__(request.method)