Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / views / decorators.py @ fb9ba8d5

History | View | Annotate | Download (5.3 kB)

1 70e11eaa Sofia Papagiannaki
# Copyright 2011-2012 GRNET S.A. All rights reserved.
2 70e11eaa Sofia Papagiannaki
#
3 70e11eaa Sofia Papagiannaki
# Redistribution and use in source and binary forms, with or
4 70e11eaa Sofia Papagiannaki
# without modification, are permitted provided that the following
5 70e11eaa Sofia Papagiannaki
# conditions are met:
6 70e11eaa Sofia Papagiannaki
#
7 70e11eaa Sofia Papagiannaki
#   1. Redistributions of source code must retain the above
8 70e11eaa Sofia Papagiannaki
#      copyright notice, this list of conditions and the following
9 70e11eaa Sofia Papagiannaki
#      disclaimer.
10 70e11eaa Sofia Papagiannaki
#
11 70e11eaa Sofia Papagiannaki
#   2. Redistributions in binary form must reproduce the above
12 70e11eaa Sofia Papagiannaki
#      copyright notice, this list of conditions and the following
13 70e11eaa Sofia Papagiannaki
#      disclaimer in the documentation and/or other materials
14 70e11eaa Sofia Papagiannaki
#      provided with the distribution.
15 70e11eaa Sofia Papagiannaki
#
16 70e11eaa Sofia Papagiannaki
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 70e11eaa Sofia Papagiannaki
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 70e11eaa Sofia Papagiannaki
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 70e11eaa Sofia Papagiannaki
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 70e11eaa Sofia Papagiannaki
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 70e11eaa Sofia Papagiannaki
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 70e11eaa Sofia Papagiannaki
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 70e11eaa Sofia Papagiannaki
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 70e11eaa Sofia Papagiannaki
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 70e11eaa Sofia Papagiannaki
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 70e11eaa Sofia Papagiannaki
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 70e11eaa Sofia Papagiannaki
# POSSIBILITY OF SUCH DAMAGE.
28 70e11eaa Sofia Papagiannaki
#
29 70e11eaa Sofia Papagiannaki
# The views and conclusions contained in the software and
30 70e11eaa Sofia Papagiannaki
# documentation are those of the authors and should not be
31 70e11eaa Sofia Papagiannaki
# interpreted as representing official policies, either expressed
32 70e11eaa Sofia Papagiannaki
# or implied, of GRNET S.A.
33 70e11eaa Sofia Papagiannaki
34 70e11eaa Sofia Papagiannaki
from functools import wraps
35 70e11eaa Sofia Papagiannaki
36 70e11eaa Sofia Papagiannaki
from django.contrib import messages
37 70e11eaa Sofia Papagiannaki
from django.contrib.auth.decorators import login_required
38 70e11eaa Sofia Papagiannaki
from django.core.exceptions import PermissionDenied
39 70e11eaa Sofia Papagiannaki
from django.core.urlresolvers import reverse
40 70e11eaa Sofia Papagiannaki
from django.http import HttpResponse, HttpResponseRedirect
41 70e11eaa Sofia Papagiannaki
from django.utils.http import urlencode
42 70e11eaa Sofia Papagiannaki
43 70e11eaa Sofia Papagiannaki
from astakos.im import auth_providers as auth
44 70e11eaa Sofia Papagiannaki
from astakos.im.cookie import CookieHandler
45 70e11eaa Sofia Papagiannaki
46 70e11eaa Sofia Papagiannaki
47 70e11eaa Sofia Papagiannaki
def cookie_fix(func):
48 70e11eaa Sofia Papagiannaki
    """
49 70e11eaa Sofia Papagiannaki
    Decorator checks whether the request.user conforms
50 70e11eaa Sofia Papagiannaki
    with the astakos cookie and if not it fixes it.
51 70e11eaa Sofia Papagiannaki
    """
52 70e11eaa Sofia Papagiannaki
    @wraps(func)
53 70e11eaa Sofia Papagiannaki
    def wrapper(request, *args, **kwargs):
54 70e11eaa Sofia Papagiannaki
        cookie = CookieHandler(request)
55 70e11eaa Sofia Papagiannaki
        if not cookie.is_valid:
56 70e11eaa Sofia Papagiannaki
            # redirect to request path to set/delete the cookie
57 70e11eaa Sofia Papagiannaki
            response = HttpResponse(status=302)
58 70e11eaa Sofia Papagiannaki
            response['Location'] = request.get_full_path()
59 70e11eaa Sofia Papagiannaki
            cookie.fix(response)
60 70e11eaa Sofia Papagiannaki
            return response
61 70e11eaa Sofia Papagiannaki
62 70e11eaa Sofia Papagiannaki
        response = func(request, *args, **kwargs)
63 70e11eaa Sofia Papagiannaki
64 70e11eaa Sofia Papagiannaki
        # if the user authentication status has changed during the processing
65 70e11eaa Sofia Papagiannaki
        # set/delete the cookie appropriately
66 70e11eaa Sofia Papagiannaki
        if not cookie.is_valid:
67 70e11eaa Sofia Papagiannaki
            cookie.fix(response)
68 70e11eaa Sofia Papagiannaki
        return response
69 70e11eaa Sofia Papagiannaki
    return wrapper
70 70e11eaa Sofia Papagiannaki
71 70e11eaa Sofia Papagiannaki
72 70e11eaa Sofia Papagiannaki
def requires_auth_provider(provider_id, **perms):
73 70e11eaa Sofia Papagiannaki
    """
74 70e11eaa Sofia Papagiannaki
    """
75 70e11eaa Sofia Papagiannaki
    def decorator(func, *args, **kwargs):
76 70e11eaa Sofia Papagiannaki
        @wraps(func)
77 70e11eaa Sofia Papagiannaki
        def wrapper(request, *args, **kwargs):
78 70e11eaa Sofia Papagiannaki
            provider = auth.get_provider(provider_id)
79 70e11eaa Sofia Papagiannaki
80 70e11eaa Sofia Papagiannaki
            if not provider or not provider.is_active():
81 70e11eaa Sofia Papagiannaki
                raise PermissionDenied
82 70e11eaa Sofia Papagiannaki
83 70e11eaa Sofia Papagiannaki
            for pkey, value in perms.iteritems():
84 70e11eaa Sofia Papagiannaki
                attr = 'get_%s_policy' % pkey.lower()
85 70e11eaa Sofia Papagiannaki
                if getattr(provider, attr) != value:
86 70e11eaa Sofia Papagiannaki
                    #TODO: add session message
87 70e11eaa Sofia Papagiannaki
                    return HttpResponseRedirect(reverse('login'))
88 70e11eaa Sofia Papagiannaki
            return func(request, *args)
89 70e11eaa Sofia Papagiannaki
        return wrapper
90 70e11eaa Sofia Papagiannaki
    return decorator
91 70e11eaa Sofia Papagiannaki
92 70e11eaa Sofia Papagiannaki
93 70e11eaa Sofia Papagiannaki
def requires_anonymous(func):
94 70e11eaa Sofia Papagiannaki
    """
95 70e11eaa Sofia Papagiannaki
    Decorator checkes whether the request.user is not Anonymous and
96 70e11eaa Sofia Papagiannaki
    in that case redirects to `logout`.
97 70e11eaa Sofia Papagiannaki
    """
98 70e11eaa Sofia Papagiannaki
    @wraps(func)
99 70e11eaa Sofia Papagiannaki
    def wrapper(request, *args):
100 70e11eaa Sofia Papagiannaki
        if not request.user.is_anonymous():
101 70e11eaa Sofia Papagiannaki
            next = urlencode({'next': request.build_absolute_uri()})
102 70e11eaa Sofia Papagiannaki
            logout_uri = reverse('astakos.im.views.logout') + '?' + next
103 70e11eaa Sofia Papagiannaki
            return HttpResponseRedirect(logout_uri)
104 70e11eaa Sofia Papagiannaki
        return func(request, *args)
105 70e11eaa Sofia Papagiannaki
    return wrapper
106 70e11eaa Sofia Papagiannaki
107 70e11eaa Sofia Papagiannaki
108 70e11eaa Sofia Papagiannaki
def signed_terms_required(func):
109 70e11eaa Sofia Papagiannaki
    """
110 70e11eaa Sofia Papagiannaki
    Decorator checks whether the request.user is Anonymous and in that case
111 70e11eaa Sofia Papagiannaki
    redirects to `logout`.
112 70e11eaa Sofia Papagiannaki
    """
113 70e11eaa Sofia Papagiannaki
    @wraps(func)
114 70e11eaa Sofia Papagiannaki
    def wrapper(request, *args, **kwargs):
115 70e11eaa Sofia Papagiannaki
        if request.user.is_authenticated() and not request.user.signed_terms:
116 70e11eaa Sofia Papagiannaki
            params = urlencode({'next': request.build_absolute_uri(),
117 70e11eaa Sofia Papagiannaki
                                'show_form': ''})
118 70e11eaa Sofia Papagiannaki
            terms_uri = reverse('latest_terms') + '?' + params
119 70e11eaa Sofia Papagiannaki
            return HttpResponseRedirect(terms_uri)
120 70e11eaa Sofia Papagiannaki
        return func(request, *args, **kwargs)
121 70e11eaa Sofia Papagiannaki
    return wrapper
122 70e11eaa Sofia Papagiannaki
123 70e11eaa Sofia Papagiannaki
124 70e11eaa Sofia Papagiannaki
def required_auth_methods_assigned(allow_access=False):
125 70e11eaa Sofia Papagiannaki
    """
126 70e11eaa Sofia Papagiannaki
    Decorator that checks whether the request.user has all
127 70e11eaa Sofia Papagiannaki
    required auth providers assigned.
128 70e11eaa Sofia Papagiannaki
    """
129 70e11eaa Sofia Papagiannaki
130 70e11eaa Sofia Papagiannaki
    def decorator(func):
131 70e11eaa Sofia Papagiannaki
        @wraps(func)
132 70e11eaa Sofia Papagiannaki
        def wrapper(request, *args, **kwargs):
133 70e11eaa Sofia Papagiannaki
            if request.user.is_authenticated():
134 70e11eaa Sofia Papagiannaki
                missing = request.user.missing_required_providers()
135 70e11eaa Sofia Papagiannaki
                if missing:
136 70e11eaa Sofia Papagiannaki
                    for provider in missing:
137 70e11eaa Sofia Papagiannaki
                        messages.error(request,
138 70e11eaa Sofia Papagiannaki
                                       provider.get_required_msg)
139 70e11eaa Sofia Papagiannaki
                    if not allow_access:
140 70e11eaa Sofia Papagiannaki
                        return HttpResponseRedirect(reverse('edit_profile'))
141 70e11eaa Sofia Papagiannaki
            return func(request, *args, **kwargs)
142 70e11eaa Sofia Papagiannaki
        return wrapper
143 70e11eaa Sofia Papagiannaki
    return decorator
144 70e11eaa Sofia Papagiannaki
145 70e11eaa Sofia Papagiannaki
146 70e11eaa Sofia Papagiannaki
def valid_astakos_user_required(func):
147 70e11eaa Sofia Papagiannaki
    return signed_terms_required(
148 70e11eaa Sofia Papagiannaki
        required_auth_methods_assigned()(login_required(func)))