Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (5.3 kB)

1
# Copyright 2011-2012 GRNET S.A. All rights reserved.
2
#
3
# Redistribution and use in source and binary forms, with or
4
# without modification, are permitted provided that the following
5
# conditions are met:
6
#
7
#   1. Redistributions of source code must retain the above
8
#      copyright notice, this list of conditions and the following
9
#      disclaimer.
10
#
11
#   2. Redistributions in binary form must reproduce the above
12
#      copyright notice, this list of conditions and the following
13
#      disclaimer in the documentation and/or other materials
14
#      provided with the distribution.
15
#
16
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
# POSSIBILITY OF SUCH DAMAGE.
28
#
29
# The views and conclusions contained in the software and
30
# documentation are those of the authors and should not be
31
# interpreted as representing official policies, either expressed
32
# or implied, of GRNET S.A.
33

    
34
from functools import wraps
35

    
36
from django.contrib import messages
37
from django.contrib.auth.decorators import login_required
38
from django.core.exceptions import PermissionDenied
39
from django.core.urlresolvers import reverse
40
from django.http import HttpResponse, HttpResponseRedirect
41
from django.utils.http import urlencode
42

    
43
from astakos.im import auth_providers as auth
44
from astakos.im.cookie import CookieHandler
45

    
46

    
47
def cookie_fix(func):
48
    """
49
    Decorator checks whether the request.user conforms
50
    with the astakos cookie and if not it fixes it.
51
    """
52
    @wraps(func)
53
    def wrapper(request, *args, **kwargs):
54
        cookie = CookieHandler(request)
55
        if not cookie.is_valid:
56
            # redirect to request path to set/delete the cookie
57
            response = HttpResponse(status=302)
58
            response['Location'] = request.get_full_path()
59
            cookie.fix(response)
60
            return response
61

    
62
        response = func(request, *args, **kwargs)
63

    
64
        # if the user authentication status has changed during the processing
65
        # set/delete the cookie appropriately
66
        if not cookie.is_valid:
67
            cookie.fix(response)
68
        return response
69
    return wrapper
70

    
71

    
72
def requires_auth_provider(provider_id, **perms):
73
    """
74
    """
75
    def decorator(func, *args, **kwargs):
76
        @wraps(func)
77
        def wrapper(request, *args, **kwargs):
78
            provider = auth.get_provider(provider_id)
79

    
80
            if not provider or not provider.is_active():
81
                raise PermissionDenied
82

    
83
            for pkey, value in perms.iteritems():
84
                attr = 'get_%s_policy' % pkey.lower()
85
                if getattr(provider, attr) != value:
86
                    #TODO: add session message
87
                    return HttpResponseRedirect(reverse('login'))
88
            return func(request, *args)
89
        return wrapper
90
    return decorator
91

    
92

    
93
def requires_anonymous(func):
94
    """
95
    Decorator checkes whether the request.user is not Anonymous and
96
    in that case redirects to `logout`.
97
    """
98
    @wraps(func)
99
    def wrapper(request, *args):
100
        if not request.user.is_anonymous():
101
            next = urlencode({'next': request.build_absolute_uri()})
102
            logout_uri = reverse('astakos.im.views.logout') + '?' + next
103
            return HttpResponseRedirect(logout_uri)
104
        return func(request, *args)
105
    return wrapper
106

    
107

    
108
def signed_terms_required(func):
109
    """
110
    Decorator checks whether the request.user is Anonymous and in that case
111
    redirects to `logout`.
112
    """
113
    @wraps(func)
114
    def wrapper(request, *args, **kwargs):
115
        if request.user.is_authenticated() and not request.user.signed_terms:
116
            params = urlencode({'next': request.build_absolute_uri(),
117
                                'show_form': ''})
118
            terms_uri = reverse('latest_terms') + '?' + params
119
            return HttpResponseRedirect(terms_uri)
120
        return func(request, *args, **kwargs)
121
    return wrapper
122

    
123

    
124
def required_auth_methods_assigned(allow_access=False):
125
    """
126
    Decorator that checks whether the request.user has all
127
    required auth providers assigned.
128
    """
129

    
130
    def decorator(func):
131
        @wraps(func)
132
        def wrapper(request, *args, **kwargs):
133
            if request.user.is_authenticated():
134
                missing = request.user.missing_required_providers()
135
                if missing:
136
                    for provider in missing:
137
                        messages.error(request,
138
                                       provider.get_required_msg)
139
                    if not allow_access:
140
                        return HttpResponseRedirect(reverse('edit_profile'))
141
            return func(request, *args, **kwargs)
142
        return wrapper
143
    return decorator
144

    
145

    
146
def valid_astakos_user_required(func):
147
    return signed_terms_required(
148
        required_auth_methods_assigned()(login_required(func)))