Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / auth_providers.py @ 67cf14bf

History | View | Annotate | Download (21.4 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 9d20fe23 Kostas Papadimitriou
import copy
35 9d20fe23 Kostas Papadimitriou
import json
36 9d20fe23 Kostas Papadimitriou
37 9d20fe23 Kostas Papadimitriou
from synnefo.lib.ordereddict import OrderedDict
38 d2633501 Kostas Papadimitriou
39 d2633501 Kostas Papadimitriou
from django.core.urlresolvers import reverse
40 d2633501 Kostas Papadimitriou
from django.utils.translation import ugettext as _
41 9d20fe23 Kostas Papadimitriou
from django.contrib.auth.models import Group
42 9d20fe23 Kostas Papadimitriou
from django import template
43 d2633501 Kostas Papadimitriou
44 081070a5 Kostas Papadimitriou
from django.conf import settings
45 c4b1a172 Kostas Papadimitriou
46 081070a5 Kostas Papadimitriou
from astakos.im import settings as astakos_settings
47 c4b1a172 Kostas Papadimitriou
from astakos.im import messages as astakos_messages
48 d2633501 Kostas Papadimitriou
49 d2633501 Kostas Papadimitriou
import logging
50 d2633501 Kostas Papadimitriou
51 d2633501 Kostas Papadimitriou
logger = logging.getLogger(__name__)
52 d2633501 Kostas Papadimitriou
53 d2633501 Kostas Papadimitriou
# providers registry
54 6012535a Kostas Papadimitriou
PROVIDERS = {}
55 badcb2a9 Kostas Papadimitriou
REQUIRED_PROVIDERS = {}
56 d2633501 Kostas Papadimitriou
57 9d20fe23 Kostas Papadimitriou
58 d2633501 Kostas Papadimitriou
class AuthProviderBase(type):
59 d2633501 Kostas Papadimitriou
60 d2633501 Kostas Papadimitriou
    def __new__(cls, name, bases, dct):
61 d2633501 Kostas Papadimitriou
        include = False
62 d2633501 Kostas Papadimitriou
        if [b for b in bases if isinstance(b, AuthProviderBase)]:
63 d2633501 Kostas Papadimitriou
            type_id = dct.get('module')
64 d2633501 Kostas Papadimitriou
            if type_id:
65 d2633501 Kostas Papadimitriou
                include = True
66 081070a5 Kostas Papadimitriou
            if type_id in astakos_settings.IM_MODULES:
67 d2633501 Kostas Papadimitriou
                dct['module_enabled'] = True
68 d2633501 Kostas Papadimitriou
69 d2633501 Kostas Papadimitriou
        newcls = super(AuthProviderBase, cls).__new__(cls, name, bases, dct)
70 d2633501 Kostas Papadimitriou
        if include:
71 6012535a Kostas Papadimitriou
            PROVIDERS[type_id] = newcls
72 9d20fe23 Kostas Papadimitriou
            if newcls().get_required_policy:
73 badcb2a9 Kostas Papadimitriou
                REQUIRED_PROVIDERS[type_id] = newcls
74 d2633501 Kostas Papadimitriou
        return newcls
75 d2633501 Kostas Papadimitriou
76 d2633501 Kostas Papadimitriou
77 d2633501 Kostas Papadimitriou
class AuthProvider(object):
78 d2633501 Kostas Papadimitriou
79 d2633501 Kostas Papadimitriou
    __metaclass__ = AuthProviderBase
80 d2633501 Kostas Papadimitriou
81 d2633501 Kostas Papadimitriou
    module = None
82 d2633501 Kostas Papadimitriou
    module_enabled = False
83 9d20fe23 Kostas Papadimitriou
84 9d20fe23 Kostas Papadimitriou
    message_tpls = OrderedDict((
85 9d20fe23 Kostas Papadimitriou
        ('title', '{module_title}'),
86 9d20fe23 Kostas Papadimitriou
        ('login_title', '{title} LOGIN'),
87 9d20fe23 Kostas Papadimitriou
        ('method_prompt', '{title} login'),
88 9d20fe23 Kostas Papadimitriou
        ('account_prompt', '{title} account'),
89 9d20fe23 Kostas Papadimitriou
        ('signup_title', '{title}'),
90 9d20fe23 Kostas Papadimitriou
        ('profile_title', '{title}'),
91 9d20fe23 Kostas Papadimitriou
        ('method_details', '{account_prompt}: {identifier}'),
92 9d20fe23 Kostas Papadimitriou
        ('primary_login_prompt', 'Login using '),
93 9d20fe23 Kostas Papadimitriou
        ('required', '{title} is required. You can assign it '
94 9d20fe23 Kostas Papadimitriou
                     'from your profile page'),
95 9d20fe23 Kostas Papadimitriou
        ('login_prompt', ''),
96 9d20fe23 Kostas Papadimitriou
        ('add_prompt', 'Allows you to login using {title}'),
97 9d20fe23 Kostas Papadimitriou
        ('login_extra', ''),
98 9d20fe23 Kostas Papadimitriou
        ('username', '{username}'),
99 9d20fe23 Kostas Papadimitriou
        ('disabled_for_create', '{title} is not available for signup.'),
100 9d20fe23 Kostas Papadimitriou
        ('switch_success', 'Account changed successfully.'),
101 9d20fe23 Kostas Papadimitriou
        ('cannot_login', '{title} is not available for login. '
102 9d20fe23 Kostas Papadimitriou
                         'Please use one of your other available methods '
103 9d20fe23 Kostas Papadimitriou
                         'to login ({available_methods_links}'),
104 9d20fe23 Kostas Papadimitriou
105 9d20fe23 Kostas Papadimitriou
        # icons should end with _icon
106 9d20fe23 Kostas Papadimitriou
        ('module_medium_icon', 'im/auth/icons-medium/{module}.png'),
107 9d20fe23 Kostas Papadimitriou
        ('module_icon', 'im/auth/icons/{module}.png'))
108 9d20fe23 Kostas Papadimitriou
    )
109 9d20fe23 Kostas Papadimitriou
110 9d20fe23 Kostas Papadimitriou
    messages = {}
111 9d20fe23 Kostas Papadimitriou
    module_urls = {}
112 9d20fe23 Kostas Papadimitriou
113 564a2292 Kostas Papadimitriou
    remote_authenticate = True
114 564a2292 Kostas Papadimitriou
    remote_logout_url = None
115 d2633501 Kostas Papadimitriou
116 9d20fe23 Kostas Papadimitriou
    # templates
117 9d20fe23 Kostas Papadimitriou
    primary_login_template = 'im/auth/generic_primary_login.html'
118 9d20fe23 Kostas Papadimitriou
    login_template = 'im/auth/generic_login.html'
119 9d20fe23 Kostas Papadimitriou
    signup_template = 'im/signup.html'
120 9d20fe23 Kostas Papadimitriou
    login_prompt_template = 'im/auth/generic_login_prompt.html'
121 9d20fe23 Kostas Papadimitriou
    signup_prompt_template = 'im/auth/signup_prompt.html'
122 9d20fe23 Kostas Papadimitriou
123 9d20fe23 Kostas Papadimitriou
    default_policies = {
124 9d20fe23 Kostas Papadimitriou
        'login': True,
125 9d20fe23 Kostas Papadimitriou
        'create': True,
126 9d20fe23 Kostas Papadimitriou
        'add': True,
127 9d20fe23 Kostas Papadimitriou
        'remove': True,
128 9d20fe23 Kostas Papadimitriou
        'limit': 1,
129 9d20fe23 Kostas Papadimitriou
        'switch': True,
130 9d20fe23 Kostas Papadimitriou
        'add_groups': [],
131 9d20fe23 Kostas Papadimitriou
        'creation_groups': [],
132 9d20fe23 Kostas Papadimitriou
        'required': False,
133 9d20fe23 Kostas Papadimitriou
        'automoderate': not astakos_settings.MODERATION_ENABLED
134 9d20fe23 Kostas Papadimitriou
    }
135 9d20fe23 Kostas Papadimitriou
136 9d20fe23 Kostas Papadimitriou
    policies = {}
137 9d20fe23 Kostas Papadimitriou
138 9d20fe23 Kostas Papadimitriou
    def __init__(self, user=None, identifier=None, **provider_params):
139 9d20fe23 Kostas Papadimitriou
        """
140 9d20fe23 Kostas Papadimitriou
        3 ways to initialize (no args, user, user and identifier).
141 9d20fe23 Kostas Papadimitriou

142 9d20fe23 Kostas Papadimitriou
        no args: Used for anonymous unauthenticated users.
143 9d20fe23 Kostas Papadimitriou
        >>> p = auth_providers.get_provider('local')
144 9d20fe23 Kostas Papadimitriou
        >>> # check that global settings allows us to create a new account
145 9d20fe23 Kostas Papadimitriou
        >>> # using `local` provider.
146 9d20fe23 Kostas Papadimitriou
        >>> print p.is_available_for_create()
147 9d20fe23 Kostas Papadimitriou

148 9d20fe23 Kostas Papadimitriou
        user and identifier: Used to provide details about a user's specific
149 9d20fe23 Kostas Papadimitriou
        login method.
150 97246b51 Kostas Papadimitriou
        >>> p = auth_providers.get_provider('google', user,
151 97246b51 Kostas Papadimitriou
        >>>                                 identifier='1421421')
152 9d20fe23 Kostas Papadimitriou
        >>> # provider (google) details prompt
153 9d20fe23 Kostas Papadimitriou
        >>> print p.get_method_details()
154 9d20fe23 Kostas Papadimitriou
        "Google account: 1421421"
155 9d20fe23 Kostas Papadimitriou
        """
156 9d20fe23 Kostas Papadimitriou
157 9d20fe23 Kostas Papadimitriou
        # handle AnonymousUser instance
158 9d20fe23 Kostas Papadimitriou
        self.user = None
159 9d20fe23 Kostas Papadimitriou
        if user and hasattr(user, 'pk') and user.pk:
160 9d20fe23 Kostas Papadimitriou
            self.user = user
161 c4b1a172 Kostas Papadimitriou
162 9d20fe23 Kostas Papadimitriou
        self.identifier = identifier
163 9d20fe23 Kostas Papadimitriou
        self._instance = None
164 9d20fe23 Kostas Papadimitriou
        if 'instance' in provider_params:
165 9d20fe23 Kostas Papadimitriou
            self._instance = provider_params['instance']
166 9d20fe23 Kostas Papadimitriou
            del provider_params['instance']
167 9d20fe23 Kostas Papadimitriou
168 9d20fe23 Kostas Papadimitriou
        # initialize policies
169 9d20fe23 Kostas Papadimitriou
        self.module_policies = copy.copy(self.default_policies)
170 9d20fe23 Kostas Papadimitriou
        self.module_policies['automoderate'] = not \
171 9d20fe23 Kostas Papadimitriou
            astakos_settings.MODERATION_ENABLED
172 bc8bede2 Kostas Papadimitriou
        for policy, value in self.policies.iteritems():
173 9d20fe23 Kostas Papadimitriou
            setting_key = "%s_POLICY" % policy.upper()
174 9d20fe23 Kostas Papadimitriou
            if self.has_setting(setting_key):
175 9d20fe23 Kostas Papadimitriou
                self.module_policies[policy] = self.get_setting(setting_key)
176 7bb081f5 Kostas Papadimitriou
            else:
177 7bb081f5 Kostas Papadimitriou
                self.module_policies[policy] = value
178 9d20fe23 Kostas Papadimitriou
179 9d20fe23 Kostas Papadimitriou
        # messages cache
180 9d20fe23 Kostas Papadimitriou
        self.message_tpls_compiled = OrderedDict()
181 9d20fe23 Kostas Papadimitriou
182 9d20fe23 Kostas Papadimitriou
        # module specific messages
183 9d20fe23 Kostas Papadimitriou
        self.message_tpls = OrderedDict(self.message_tpls)
184 9d20fe23 Kostas Papadimitriou
        for key, value in self.messages.iteritems():
185 9d20fe23 Kostas Papadimitriou
            self.message_tpls[key] = value
186 9d20fe23 Kostas Papadimitriou
187 9d20fe23 Kostas Papadimitriou
        self._provider_details = provider_params
188 9d20fe23 Kostas Papadimitriou
189 9d20fe23 Kostas Papadimitriou
        self.resolve_available_methods = True
190 9d20fe23 Kostas Papadimitriou
191 9d20fe23 Kostas Papadimitriou
    def get_provider_model(self):
192 9d20fe23 Kostas Papadimitriou
        from astakos.im.models import AstakosUserAuthProvider as AuthProvider
193 9d20fe23 Kostas Papadimitriou
        return AuthProvider
194 9d20fe23 Kostas Papadimitriou
195 9d20fe23 Kostas Papadimitriou
    def remove_from_user(self):
196 9d20fe23 Kostas Papadimitriou
        if not self.get_remove_policy:
197 9d20fe23 Kostas Papadimitriou
            raise Exception("Provider cannot be removed")
198 9d20fe23 Kostas Papadimitriou
199 5d91dccb Kostas Papadimitriou
        for group_name in self.get_add_groups_policy:
200 5d91dccb Kostas Papadimitriou
            group = Group.objects.get(name=group_name)
201 5d91dccb Kostas Papadimitriou
            self.user.groups.remove(group)
202 5d91dccb Kostas Papadimitriou
            self.log('removed from group due to add_groups_policy %s',
203 5d91dccb Kostas Papadimitriou
                     group.name)
204 5d91dccb Kostas Papadimitriou
205 9d20fe23 Kostas Papadimitriou
        self._instance.delete()
206 5d91dccb Kostas Papadimitriou
        self.log('removed')
207 9d20fe23 Kostas Papadimitriou
208 9d20fe23 Kostas Papadimitriou
    def add_to_user(self, **params):
209 9d20fe23 Kostas Papadimitriou
        if self._instance:
210 9d20fe23 Kostas Papadimitriou
            raise Exception("Cannot add an existing provider")
211 9d20fe23 Kostas Papadimitriou
212 9d20fe23 Kostas Papadimitriou
        create = False
213 9d20fe23 Kostas Papadimitriou
        if self.get_user_providers().count() == 0:
214 9d20fe23 Kostas Papadimitriou
            create = True
215 9d20fe23 Kostas Papadimitriou
216 9d20fe23 Kostas Papadimitriou
        if create and not self.get_create_policy:
217 9d20fe23 Kostas Papadimitriou
            raise Exception("Provider not available for create")
218 9d20fe23 Kostas Papadimitriou
219 9d20fe23 Kostas Papadimitriou
        if not self.get_add_policy:
220 9d20fe23 Kostas Papadimitriou
            raise Exception("Provider cannot be added")
221 9d20fe23 Kostas Papadimitriou
222 9d20fe23 Kostas Papadimitriou
        if create:
223 9d20fe23 Kostas Papadimitriou
            for group_name in self.get_creation_groups_policy:
224 9d20fe23 Kostas Papadimitriou
                group, created = Group.objects.get_or_create(name=group_name)
225 9d20fe23 Kostas Papadimitriou
                self.user.groups.add(group)
226 97246b51 Kostas Papadimitriou
                self.log("added to %s group due to creation_groups_policy",
227 97246b51 Kostas Papadimitriou
                         group_name)
228 9d20fe23 Kostas Papadimitriou
229 9d20fe23 Kostas Papadimitriou
        for group_name in self.get_add_groups_policy:
230 9d20fe23 Kostas Papadimitriou
            group, created = Group.objects.get_or_create(name=group_name)
231 9d20fe23 Kostas Papadimitriou
            self.user.groups.add(group)
232 97246b51 Kostas Papadimitriou
            self.log("added to %s group due to add_groups_policy",
233 97246b51 Kostas Papadimitriou
                     group_name)
234 9d20fe23 Kostas Papadimitriou
235 9d20fe23 Kostas Papadimitriou
        if self.identifier:
236 9d20fe23 Kostas Papadimitriou
            pending = self.get_provider_model().objects.unverified(
237 9d20fe23 Kostas Papadimitriou
                self.module, identifier=self.identifier)
238 9d20fe23 Kostas Papadimitriou
239 9d20fe23 Kostas Papadimitriou
            if pending:
240 9d20fe23 Kostas Papadimitriou
                pending._instance.delete()
241 9d20fe23 Kostas Papadimitriou
242 9d20fe23 Kostas Papadimitriou
        create_params = {
243 9d20fe23 Kostas Papadimitriou
            'module': self.module,
244 9d20fe23 Kostas Papadimitriou
            'info_data': json.dumps(self.provider_details.get('info', {})),
245 9d20fe23 Kostas Papadimitriou
            'active': True,
246 9d20fe23 Kostas Papadimitriou
            'identifier': self.identifier
247 9d20fe23 Kostas Papadimitriou
        }
248 9d20fe23 Kostas Papadimitriou
        if 'info' in self.provider_details:
249 9d20fe23 Kostas Papadimitriou
            del self.provider_details['info']
250 9d20fe23 Kostas Papadimitriou
251 9d20fe23 Kostas Papadimitriou
        create_params.update(self.provider_details)
252 9d20fe23 Kostas Papadimitriou
        create_params.update(params)
253 97246b51 Kostas Papadimitriou
        create = self.user.auth_providers.create(**create_params)
254 97246b51 Kostas Papadimitriou
        self.log("created %r" % create_params)
255 97246b51 Kostas Papadimitriou
        return create
256 9d20fe23 Kostas Papadimitriou
257 9d20fe23 Kostas Papadimitriou
    def __repr__(self):
258 9d20fe23 Kostas Papadimitriou
        r = "'%s' module" % self.__class__.__name__
259 9d20fe23 Kostas Papadimitriou
        if self.user:
260 9d20fe23 Kostas Papadimitriou
            r += ' (user: %s)' % self.user
261 9d20fe23 Kostas Papadimitriou
        if self.identifier:
262 97246b51 Kostas Papadimitriou
            r += '(identifier: %s)' % self.identifier
263 9d20fe23 Kostas Papadimitriou
        return r
264 9d20fe23 Kostas Papadimitriou
265 9d20fe23 Kostas Papadimitriou
    def _message_params(self, **extra_params):
266 9d20fe23 Kostas Papadimitriou
        """
267 9d20fe23 Kostas Papadimitriou
        Retrieve message formating parameters.
268 9d20fe23 Kostas Papadimitriou
        """
269 9d20fe23 Kostas Papadimitriou
        params = {'module': self.module, 'module_title': self.module.title()}
270 9d20fe23 Kostas Papadimitriou
        if self.identifier:
271 9d20fe23 Kostas Papadimitriou
            params['identifier'] = self.identifier
272 c4b1a172 Kostas Papadimitriou
273 9d20fe23 Kostas Papadimitriou
        if self.user:
274 9d20fe23 Kostas Papadimitriou
            for key, val in self.user.__dict__.iteritems():
275 9d20fe23 Kostas Papadimitriou
                params["user_%s" % key.lower()] = val
276 9d20fe23 Kostas Papadimitriou
277 9d20fe23 Kostas Papadimitriou
        if self.provider_details:
278 9d20fe23 Kostas Papadimitriou
            for key, val in self.provider_details.iteritems():
279 9d20fe23 Kostas Papadimitriou
                params["provider_%s" % key.lower()] = val
280 9d20fe23 Kostas Papadimitriou
281 9d20fe23 Kostas Papadimitriou
            if 'info' in self.provider_details:
282 9d20fe23 Kostas Papadimitriou
                if isinstance(self.provider_details['info'], basestring):
283 9d20fe23 Kostas Papadimitriou
                    self.provider_details['info'] = \
284 9d20fe23 Kostas Papadimitriou
                        json.loads(self.provider_details['info'])
285 9d20fe23 Kostas Papadimitriou
                for key, val in self.provider_details['info'].iteritems():
286 9d20fe23 Kostas Papadimitriou
                   params['provider_info_%s' % key.lower()] = val
287 9d20fe23 Kostas Papadimitriou
288 9d20fe23 Kostas Papadimitriou
        # resolve username, handle unexisting defined username key
289 9d20fe23 Kostas Papadimitriou
        if self.user and self.username_key in params:
290 9d20fe23 Kostas Papadimitriou
            params['username'] = params[self.username_key]
291 9d20fe23 Kostas Papadimitriou
        else:
292 9d20fe23 Kostas Papadimitriou
            params['username'] = self.identifier
293 9d20fe23 Kostas Papadimitriou
294 9d20fe23 Kostas Papadimitriou
        if not self.message_tpls_compiled:
295 9d20fe23 Kostas Papadimitriou
            for key, message_tpl in self.message_tpls.iteritems():
296 9d20fe23 Kostas Papadimitriou
                msg = self.messages.get(key, self.message_tpls.get(key))
297 9d20fe23 Kostas Papadimitriou
                override_in_settings = self.get_setting(key)
298 9d20fe23 Kostas Papadimitriou
                if override_in_settings is not None:
299 9d20fe23 Kostas Papadimitriou
                    msg = override_in_settings
300 9d20fe23 Kostas Papadimitriou
                try:
301 9d20fe23 Kostas Papadimitriou
                    self.message_tpls_compiled[key] = msg.format(**params)
302 9d20fe23 Kostas Papadimitriou
                    params.update(self.message_tpls_compiled)
303 9d20fe23 Kostas Papadimitriou
                except KeyError, e:
304 9d20fe23 Kostas Papadimitriou
                    continue
305 9d20fe23 Kostas Papadimitriou
        else:
306 9d20fe23 Kostas Papadimitriou
            params.update(self.message_tpls_compiled)
307 9d20fe23 Kostas Papadimitriou
308 9d20fe23 Kostas Papadimitriou
        for key, value in self.urls.iteritems():
309 9d20fe23 Kostas Papadimitriou
            params['%s_url' % key] = value
310 9d20fe23 Kostas Papadimitriou
311 9d20fe23 Kostas Papadimitriou
        if self.user and self.resolve_available_methods:
312 9d20fe23 Kostas Papadimitriou
            available_providers = self.user.get_enabled_auth_providers()
313 9d20fe23 Kostas Papadimitriou
            for p in available_providers:
314 9d20fe23 Kostas Papadimitriou
                p.resolve_available_methods = False
315 9d20fe23 Kostas Papadimitriou
                if p.module == self.module and p.identifier == self.identifier:
316 9d20fe23 Kostas Papadimitriou
                    available_providers.remove(p)
317 9d20fe23 Kostas Papadimitriou
318 9d20fe23 Kostas Papadimitriou
            get_msg = lambda p: p.get_method_prompt_msg
319 9d20fe23 Kostas Papadimitriou
            params['available_methods'] = \
320 9d20fe23 Kostas Papadimitriou
                ','.join(map(get_msg, available_providers))
321 9d20fe23 Kostas Papadimitriou
322 9d20fe23 Kostas Papadimitriou
            get_msg = lambda p: "<a href='%s'>%s</a>" % \
323 97246b51 Kostas Papadimitriou
                (p.get_login_url, p.get_method_prompt_msg)
324 9d20fe23 Kostas Papadimitriou
325 9d20fe23 Kostas Papadimitriou
            params['available_methods_links'] = \
326 9d20fe23 Kostas Papadimitriou
                ','.join(map(get_msg, available_providers))
327 9d20fe23 Kostas Papadimitriou
328 9d20fe23 Kostas Papadimitriou
        params.update(extra_params)
329 9d20fe23 Kostas Papadimitriou
        return params
330 9d20fe23 Kostas Papadimitriou
331 9d20fe23 Kostas Papadimitriou
    def get_template(self, tpl):
332 9d20fe23 Kostas Papadimitriou
        tpls = ['im/auth/%s_%s.html' % (self.module, tpl),
333 9d20fe23 Kostas Papadimitriou
                getattr(self, '%s_template' % tpl)]
334 9d20fe23 Kostas Papadimitriou
        found = None
335 9d20fe23 Kostas Papadimitriou
        for tpl in tpls:
336 9d20fe23 Kostas Papadimitriou
            try:
337 9d20fe23 Kostas Papadimitriou
                found = template.loader.get_template(tpl)
338 9d20fe23 Kostas Papadimitriou
                return tpl
339 9d20fe23 Kostas Papadimitriou
            except template.TemplateDoesNotExist:
340 9d20fe23 Kostas Papadimitriou
                continue
341 9d20fe23 Kostas Papadimitriou
        if not found:
342 9d20fe23 Kostas Papadimitriou
            raise template.TemplateDoesNotExist
343 9d20fe23 Kostas Papadimitriou
        return tpl
344 9d20fe23 Kostas Papadimitriou
345 9d20fe23 Kostas Papadimitriou
    def get_username(self):
346 9d20fe23 Kostas Papadimitriou
        return self.get_username_msg
347 9d20fe23 Kostas Papadimitriou
348 9d20fe23 Kostas Papadimitriou
    def get_user_providers(self):
349 9d20fe23 Kostas Papadimitriou
        return self.user.auth_providers.active()
350 9d20fe23 Kostas Papadimitriou
351 9d20fe23 Kostas Papadimitriou
    def get_user_module_providers(self):
352 9d20fe23 Kostas Papadimitriou
        return self.user.auth_providers.active().filter(module=self.module)
353 9d20fe23 Kostas Papadimitriou
354 9d20fe23 Kostas Papadimitriou
    def get_existing_providers(self):
355 9d20fe23 Kostas Papadimitriou
        return ""
356 9d20fe23 Kostas Papadimitriou
357 9d20fe23 Kostas Papadimitriou
    def verified_exists(self):
358 9d20fe23 Kostas Papadimitriou
        return self.get_provider_model().objects.verified(
359 9d20fe23 Kostas Papadimitriou
            self.module, identifier=self.identifier)
360 9d20fe23 Kostas Papadimitriou
361 97246b51 Kostas Papadimitriou
    def resolve_policy(self, policy, default=None):
362 9d20fe23 Kostas Papadimitriou
363 9d20fe23 Kostas Papadimitriou
        if policy == 'switch' and default and not self.get_add_policy:
364 9d20fe23 Kostas Papadimitriou
            return not self.get_policy('remove')
365 9d20fe23 Kostas Papadimitriou
366 9d20fe23 Kostas Papadimitriou
        if not self.user:
367 9d20fe23 Kostas Papadimitriou
            return default
368 9d20fe23 Kostas Papadimitriou
369 9d20fe23 Kostas Papadimitriou
        if policy == 'remove' and default is True:
370 9d20fe23 Kostas Papadimitriou
            return self.get_user_providers().count() > 1
371 9d20fe23 Kostas Papadimitriou
372 9d20fe23 Kostas Papadimitriou
        if policy == 'add' and default is True:
373 9d20fe23 Kostas Papadimitriou
            limit = self.get_policy('limit')
374 9d20fe23 Kostas Papadimitriou
            if limit <= self.get_user_module_providers().count():
375 9d20fe23 Kostas Papadimitriou
                return False
376 9d20fe23 Kostas Papadimitriou
377 9d20fe23 Kostas Papadimitriou
            if self.identifier:
378 9d20fe23 Kostas Papadimitriou
                if self.verified_exists():
379 9d20fe23 Kostas Papadimitriou
                    return False
380 9d20fe23 Kostas Papadimitriou
381 9d20fe23 Kostas Papadimitriou
        return default
382 9d20fe23 Kostas Papadimitriou
383 9d20fe23 Kostas Papadimitriou
    def get_user_policies(self):
384 9d20fe23 Kostas Papadimitriou
        from astakos.im.models import AuthProviderPolicyProfile
385 9d20fe23 Kostas Papadimitriou
        return AuthProviderPolicyProfile.objects.for_user(self.user,
386 9d20fe23 Kostas Papadimitriou
                                                          self.module)
387 9d20fe23 Kostas Papadimitriou
388 9d20fe23 Kostas Papadimitriou
    def get_policy(self, policy):
389 9d20fe23 Kostas Papadimitriou
        module_default = self.module_policies.get(policy)
390 9d20fe23 Kostas Papadimitriou
        settings_key = '%s_POLICY' % policy.upper()
391 9d20fe23 Kostas Papadimitriou
        settings_default = self.get_setting(settings_key, module_default)
392 9d20fe23 Kostas Papadimitriou
393 9d20fe23 Kostas Papadimitriou
        if self.user:
394 9d20fe23 Kostas Papadimitriou
            user_policies = self.get_user_policies()
395 9d20fe23 Kostas Papadimitriou
            settings_default = user_policies.get(policy, settings_default)
396 9d20fe23 Kostas Papadimitriou
397 97246b51 Kostas Papadimitriou
        return self.resolve_policy(policy, settings_default)
398 9d20fe23 Kostas Papadimitriou
399 9d20fe23 Kostas Papadimitriou
    def get_message(self, msg, **extra_params):
400 9d20fe23 Kostas Papadimitriou
        """
401 9d20fe23 Kostas Papadimitriou
        Retrieve an auth provider message
402 9d20fe23 Kostas Papadimitriou
        """
403 9d20fe23 Kostas Papadimitriou
        if msg.endswith('_msg'):
404 9d20fe23 Kostas Papadimitriou
            msg = msg.replace('_msg', '')
405 9d20fe23 Kostas Papadimitriou
        params = self._message_params(**extra_params)
406 9d20fe23 Kostas Papadimitriou
407 9d20fe23 Kostas Papadimitriou
        # is message ???
408 9d20fe23 Kostas Papadimitriou
        tpl = self.message_tpls_compiled.get(msg.lower(), None)
409 9d20fe23 Kostas Papadimitriou
        if not tpl:
410 9d20fe23 Kostas Papadimitriou
            msg_key = 'AUTH_PROVIDER_%s' % msg.upper()
411 9d20fe23 Kostas Papadimitriou
            try:
412 9d20fe23 Kostas Papadimitriou
                tpl = getattr(astakos_messages, msg_key)
413 9d20fe23 Kostas Papadimitriou
            except AttributeError, e:
414 9d20fe23 Kostas Papadimitriou
                try:
415 9d20fe23 Kostas Papadimitriou
                    msg_key = msg.upper()
416 9d20fe23 Kostas Papadimitriou
                    tpl = getattr(astakos_messages, msg_key)
417 9d20fe23 Kostas Papadimitriou
                except AttributeError, e:
418 9d20fe23 Kostas Papadimitriou
                    tpl = ''
419 9d20fe23 Kostas Papadimitriou
420 9d20fe23 Kostas Papadimitriou
        in_settings = self.get_setting(msg)
421 9d20fe23 Kostas Papadimitriou
        if in_settings:
422 9d20fe23 Kostas Papadimitriou
            tpl = in_settings
423 9d20fe23 Kostas Papadimitriou
424 9d20fe23 Kostas Papadimitriou
        return tpl.format(**params)
425 dd5f8f4d Kostas Papadimitriou
426 0e79735c Kostas Papadimitriou
    @property
427 9d20fe23 Kostas Papadimitriou
    def urls(self):
428 9d20fe23 Kostas Papadimitriou
        urls = {
429 9d20fe23 Kostas Papadimitriou
            'login': reverse(self.login_view),
430 9d20fe23 Kostas Papadimitriou
            'add': reverse(self.login_view),
431 9d20fe23 Kostas Papadimitriou
            'profile': reverse('edit_profile'),
432 9d20fe23 Kostas Papadimitriou
        }
433 0e79735c Kostas Papadimitriou
        if self.user:
434 9d20fe23 Kostas Papadimitriou
            urls.update({
435 9d20fe23 Kostas Papadimitriou
                'resend_activation': self.user.get_resend_activation_url(),
436 9d20fe23 Kostas Papadimitriou
            })
437 9d20fe23 Kostas Papadimitriou
        if self.identifier and self._instance:
438 9d20fe23 Kostas Papadimitriou
            urls.update({
439 9d20fe23 Kostas Papadimitriou
                'switch': reverse(self.login_view) + '?switch_from=%d' % \
440 9d20fe23 Kostas Papadimitriou
                    self._instance.pk,
441 9d20fe23 Kostas Papadimitriou
                'remove': reverse('remove_auth_provider',
442 9d20fe23 Kostas Papadimitriou
                                  kwargs={'pk': self._instance.pk})
443 9d20fe23 Kostas Papadimitriou
            })
444 9d20fe23 Kostas Papadimitriou
        urls.update(self.module_urls)
445 9d20fe23 Kostas Papadimitriou
        return urls
446 9d20fe23 Kostas Papadimitriou
447 9d20fe23 Kostas Papadimitriou
    def get_setting_key(self, name):
448 9d20fe23 Kostas Papadimitriou
        return 'ASTAKOS_AUTH_PROVIDER_%s_%s' % (self.module.upper(),
449 9d20fe23 Kostas Papadimitriou
                                                name.upper())
450 9d20fe23 Kostas Papadimitriou
451 9d20fe23 Kostas Papadimitriou
    def get_global_setting_key(self, name):
452 9d20fe23 Kostas Papadimitriou
        return 'ASTAKOS_AUTH_PROVIDERS_%s' % name.upper()
453 9d20fe23 Kostas Papadimitriou
454 9d20fe23 Kostas Papadimitriou
    def has_global_setting(self, name):
455 9d20fe23 Kostas Papadimitriou
        return hasattr(settings, self.get_global_setting_key(name))
456 9d20fe23 Kostas Papadimitriou
457 9d20fe23 Kostas Papadimitriou
    def has_setting(self, name):
458 9d20fe23 Kostas Papadimitriou
        return hasattr(settings, self.get_setting_key(name))
459 0e79735c Kostas Papadimitriou
460 9d20fe23 Kostas Papadimitriou
    def get_setting(self, name, default=None):
461 9d20fe23 Kostas Papadimitriou
        attr = self.get_setting_key(name)
462 9d20fe23 Kostas Papadimitriou
        if not self.has_setting(name):
463 9d20fe23 Kostas Papadimitriou
            return self.get_global_setting(name, default)
464 9d20fe23 Kostas Papadimitriou
        return getattr(settings, attr, default)
465 0e79735c Kostas Papadimitriou
466 9d20fe23 Kostas Papadimitriou
    def get_global_setting(self, name, default=None):
467 9d20fe23 Kostas Papadimitriou
        attr = self.get_global_setting_key(name)
468 9d20fe23 Kostas Papadimitriou
        if not self.has_global_setting(name):
469 9d20fe23 Kostas Papadimitriou
            return default
470 9d20fe23 Kostas Papadimitriou
        return getattr(settings, attr, default)
471 9d20fe23 Kostas Papadimitriou
472 9d20fe23 Kostas Papadimitriou
    @property
473 9d20fe23 Kostas Papadimitriou
    def provider_details(self):
474 9d20fe23 Kostas Papadimitriou
        if self._provider_details:
475 9d20fe23 Kostas Papadimitriou
            return self._provider_details
476 564a2292 Kostas Papadimitriou
477 9d20fe23 Kostas Papadimitriou
        self._provider_details = {}
478 64492c49 Kostas Papadimitriou
479 9d20fe23 Kostas Papadimitriou
        if self._instance:
480 9d20fe23 Kostas Papadimitriou
            self._provider_details = self._instance.__dict__
481 bd0f516a Kostas Papadimitriou
482 9d20fe23 Kostas Papadimitriou
        if self.user and self.identifier:
483 9d20fe23 Kostas Papadimitriou
            if self.identifier:
484 9d20fe23 Kostas Papadimitriou
                try:
485 9d20fe23 Kostas Papadimitriou
                    self._provider_details = \
486 9d20fe23 Kostas Papadimitriou
                        self.user.get_auth_providers().get(
487 9d20fe23 Kostas Papadimitriou
                            module=self.module,
488 9d20fe23 Kostas Papadimitriou
                            identifier=self.identifier).__dict__
489 9d20fe23 Kostas Papadimitriou
                except Exception:
490 9d20fe23 Kostas Papadimitriou
                    return {}
491 9d20fe23 Kostas Papadimitriou
        return self._provider_details
492 d0632ab1 Olga Brani
493 081070a5 Kostas Papadimitriou
    def __getattr__(self, key):
494 081070a5 Kostas Papadimitriou
        if not key.startswith('get_'):
495 6974e526 Kostas Papadimitriou
            return super(AuthProvider, self).__getattribute__(key)
496 081070a5 Kostas Papadimitriou
497 9d20fe23 Kostas Papadimitriou
        key = key.replace('get_', '')
498 9d20fe23 Kostas Papadimitriou
        if key.endswith('_msg'):
499 9d20fe23 Kostas Papadimitriou
            return self.get_message(key)
500 91bbc1a4 Kostas Papadimitriou
501 9d20fe23 Kostas Papadimitriou
        if key.endswith('_policy'):
502 9d20fe23 Kostas Papadimitriou
            return self.get_policy(key.replace('_policy', ''))
503 d2633501 Kostas Papadimitriou
504 9d20fe23 Kostas Papadimitriou
        if key.endswith('_url'):
505 9d20fe23 Kostas Papadimitriou
            key = key.replace('_url', '')
506 9d20fe23 Kostas Papadimitriou
            return self.urls.get(key)
507 e9e692be Kostas Papadimitriou
508 9d20fe23 Kostas Papadimitriou
        if key.endswith('_icon'):
509 9d20fe23 Kostas Papadimitriou
            key = key.replace('_msg', '_icon')
510 9d20fe23 Kostas Papadimitriou
            return settings.MEDIA_URL + self.get_message(key)
511 d2633501 Kostas Papadimitriou
512 9d20fe23 Kostas Papadimitriou
        if key.endswith('_setting'):
513 9d20fe23 Kostas Papadimitriou
            key = key.replace('_setting', '')
514 9d20fe23 Kostas Papadimitriou
            return self.get_message(key)
515 d2633501 Kostas Papadimitriou
516 9d20fe23 Kostas Papadimitriou
        if key.endswith('_template'):
517 9d20fe23 Kostas Papadimitriou
            key = key.replace('_template', '')
518 9d20fe23 Kostas Papadimitriou
            return self.get_template(key)
519 d2633501 Kostas Papadimitriou
520 9d20fe23 Kostas Papadimitriou
        return super(AuthProvider, self).__getattribute__(key)
521 badcb2a9 Kostas Papadimitriou
522 d2633501 Kostas Papadimitriou
    def is_active(self):
523 9d20fe23 Kostas Papadimitriou
        return self.module_enabled
524 d2633501 Kostas Papadimitriou
525 97246b51 Kostas Papadimitriou
    @property
526 97246b51 Kostas Papadimitriou
    def log_display(self):
527 97246b51 Kostas Papadimitriou
        dsp = "%sAuth" % self.module.title()
528 97246b51 Kostas Papadimitriou
        if self.user:
529 97246b51 Kostas Papadimitriou
            dsp += "[%s]" % self.user.log_display
530 97246b51 Kostas Papadimitriou
            if self.identifier:
531 97246b51 Kostas Papadimitriou
                dsp += '[%s]' % self.identifier
532 97246b51 Kostas Papadimitriou
                if self._instance and self._instance.pk:
533 97246b51 Kostas Papadimitriou
                    dsp += '[%d]' % self._instance.pk
534 97246b51 Kostas Papadimitriou
        return dsp
535 97246b51 Kostas Papadimitriou
536 97246b51 Kostas Papadimitriou
    def log(self, msg, *args, **kwargs):
537 97246b51 Kostas Papadimitriou
        level = kwargs.pop('level', logging.INFO)
538 97246b51 Kostas Papadimitriou
        message = '%s: %s' % (self.log_display, msg)
539 97246b51 Kostas Papadimitriou
        logger.log(level, message, *args, **kwargs)
540 97246b51 Kostas Papadimitriou
541 d2633501 Kostas Papadimitriou
542 d2633501 Kostas Papadimitriou
class LocalAuthProvider(AuthProvider):
543 d2633501 Kostas Papadimitriou
    module = 'local'
544 9d20fe23 Kostas Papadimitriou
545 dd5f8f4d Kostas Papadimitriou
    login_view = 'password_change'
546 564a2292 Kostas Papadimitriou
    remote_authenticate = False
547 9d20fe23 Kostas Papadimitriou
    username_key = 'user_email'
548 081070a5 Kostas Papadimitriou
549 9d20fe23 Kostas Papadimitriou
    messages = {
550 9d20fe23 Kostas Papadimitriou
        'title': _('Classic'),
551 9d20fe23 Kostas Papadimitriou
        'login_prompt': _('Classic login (username/password)'),
552 9d20fe23 Kostas Papadimitriou
        'login_success': _('Logged in successfully.'),
553 9d20fe23 Kostas Papadimitriou
        'method_details': 'Username: {username}',
554 9d20fe23 Kostas Papadimitriou
        'logout_success_extra': ' '
555 9d20fe23 Kostas Papadimitriou
    }
556 d2633501 Kostas Papadimitriou
557 bc8bede2 Kostas Papadimitriou
    policies = {
558 7bb081f5 Kostas Papadimitriou
        'limit': 1,
559 7bb081f5 Kostas Papadimitriou
        'switch': False
560 bc8bede2 Kostas Papadimitriou
    }
561 bc8bede2 Kostas Papadimitriou
562 d2633501 Kostas Papadimitriou
    @property
563 9d20fe23 Kostas Papadimitriou
    def urls(self):
564 9d20fe23 Kostas Papadimitriou
        urls = super(LocalAuthProvider, self).urls
565 9d20fe23 Kostas Papadimitriou
        urls['change_password'] = reverse('password_change')
566 9d20fe23 Kostas Papadimitriou
        if self.user:
567 9d20fe23 Kostas Papadimitriou
            urls['add'] = reverse('password_change')
568 9d20fe23 Kostas Papadimitriou
        if self._instance:
569 9d20fe23 Kostas Papadimitriou
            urls.update({
570 9d20fe23 Kostas Papadimitriou
                'remove': reverse('remove_auth_provider',
571 9d20fe23 Kostas Papadimitriou
                                  kwargs={'pk': self._instance.pk})
572 9d20fe23 Kostas Papadimitriou
            })
573 9d20fe23 Kostas Papadimitriou
            if 'switch' in urls:
574 9d20fe23 Kostas Papadimitriou
                del urls['switch']
575 9d20fe23 Kostas Papadimitriou
        return urls
576 9d20fe23 Kostas Papadimitriou
577 9d20fe23 Kostas Papadimitriou
    def remove_from_user(self):
578 9d20fe23 Kostas Papadimitriou
        super(LocalAuthProvider, self).remove_from_user()
579 9d20fe23 Kostas Papadimitriou
        self.user.set_unusable_password()
580 9d20fe23 Kostas Papadimitriou
        self.user.save()
581 d2633501 Kostas Papadimitriou
582 74796dd8 Kostas Papadimitriou
583 d2633501 Kostas Papadimitriou
class ShibbolethAuthProvider(AuthProvider):
584 d2633501 Kostas Papadimitriou
    module = 'shibboleth'
585 70e11eaa Sofia Papagiannaki
    login_view = 'astakos.im.views.target.shibboleth.login'
586 9d20fe23 Kostas Papadimitriou
    username_key = 'identifier'
587 d2633501 Kostas Papadimitriou
588 7bb081f5 Kostas Papadimitriou
    policies = {
589 7bb081f5 Kostas Papadimitriou
        'switch': False
590 7bb081f5 Kostas Papadimitriou
    }
591 7bb081f5 Kostas Papadimitriou
592 9d20fe23 Kostas Papadimitriou
    messages = {
593 9d20fe23 Kostas Papadimitriou
        'title': _('Academic'),
594 9d20fe23 Kostas Papadimitriou
        'login_description': _('If you are a student, professor or researcher'
595 9d20fe23 Kostas Papadimitriou
                               ' you can login using your academic account.'),
596 9d20fe23 Kostas Papadimitriou
        'method_details': 'Account: {username}',
597 9d20fe23 Kostas Papadimitriou
        'logout_extra': _('Please close all browser windows to complete '
598 9d20fe23 Kostas Papadimitriou
                          'logout from your Academic account, too.')
599 9d20fe23 Kostas Papadimitriou
    }
600 ca5148f2 Kostas Papadimitriou
601 d2633501 Kostas Papadimitriou
602 c101b32b Kostas Papadimitriou
class TwitterAuthProvider(AuthProvider):
603 c101b32b Kostas Papadimitriou
    module = 'twitter'
604 70e11eaa Sofia Papagiannaki
    login_view = 'astakos.im.views.target.twitter.login'
605 9d20fe23 Kostas Papadimitriou
    username_key = 'provider_info_screen_name'
606 c101b32b Kostas Papadimitriou
607 9d20fe23 Kostas Papadimitriou
    messages = {
608 9d20fe23 Kostas Papadimitriou
        'title': _('Twitter'),
609 9d20fe23 Kostas Papadimitriou
        'method_details': 'Screen name: {username}',
610 9d20fe23 Kostas Papadimitriou
    }
611 c101b32b Kostas Papadimitriou
612 74796dd8 Kostas Papadimitriou
613 74796dd8 Kostas Papadimitriou
class GoogleAuthProvider(AuthProvider):
614 74796dd8 Kostas Papadimitriou
    module = 'google'
615 70e11eaa Sofia Papagiannaki
    login_view = 'astakos.im.views.target.google.login'
616 9d20fe23 Kostas Papadimitriou
    username_key = 'provider_info_email'
617 74796dd8 Kostas Papadimitriou
618 9d20fe23 Kostas Papadimitriou
    messages = {
619 9d20fe23 Kostas Papadimitriou
        'title': _('Google'),
620 9d20fe23 Kostas Papadimitriou
        'method_details': 'Email: {username}',
621 9d20fe23 Kostas Papadimitriou
    }
622 74796dd8 Kostas Papadimitriou
623 74796dd8 Kostas Papadimitriou
624 74796dd8 Kostas Papadimitriou
class LinkedInAuthProvider(AuthProvider):
625 74796dd8 Kostas Papadimitriou
    module = 'linkedin'
626 70e11eaa Sofia Papagiannaki
    login_view = 'astakos.im.views.target.linkedin.login'
627 9d20fe23 Kostas Papadimitriou
    username_key = 'provider_info_email'
628 74796dd8 Kostas Papadimitriou
629 9d20fe23 Kostas Papadimitriou
    messages = {
630 9d20fe23 Kostas Papadimitriou
        'title': _('LinkedIn'),
631 9d20fe23 Kostas Papadimitriou
        'method_details': 'Email: {username}',
632 9d20fe23 Kostas Papadimitriou
    }
633 74796dd8 Kostas Papadimitriou
634 74796dd8 Kostas Papadimitriou
635 9d20fe23 Kostas Papadimitriou
# Utility method
636 9d20fe23 Kostas Papadimitriou
def get_provider(module, user_obj=None, identifier=None, **params):
637 d2633501 Kostas Papadimitriou
    """
638 d2633501 Kostas Papadimitriou
    Return a provider instance from the auth providers registry.
639 d2633501 Kostas Papadimitriou
    """
640 9d20fe23 Kostas Papadimitriou
    if not module in PROVIDERS:
641 9d20fe23 Kostas Papadimitriou
        raise Exception('Invalid auth provider "%s"' % id)
642 d2633501 Kostas Papadimitriou
643 9d20fe23 Kostas Papadimitriou
    return PROVIDERS.get(module)(user_obj, identifier, **params)