Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (7.6 kB)

1 aba1e498 Antony Chazapis
# Copyright 2011-2012 GRNET S.A. All rights reserved.
2 5ce3ce4f Sofia Papagiannaki
#
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 5ce3ce4f Sofia Papagiannaki
#
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 5ce3ce4f Sofia Papagiannaki
#
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 5ce3ce4f Sofia Papagiannaki
#
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 5ce3ce4f Sofia Papagiannaki
#
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 0905ccd2 Sofia Papagiannaki
40 64cd4730 Antony Chazapis
from datetime import tzinfo, timedelta
41 27e26a41 Sofia Papagiannaki
from django.http import HttpResponse, HttpResponseBadRequest, urlencode
42 0905ccd2 Sofia Papagiannaki
from django.template import RequestContext
43 15efc749 Sofia Papagiannaki
from django.utils.translation import ugettext as _
44 111f3da6 Sofia Papagiannaki
from django.contrib.auth import authenticate
45 63ecdd20 Sofia Papagiannaki
from django.core.urlresolvers import reverse
46 9a06d96f Olga Brani
from django.core.exceptions import ValidationError, ObjectDoesNotExist
47 9a06d96f Olga Brani
from django.db.models.fields import Field
48 ae497612 Olga Brani
from django.utils.translation import ugettext as _
49 ae497612 Olga Brani
50 aab4d540 Sofia Papagiannaki
from astakos.im.models import AstakosUser, Invitation
51 aab4d540 Sofia Papagiannaki
from astakos.im.settings import COOKIE_NAME, \
52 111f3da6 Sofia Papagiannaki
    COOKIE_DOMAIN, COOKIE_SECURE, FORCE_PROFILE_UPDATE, LOGGING_LEVEL
53 111f3da6 Sofia Papagiannaki
from astakos.im.functions import login
54 64cd4730 Antony Chazapis
55 ae497612 Olga Brani
import astakos.im.messages as astakos_messages
56 ae497612 Olga Brani
57 e015e9e6 Sofia Papagiannaki
logger = logging.getLogger(__name__)
58 e015e9e6 Sofia Papagiannaki
59 5ce3ce4f Sofia Papagiannaki
60 64cd4730 Antony Chazapis
class UTC(tzinfo):
61 aab4d540 Sofia Papagiannaki
    def utcoffset(self, dt):
62 aab4d540 Sofia Papagiannaki
        return timedelta(0)
63 5ce3ce4f Sofia Papagiannaki
64 aab4d540 Sofia Papagiannaki
    def tzname(self, dt):
65 aab4d540 Sofia Papagiannaki
        return 'UTC'
66 5ce3ce4f Sofia Papagiannaki
67 aab4d540 Sofia Papagiannaki
    def dst(self, dt):
68 aab4d540 Sofia Papagiannaki
        return timedelta(0)
69 64cd4730 Antony Chazapis
70 5ce3ce4f Sofia Papagiannaki
71 64cd4730 Antony Chazapis
def isoformat(d):
72 aab4d540 Sofia Papagiannaki
    """Return an ISO8601 date string that includes a timezone."""
73 5ce3ce4f Sofia Papagiannaki
74 aab4d540 Sofia Papagiannaki
    return d.replace(tzinfo=UTC()).isoformat()
75 0905ccd2 Sofia Papagiannaki
76 5ce3ce4f Sofia Papagiannaki
77 18ffbee1 Sofia Papagiannaki
def epoch(datetime):
78 5ce3ce4f Sofia Papagiannaki
    return int(time.mktime(datetime.timetuple()) * 1000)
79 5ce3ce4f Sofia Papagiannaki
80 18ffbee1 Sofia Papagiannaki
81 aab4d540 Sofia Papagiannaki
def get_context(request, extra_context=None, **kwargs):
82 aab4d540 Sofia Papagiannaki
    extra_context = extra_context or {}
83 0905ccd2 Sofia Papagiannaki
    extra_context.update(kwargs)
84 0905ccd2 Sofia Papagiannaki
    return RequestContext(request, extra_context)
85 e2125441 Sofia Papagiannaki
86 5ce3ce4f Sofia Papagiannaki
87 15efc749 Sofia Papagiannaki
def get_invitation(request):
88 15efc749 Sofia Papagiannaki
    """
89 15efc749 Sofia Papagiannaki
    Returns the invitation identified by the ``code``.
90 5ce3ce4f Sofia Papagiannaki

91 0a569195 Sofia Papagiannaki
    Raises ValueError if the invitation is consumed or there is another account
92 0a569195 Sofia Papagiannaki
    associated with this email.
93 15efc749 Sofia Papagiannaki
    """
94 15efc749 Sofia Papagiannaki
    code = request.GET.get('code')
95 15efc749 Sofia Papagiannaki
    if request.method == 'POST':
96 15efc749 Sofia Papagiannaki
        code = request.POST.get('code')
97 15efc749 Sofia Papagiannaki
    if not code:
98 15efc749 Sofia Papagiannaki
        return
99 5ce3ce4f Sofia Papagiannaki
    invitation = Invitation.objects.get(code=code)
100 15efc749 Sofia Papagiannaki
    if invitation.is_consumed:
101 ae497612 Olga Brani
        raise ValueError(_(astakos_messages.INVITATION_CONSUMED_ERR))
102 0a569195 Sofia Papagiannaki
    if reserved_email(invitation.username):
103 ae497612 Olga Brani
        email = invitation.username
104 d1a767f7 Olga Brani
        raise ValueError(_(astakos_messages.EMAIL_RESRVED) % locals())
105 63ecdd20 Sofia Papagiannaki
    return invitation
106 63ecdd20 Sofia Papagiannaki
107 5ce3ce4f Sofia Papagiannaki
108 8fbf5367 root
def prepare_response(request, user, next='', renew=False):
109 63ecdd20 Sofia Papagiannaki
    """Return the unique username and the token
110 63ecdd20 Sofia Papagiannaki
       as 'X-Auth-User' and 'X-Auth-Token' headers,
111 63ecdd20 Sofia Papagiannaki
       or redirect to the URL provided in 'next'
112 63ecdd20 Sofia Papagiannaki
       with the 'user' and 'token' as parameters.
113 5ce3ce4f Sofia Papagiannaki

114 63ecdd20 Sofia Papagiannaki
       Reissue the token even if it has not yet
115 63ecdd20 Sofia Papagiannaki
       expired, if the 'renew' parameter is present
116 63ecdd20 Sofia Papagiannaki
       or user has not a valid token.
117 63ecdd20 Sofia Papagiannaki
    """
118 63ecdd20 Sofia Papagiannaki
    renew = renew or (not user.auth_token)
119 f627a979 Sofia Papagiannaki
    renew = renew or (user.auth_token_expires < datetime.datetime.now())
120 63ecdd20 Sofia Papagiannaki
    if renew:
121 63ecdd20 Sofia Papagiannaki
        user.renew_token()
122 27e26a41 Sofia Papagiannaki
        try:
123 27e26a41 Sofia Papagiannaki
            user.save()
124 27e26a41 Sofia Papagiannaki
        except ValidationError, e:
125 5ce3ce4f Sofia Papagiannaki
            return HttpResponseBadRequest(e)
126 5ce3ce4f Sofia Papagiannaki
127 92defad4 Sofia Papagiannaki
    if FORCE_PROFILE_UPDATE and not user.is_verified and not user.is_superuser:
128 63ecdd20 Sofia Papagiannaki
        params = ''
129 63ecdd20 Sofia Papagiannaki
        if next:
130 63ecdd20 Sofia Papagiannaki
            params = '?' + urlencode({'next': next})
131 6ff7a7ca Sofia Papagiannaki
        next = reverse('edit_profile') + params
132 5ce3ce4f Sofia Papagiannaki
133 63ecdd20 Sofia Papagiannaki
    response = HttpResponse()
134 5ce3ce4f Sofia Papagiannaki
135 8fbf5367 root
    # authenticate before login
136 8fbf5367 root
    user = authenticate(email=user.email, auth_token=user.auth_token)
137 8fbf5367 root
    login(request, user)
138 c301698f Sofia Papagiannaki
    set_cookie(response, user)
139 b42b0987 Sofia Papagiannaki
    request.session.set_expiry(user.auth_token_expires)
140 5ce3ce4f Sofia Papagiannaki
141 63ecdd20 Sofia Papagiannaki
    if not next:
142 6ff7a7ca Sofia Papagiannaki
        next = reverse('index')
143 5ce3ce4f Sofia Papagiannaki
144 63ecdd20 Sofia Papagiannaki
    response['Location'] = next
145 63ecdd20 Sofia Papagiannaki
    response.status_code = 302
146 8fbf5367 root
    return response
147 c301698f Sofia Papagiannaki
148 5ce3ce4f Sofia Papagiannaki
149 c301698f Sofia Papagiannaki
def set_cookie(response, user):
150 c301698f Sofia Papagiannaki
    expire_fmt = user.auth_token_expires.strftime('%a, %d-%b-%Y %H:%M:%S %Z')
151 c301698f Sofia Papagiannaki
    cookie_value = quote(user.email + '|' + user.auth_token)
152 c301698f Sofia Papagiannaki
    response.set_cookie(COOKIE_NAME, value=cookie_value,
153 5ce3ce4f Sofia Papagiannaki
                        expires=expire_fmt, path='/',
154 9a06d96f Olga Brani
                        domain=COOKIE_DOMAIN, secure=COOKIE_SECURE)
155 f627a979 Sofia Papagiannaki
    msg = 'Cookie [expiring %s] set for %s' % (
156 f627a979 Sofia Papagiannaki
        user.auth_token_expires,
157 f627a979 Sofia Papagiannaki
        user.email
158 f627a979 Sofia Papagiannaki
    )
159 aab4d540 Sofia Papagiannaki
    logger.log(LOGGING_LEVEL, msg)
160 270dd48d Sofia Papagiannaki
161 5ce3ce4f Sofia Papagiannaki
162 270dd48d Sofia Papagiannaki
class lazy_string(object):
163 270dd48d Sofia Papagiannaki
    def __init__(self, function, *args, **kwargs):
164 5ce3ce4f Sofia Papagiannaki
        self.function = function
165 5ce3ce4f Sofia Papagiannaki
        self.args = args
166 5ce3ce4f Sofia Papagiannaki
        self.kwargs = kwargs
167 5ce3ce4f Sofia Papagiannaki
168 270dd48d Sofia Papagiannaki
    def __str__(self):
169 270dd48d Sofia Papagiannaki
        if not hasattr(self, 'str'):
170 5ce3ce4f Sofia Papagiannaki
            self.str = self.function(*self.args, **self.kwargs)
171 270dd48d Sofia Papagiannaki
        return self.str
172 270dd48d Sofia Papagiannaki
173 5ce3ce4f Sofia Papagiannaki
174 270dd48d Sofia Papagiannaki
def reverse_lazy(*args, **kwargs):
175 270dd48d Sofia Papagiannaki
    return lazy_string(reverse, *args, **kwargs)
176 270dd48d Sofia Papagiannaki
177 5ce3ce4f Sofia Papagiannaki
178 0a569195 Sofia Papagiannaki
def reserved_email(email):
179 9a06d96f Olga Brani
    return AstakosUser.objects.filter(email__iexact=email).count() != 0
180 5ce3ce4f Sofia Papagiannaki
181 0a569195 Sofia Papagiannaki
182 0a569195 Sofia Papagiannaki
def get_query(request):
183 f627a979 Sofia Papagiannaki
    try:
184 f627a979 Sofia Papagiannaki
        return request.__getattribute__(request.method)
185 f627a979 Sofia Papagiannaki
    except AttributeError:
186 9a06d96f Olga Brani
        return {}
187 9a06d96f Olga Brani
188 9a06d96f Olga Brani
189 9a06d96f Olga Brani
def model_to_dict(obj, exclude=['AutoField', 'ForeignKey', 'OneToOneField'],
190 9a06d96f Olga Brani
                  include_empty=True):
191 9a06d96f Olga Brani
    '''
192 9a06d96f Olga Brani
        serialize model object to dict with related objects
193 9a06d96f Olga Brani

194 9a06d96f Olga Brani
        author: Vadym Zakovinko <vp@zakovinko.com>
195 9a06d96f Olga Brani
        date: January 31, 2011
196 9a06d96f Olga Brani
        http://djangosnippets.org/snippets/2342/
197 9a06d96f Olga Brani
    '''
198 9a06d96f Olga Brani
    tree = {}
199 9a06d96f Olga Brani
    for field_name in obj._meta.get_all_field_names():
200 9a06d96f Olga Brani
        try:
201 9a06d96f Olga Brani
            field = getattr(obj, field_name)
202 9a06d96f Olga Brani
        except (ObjectDoesNotExist, AttributeError):
203 9a06d96f Olga Brani
            continue
204 9a06d96f Olga Brani
205 9a06d96f Olga Brani
        if field.__class__.__name__ in ['RelatedManager', 'ManyRelatedManager']:
206 9a06d96f Olga Brani
            if field.model.__name__ in exclude:
207 9a06d96f Olga Brani
                continue
208 9a06d96f Olga Brani
209 9a06d96f Olga Brani
            if field.__class__.__name__ == 'ManyRelatedManager':
210 9a06d96f Olga Brani
                exclude.append(obj.__class__.__name__)
211 9a06d96f Olga Brani
            subtree = []
212 9a06d96f Olga Brani
            for related_obj in getattr(obj, field_name).all():
213 9a06d96f Olga Brani
                value = model_to_dict(related_obj, exclude=exclude)
214 9a06d96f Olga Brani
                if value or include_empty:
215 9a06d96f Olga Brani
                    subtree.append(value)
216 9a06d96f Olga Brani
            if subtree or include_empty:
217 9a06d96f Olga Brani
                tree[field_name] = subtree
218 9a06d96f Olga Brani
            continue
219 9a06d96f Olga Brani
220 9a06d96f Olga Brani
        field = obj._meta.get_field_by_name(field_name)[0]
221 9a06d96f Olga Brani
        if field.__class__.__name__ in exclude:
222 9a06d96f Olga Brani
            continue
223 9a06d96f Olga Brani
224 9a06d96f Olga Brani
        if field.__class__.__name__ == 'RelatedObject':
225 9a06d96f Olga Brani
            exclude.append(field.model.__name__)
226 9a06d96f Olga Brani
            tree[field_name] = model_to_dict(getattr(obj, field_name),
227 9a06d96f Olga Brani
                                             exclude=exclude)
228 9a06d96f Olga Brani
            continue
229 9a06d96f Olga Brani
230 9a06d96f Olga Brani
        value = getattr(obj, field_name)
231 9a06d96f Olga Brani
        if field.__class__.__name__ == 'ForeignKey':
232 9a06d96f Olga Brani
            value = unicode(value) if value is not None else value
233 9a06d96f Olga Brani
        if value or include_empty:
234 9a06d96f Olga Brani
            tree[field_name] = value
235 9a06d96f Olga Brani
236 9a06d96f Olga Brani
    return tree