Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / auth_providers.py @ 4bdd7e3d

History | View | Annotate | Download (7.1 kB)

1 d2633501 Kostas Papadimitriou
# Copyright 2011 GRNET S.A. All rights reserved.
2 d2633501 Kostas Papadimitriou
#
3 d2633501 Kostas Papadimitriou
# Redistribution and use in source and binary forms, with or
4 d2633501 Kostas Papadimitriou
# without modification, are permitted provided that the following
5 d2633501 Kostas Papadimitriou
# conditions are met:
6 d2633501 Kostas Papadimitriou
#
7 d2633501 Kostas Papadimitriou
#   1. Redistributions of source code must retain the above
8 d2633501 Kostas Papadimitriou
#      copyright notice, this list of conditions and the following
9 d2633501 Kostas Papadimitriou
#      disclaimer.
10 d2633501 Kostas Papadimitriou
#
11 d2633501 Kostas Papadimitriou
#   2. Redistributions in binary form must reproduce the above
12 d2633501 Kostas Papadimitriou
#      copyright notice, this list of conditions and the following
13 d2633501 Kostas Papadimitriou
#      disclaimer in the documentation and/or other materials
14 d2633501 Kostas Papadimitriou
#      provided with the distribution.
15 d2633501 Kostas Papadimitriou
#
16 d2633501 Kostas Papadimitriou
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 d2633501 Kostas Papadimitriou
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 d2633501 Kostas Papadimitriou
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 d2633501 Kostas Papadimitriou
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 d2633501 Kostas Papadimitriou
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 d2633501 Kostas Papadimitriou
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 d2633501 Kostas Papadimitriou
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 d2633501 Kostas Papadimitriou
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 d2633501 Kostas Papadimitriou
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 d2633501 Kostas Papadimitriou
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 d2633501 Kostas Papadimitriou
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 d2633501 Kostas Papadimitriou
# POSSIBILITY OF SUCH DAMAGE.
28 d2633501 Kostas Papadimitriou
#
29 d2633501 Kostas Papadimitriou
# The views and conclusions contained in the software and
30 d2633501 Kostas Papadimitriou
# documentation are those of the authors and should not be
31 d2633501 Kostas Papadimitriou
# interpreted as representing official policies, either expressed
32 d2633501 Kostas Papadimitriou
# or implied, of GRNET S.A.
33 d2633501 Kostas Papadimitriou
34 d2633501 Kostas Papadimitriou
35 d2633501 Kostas Papadimitriou
from django.core.urlresolvers import reverse
36 d2633501 Kostas Papadimitriou
from django.utils.translation import ugettext as _
37 081070a5 Kostas Papadimitriou
from django.utils.datastructures import SortedDict
38 d2633501 Kostas Papadimitriou
39 081070a5 Kostas Papadimitriou
from django.conf import settings
40 c4b1a172 Kostas Papadimitriou
41 081070a5 Kostas Papadimitriou
from astakos.im import settings as astakos_settings
42 c4b1a172 Kostas Papadimitriou
from astakos.im import messages as astakos_messages
43 d2633501 Kostas Papadimitriou
44 d2633501 Kostas Papadimitriou
import logging
45 d2633501 Kostas Papadimitriou
46 d2633501 Kostas Papadimitriou
logger = logging.getLogger(__name__)
47 d2633501 Kostas Papadimitriou
48 d2633501 Kostas Papadimitriou
# providers registry
49 6012535a Kostas Papadimitriou
PROVIDERS = {}
50 d2633501 Kostas Papadimitriou
51 d2633501 Kostas Papadimitriou
class AuthProviderBase(type):
52 d2633501 Kostas Papadimitriou
53 d2633501 Kostas Papadimitriou
    def __new__(cls, name, bases, dct):
54 d2633501 Kostas Papadimitriou
        include = False
55 d2633501 Kostas Papadimitriou
        if [b for b in bases if isinstance(b, AuthProviderBase)]:
56 d2633501 Kostas Papadimitriou
            type_id = dct.get('module')
57 d2633501 Kostas Papadimitriou
            if type_id:
58 d2633501 Kostas Papadimitriou
                include = True
59 081070a5 Kostas Papadimitriou
            if type_id in astakos_settings.IM_MODULES:
60 d2633501 Kostas Papadimitriou
                dct['module_enabled'] = True
61 d2633501 Kostas Papadimitriou
62 d2633501 Kostas Papadimitriou
        newcls = super(AuthProviderBase, cls).__new__(cls, name, bases, dct)
63 d2633501 Kostas Papadimitriou
        if include:
64 6012535a Kostas Papadimitriou
            PROVIDERS[type_id] = newcls
65 d2633501 Kostas Papadimitriou
        return newcls
66 d2633501 Kostas Papadimitriou
67 d2633501 Kostas Papadimitriou
68 d2633501 Kostas Papadimitriou
class AuthProvider(object):
69 d2633501 Kostas Papadimitriou
70 d2633501 Kostas Papadimitriou
    __metaclass__ = AuthProviderBase
71 d2633501 Kostas Papadimitriou
72 d2633501 Kostas Papadimitriou
    module = None
73 d2633501 Kostas Papadimitriou
    module_active = False
74 d2633501 Kostas Papadimitriou
    module_enabled = False
75 d2633501 Kostas Papadimitriou
    one_per_user = False
76 d2633501 Kostas Papadimitriou
77 c4b1a172 Kostas Papadimitriou
    def get_message(self, msg, **kwargs):
78 c4b1a172 Kostas Papadimitriou
        params = kwargs
79 c4b1a172 Kostas Papadimitriou
        params.update({'provider': self.get_title_display})
80 c4b1a172 Kostas Papadimitriou
81 c4b1a172 Kostas Papadimitriou
        override_msg = getattr(self, 'get_%s_message_display' % msg.lower(), None)
82 c4b1a172 Kostas Papadimitriou
        msg = 'AUTH_PROVIDER_%s' % msg
83 c4b1a172 Kostas Papadimitriou
        return override_msg or getattr(astakos_messages, msg, msg) % params
84 c4b1a172 Kostas Papadimitriou
85 d2633501 Kostas Papadimitriou
    def __init__(self, user=None):
86 d2633501 Kostas Papadimitriou
        self.user = user
87 d2633501 Kostas Papadimitriou
88 081070a5 Kostas Papadimitriou
    def __getattr__(self, key):
89 081070a5 Kostas Papadimitriou
        if not key.startswith('get_'):
90 6974e526 Kostas Papadimitriou
            return super(AuthProvider, self).__getattribute__(key)
91 081070a5 Kostas Papadimitriou
92 081070a5 Kostas Papadimitriou
        if key.endswith('_display') or key.endswith('template'):
93 081070a5 Kostas Papadimitriou
            attr = key.replace('_display', '').replace('get_','')
94 081070a5 Kostas Papadimitriou
            settings_attr = self.get_setting(attr.upper())
95 081070a5 Kostas Papadimitriou
            if not settings_attr:
96 081070a5 Kostas Papadimitriou
                return getattr(self, attr)
97 081070a5 Kostas Papadimitriou
            return settings_attr
98 081070a5 Kostas Papadimitriou
        else:
99 081070a5 Kostas Papadimitriou
            return super(AuthProvider, self).__getattr__(key)
100 081070a5 Kostas Papadimitriou
101 d2633501 Kostas Papadimitriou
    def get_setting(self, name, default=None):
102 081070a5 Kostas Papadimitriou
        attr = 'ASTAKOS_AUTH_PROVIDER_%s_%s' % (self.module.upper(), name.upper())
103 d2633501 Kostas Papadimitriou
        return getattr(settings, attr, default)
104 d2633501 Kostas Papadimitriou
105 d2633501 Kostas Papadimitriou
    def is_available_for_login(self):
106 d2633501 Kostas Papadimitriou
        """ A user can login using authentication provider"""
107 d2633501 Kostas Papadimitriou
        return self.is_active() and self.get_setting('CAN_LOGIN',
108 d2633501 Kostas Papadimitriou
                                                     self.is_active())
109 d2633501 Kostas Papadimitriou
110 d2633501 Kostas Papadimitriou
    def is_available_for_create(self):
111 d2633501 Kostas Papadimitriou
        """ A user can create an account using this provider"""
112 d2633501 Kostas Papadimitriou
        return self.is_active() and self.get_setting('CAN_CREATE',
113 d2633501 Kostas Papadimitriou
                                                   self.is_active())
114 d2633501 Kostas Papadimitriou
115 d2633501 Kostas Papadimitriou
    def is_available_for_add(self):
116 d2633501 Kostas Papadimitriou
        """ A user can assign provider authentication method"""
117 d2633501 Kostas Papadimitriou
        return self.is_active() and self.get_setting('CAN_ADD',
118 d2633501 Kostas Papadimitriou
                                                   self.is_active())
119 d2633501 Kostas Papadimitriou
120 d2633501 Kostas Papadimitriou
    def is_active(self):
121 081070a5 Kostas Papadimitriou
        return self.module in astakos_settings.IM_MODULES
122 d2633501 Kostas Papadimitriou
123 d2633501 Kostas Papadimitriou
124 d2633501 Kostas Papadimitriou
class LocalAuthProvider(AuthProvider):
125 d2633501 Kostas Papadimitriou
    module = 'local'
126 d2633501 Kostas Papadimitriou
    title = _('Local password')
127 d2633501 Kostas Papadimitriou
    description = _('Create a local password for your account')
128 081070a5 Kostas Papadimitriou
    create_prompt =  _('Create an account')
129 081070a5 Kostas Papadimitriou
    add_prompt =  _('Create a local password for your account')
130 d2633501 Kostas Papadimitriou
131 d2633501 Kostas Papadimitriou
132 d2633501 Kostas Papadimitriou
    @property
133 d2633501 Kostas Papadimitriou
    def add_url(self):
134 d2633501 Kostas Papadimitriou
        return reverse('password_change')
135 d2633501 Kostas Papadimitriou
136 d2633501 Kostas Papadimitriou
    one_per_user = True
137 081070a5 Kostas Papadimitriou
138 081070a5 Kostas Papadimitriou
    login_template = 'im/auth/local_login_form.html'
139 081070a5 Kostas Papadimitriou
    login_prompt_template = 'im/auth/local_login_prompt.html'
140 081070a5 Kostas Papadimitriou
    signup_prompt_template = 'im/auth/local_signup_prompt.html'
141 d2633501 Kostas Papadimitriou
    details_tpl = _('You can login to your account using your'
142 d2633501 Kostas Papadimitriou
                    ' %(auth_backend)s password.')
143 d2633501 Kostas Papadimitriou
144 d2633501 Kostas Papadimitriou
    @property
145 d2633501 Kostas Papadimitriou
    def extra_actions(self):
146 d2633501 Kostas Papadimitriou
        return [(_('Change password'), reverse('password_change')), ]
147 d2633501 Kostas Papadimitriou
148 158a72ec root
class LDAPAuthProvider(AuthProvider):
149 158a72ec root
    module = 'ldap'
150 158a72ec root
    title = _('LDAP credentials')
151 158a72ec root
    description = _('Allows you to login using your LDAP credentials')
152 158a72ec root
153 158a72ec root
    one_per_user = True
154 158a72ec root
155 158a72ec root
    login_template = 'im/auth/local_login_form.html'
156 158a72ec root
    login_prompt_template = 'im/auth/local_login_prompt.html'
157 158a72ec root
    signup_prompt_template = 'im/auth/local_signup_prompt.html'
158 158a72ec root
    details_tpl = _('You can login to your account using your'
159 158a72ec root
                    ' %(auth_backend)s password.')
160 d2633501 Kostas Papadimitriou
161 d2633501 Kostas Papadimitriou
class ShibbolethAuthProvider(AuthProvider):
162 d2633501 Kostas Papadimitriou
    module = 'shibboleth'
163 d2633501 Kostas Papadimitriou
    title = _('Academic credentials (Shibboleth)')
164 d2633501 Kostas Papadimitriou
    description = _('Allows you to login to your account using your academic '
165 d2633501 Kostas Papadimitriou
                    'credentials')
166 081070a5 Kostas Papadimitriou
    add_prompt = _('Add academic credentials to your account.')
167 c630fee6 Kostas Papadimitriou
    details_tpl = _('Shibboleth account %(identifier)s ('
168 c630fee6 Kostas Papadimitriou
                    '%(affiliation)s affiliation) is connected with your '
169 3a72a5d4 Kostas Papadimitriou
                    ' account.')
170 3a72a5d4 Kostas Papadimitriou
    user_title = _('Academic credentials (%(identifier)s)')
171 d2633501 Kostas Papadimitriou
172 d2633501 Kostas Papadimitriou
    @property
173 d2633501 Kostas Papadimitriou
    def add_url(self):
174 d2633501 Kostas Papadimitriou
        return reverse('astakos.im.target.shibboleth.login')
175 d2633501 Kostas Papadimitriou
176 081070a5 Kostas Papadimitriou
    login_template = 'im/auth/shibboleth_login.html'
177 081070a5 Kostas Papadimitriou
    login_prompt_template = 'im/auth/shibboleth_login_prompt.html'
178 d2633501 Kostas Papadimitriou
179 d2633501 Kostas Papadimitriou
180 c101b32b Kostas Papadimitriou
class TwitterAuthProvider(AuthProvider):
181 c101b32b Kostas Papadimitriou
    module = 'twitter'
182 c101b32b Kostas Papadimitriou
    title = _('Twitter')
183 c101b32b Kostas Papadimitriou
    description = _('Allows you to login to your account using your twitter '
184 c101b32b Kostas Papadimitriou
                    'account')
185 c101b32b Kostas Papadimitriou
    add_prompt = _('Connect with your Twitter account.')
186 3a72a5d4 Kostas Papadimitriou
    details_tpl = _('Twitter screen name: %(info_screen_name)s')
187 3a72a5d4 Kostas Papadimitriou
    user_title = _('Twitter (%(info_screen_name)s)')
188 c101b32b Kostas Papadimitriou
189 c101b32b Kostas Papadimitriou
    @property
190 c101b32b Kostas Papadimitriou
    def add_url(self):
191 c101b32b Kostas Papadimitriou
        return reverse('astakos.im.target.twitter.login')
192 c101b32b Kostas Papadimitriou
193 c101b32b Kostas Papadimitriou
    login_template = 'im/auth/twitter_login.html'
194 c101b32b Kostas Papadimitriou
    login_prompt_template = 'im/auth/twitter_login_prompt.html'
195 c101b32b Kostas Papadimitriou
196 d2633501 Kostas Papadimitriou
def get_provider(id, user_obj=None, default=None):
197 d2633501 Kostas Papadimitriou
    """
198 d2633501 Kostas Papadimitriou
    Return a provider instance from the auth providers registry.
199 d2633501 Kostas Papadimitriou
    """
200 d2633501 Kostas Papadimitriou
    return PROVIDERS.get(id, default)(user_obj)