Revision 9d20fe23

b/snf-astakos-app/astakos/im/activation_backends.py
222 222
    def _is_preaccepted(self, user):
223 223
        if super(SimpleBackend, self)._is_preaccepted(user):
224 224
            return True
225
        if astakos_settings.MODERATION_ENABLED:
226
            return False
227
        return True
225

  
226
        return user.get_auth_provider().get_automoderate_policy
228 227

  
229 228

  
230 229
class ActivationResult(object):
b/snf-astakos-app/astakos/im/auth_providers.py
31 31
# interpreted as representing official policies, either expressed
32 32
# or implied, of GRNET S.A.
33 33

  
34
import copy
35
import json
36

  
37
from synnefo.lib.ordereddict import OrderedDict
34 38

  
35 39
from django.core.urlresolvers import reverse
36 40
from django.utils.translation import ugettext as _
37
from django.utils.datastructures import SortedDict
41
from django.contrib.auth.models import Group
42
from django import template
38 43

  
39 44
from django.conf import settings
40 45

  
......
42 47
from astakos.im import messages as astakos_messages
43 48

  
44 49
import logging
45
import urllib
46 50

  
47 51
logger = logging.getLogger(__name__)
48 52

  
......
50 54
PROVIDERS = {}
51 55
REQUIRED_PROVIDERS = {}
52 56

  
57

  
53 58
class AuthProviderBase(type):
54 59

  
55 60
    def __new__(cls, name, bases, dct):
......
64 69
        newcls = super(AuthProviderBase, cls).__new__(cls, name, bases, dct)
65 70
        if include:
66 71
            PROVIDERS[type_id] = newcls
67
            if newcls().is_required():
72
            if newcls().get_required_policy:
68 73
                REQUIRED_PROVIDERS[type_id] = newcls
69 74
        return newcls
70 75

  
......
74 79
    __metaclass__ = AuthProviderBase
75 80

  
76 81
    module = None
77
    module_active = False
78 82
    module_enabled = False
79
    one_per_user = True
80
    login_prompt = _('Login using ')
81
    primary_login_prompt = _('Login using ')
82
    login_message = None
83
    logout_message = 'You may still be logged in %(provider)s though. Consider logging out from there too.'
83

  
84
    message_tpls = OrderedDict((
85
        ('title', '{module_title}'),
86
        ('login_title', '{title} LOGIN'),
87
        ('method_prompt', '{title} login'),
88
        ('account_prompt', '{title} account'),
89
        ('signup_title', '{title}'),
90
        ('profile_title', '{title}'),
91
        ('method_details', '{account_prompt}: {identifier}'),
92
        ('primary_login_prompt', 'Login using '),
93
        ('required', '{title} is required. You can assign it '
94
                     'from your profile page'),
95
        ('login_prompt', ''),
96
        ('add_prompt', 'Allows you to login using {title}'),
97
        ('login_extra', ''),
98
        ('username', '{username}'),
99
        ('disabled_for_create', '{title} is not available for signup.'),
100
        ('switch_success', 'Account changed successfully.'),
101
        ('cannot_login', '{title} is not available for login. '
102
                         'Please use one of your other available methods '
103
                         'to login ({available_methods_links}'),
104

  
105
        # icons should end with _icon
106
        ('module_medium_icon', 'im/auth/icons-medium/{module}.png'),
107
        ('module_icon', 'im/auth/icons/{module}.png'))
108
    )
109

  
110
    messages = {}
111
    module_urls = {}
112

  
84 113
    remote_authenticate = True
85 114
    remote_logout_url = None
86
    logout_from_provider_text = None
87
    icon_url = None
88
    icon_medium_url = None
89
    method_prompt = None
90 115

  
91
    def get_message(self, msg, **kwargs):
92
        params = kwargs
93
        params.update({'provider': self.get_title_display})
116
    # templates
117
    primary_login_template = 'im/auth/generic_primary_login.html'
118
    login_template = 'im/auth/generic_login.html'
119
    signup_template = 'im/signup.html'
120
    login_prompt_template = 'im/auth/generic_login_prompt.html'
121
    signup_prompt_template = 'im/auth/signup_prompt.html'
122

  
123
    default_policies = {
124
        'login': True,
125
        'create': True,
126
        'add': True,
127
        'remove': True,
128
        'limit': 1,
129
        'switch': True,
130
        'add_groups': [],
131
        'creation_groups': [],
132
        'required': False,
133
        'automoderate': not astakos_settings.MODERATION_ENABLED
134
    }
135

  
136
    policies = {}
137

  
138
    def __init__(self, user=None, identifier=None, **provider_params):
139
        """
140
        3 ways to initialize (no args, user, user and identifier).
141

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

  
148
        user and identifier: Used to provide details about a user's specific
149
        login method.
150
        >>> p = auth_providers.get_provider('google', identifier='1421421')
151
        >>> # provider (google) details prompt
152
        >>> print p.get_method_details()
153
        "Google account: 1421421"
154
        """
155

  
156
        # handle AnonymousUser instance
157
        self.user = None
158
        if user and hasattr(user, 'pk') and user.pk:
159
            self.user = user
94 160

  
95
        override_msg = getattr(self, 'get_%s_message_display' % msg.lower(), None)
96
        msg = 'AUTH_PROVIDER_%s' % msg
97
        return override_msg or getattr(astakos_messages, msg, msg) % params
161
        self.identifier = identifier
162
        self._instance = None
163
        if 'instance' in provider_params:
164
            self._instance = provider_params['instance']
165
            del provider_params['instance']
166

  
167
        # initialize policies
168
        self.module_policies = copy.copy(self.default_policies)
169
        self.module_policies['automoderate'] = not \
170
            astakos_settings.MODERATION_ENABLED
171
        for policy, value in self.policies.keys():
172
            setting_key = "%s_POLICY" % policy.upper()
173
            if self.has_setting(setting_key):
174
                self.module_policies[policy] = self.get_setting(setting_key)
175

  
176
        # messages cache
177
        self.message_tpls_compiled = OrderedDict()
178

  
179
        # module specific messages
180
        self.message_tpls = OrderedDict(self.message_tpls)
181
        for key, value in self.messages.iteritems():
182
            self.message_tpls[key] = value
183

  
184
        self._provider_details = provider_params
185

  
186
        self.resolve_available_methods = True
187

  
188
    def get_provider_model(self):
189
        from astakos.im.models import AstakosUserAuthProvider as AuthProvider
190
        return AuthProvider
191

  
192
    def remove_from_user(self):
193
        if not self.get_remove_policy:
194
            raise Exception("Provider cannot be removed")
195

  
196
        self._instance.delete()
197

  
198
    def add_to_user(self, **params):
199
        if self._instance:
200
            raise Exception("Cannot add an existing provider")
201

  
202
        create = False
203
        if self.get_user_providers().count() == 0:
204
            create = True
205

  
206
        if create and not self.get_create_policy:
207
            raise Exception("Provider not available for create")
208

  
209
        if not self.get_add_policy:
210
            raise Exception("Provider cannot be added")
211

  
212
        if create:
213
            for group_name in self.get_creation_groups_policy:
214
                group, created = Group.objects.get_or_create(name=group_name)
215
                self.user.groups.add(group)
216

  
217
        for group_name in self.get_add_groups_policy:
218
            group, created = Group.objects.get_or_create(name=group_name)
219
            self.user.groups.add(group)
220

  
221
        if self.identifier:
222
            pending = self.get_provider_model().objects.unverified(
223
                self.module, identifier=self.identifier)
224

  
225
            if pending:
226
                pending._instance.delete()
227

  
228
        create_params = {
229
            'module': self.module,
230
            'info_data': json.dumps(self.provider_details.get('info', {})),
231
            'active': True,
232
            'identifier': self.identifier
233
        }
234
        if 'info' in self.provider_details:
235
            del self.provider_details['info']
236

  
237
        create_params.update(self.provider_details)
238
        create_params.update(params)
239
        return self.user.auth_providers.create(**create_params)
240

  
241
    def __repr__(self):
242
        r = "'%s' module" % self.__class__.__name__
243
        if self.user:
244
            r += ' (user: %s)' % self.user
245
        if self.identifier:
246
            r += ' (identifier: %s)' % self.identifier
247
        return r
248

  
249
    def _message_params(self, **extra_params):
250
        """
251
        Retrieve message formating parameters.
252
        """
253
        params = {'module': self.module, 'module_title': self.module.title()}
254
        if self.identifier:
255
            params['identifier'] = self.identifier
98 256

  
99
    @property
100
    def add_url(self):
101
        return reverse(self.login_view)
257
        if self.user:
258
            for key, val in self.user.__dict__.iteritems():
259
                params["user_%s" % key.lower()] = val
260

  
261
        if self.provider_details:
262
            for key, val in self.provider_details.iteritems():
263
                params["provider_%s" % key.lower()] = val
264

  
265
            if 'info' in self.provider_details:
266
                if isinstance(self.provider_details['info'], basestring):
267
                    self.provider_details['info'] = \
268
                        json.loads(self.provider_details['info'])
269
                for key, val in self.provider_details['info'].iteritems():
270
                   params['provider_info_%s' % key.lower()] = val
271

  
272
        # resolve username, handle unexisting defined username key
273
        if self.user and self.username_key in params:
274
            params['username'] = params[self.username_key]
275
        else:
276
            params['username'] = self.identifier
277

  
278
        if not self.message_tpls_compiled:
279
            for key, message_tpl in self.message_tpls.iteritems():
280
                msg = self.messages.get(key, self.message_tpls.get(key))
281
                override_in_settings = self.get_setting(key)
282
                if override_in_settings is not None:
283
                    msg = override_in_settings
284
                try:
285
                    self.message_tpls_compiled[key] = msg.format(**params)
286
                    params.update(self.message_tpls_compiled)
287
                except KeyError, e:
288
                    continue
289
        else:
290
            params.update(self.message_tpls_compiled)
291

  
292
        for key, value in self.urls.iteritems():
293
            params['%s_url' % key] = value
294

  
295
        if self.user and self.resolve_available_methods:
296
            available_providers = self.user.get_enabled_auth_providers()
297
            for p in available_providers:
298
                p.resolve_available_methods = False
299
                if p.module == self.module and p.identifier == self.identifier:
300
                    available_providers.remove(p)
301

  
302
            get_msg = lambda p: p.get_method_prompt_msg
303
            params['available_methods'] = \
304
                ','.join(map(get_msg, available_providers))
305

  
306
            get_msg = lambda p: "<a href='%s'>%s</a>" % \
307
                (p.get_method_prompt_msg, p.get_login_url)
308

  
309
            params['available_methods_links'] = \
310
                ','.join(map(get_msg, available_providers))
311

  
312
        params.update(extra_params)
313
        return params
314

  
315
    def get_template(self, tpl):
316
        tpls = ['im/auth/%s_%s.html' % (self.module, tpl),
317
                getattr(self, '%s_template' % tpl)]
318
        found = None
319
        for tpl in tpls:
320
            try:
321
                found = template.loader.get_template(tpl)
322
                return tpl
323
            except template.TemplateDoesNotExist:
324
                continue
325
        if not found:
326
            raise template.TemplateDoesNotExist
327
        return tpl
328

  
329
    def get_username(self):
330
        return self.get_username_msg
331

  
332
    def get_user_providers(self):
333
        return self.user.auth_providers.active()
334

  
335
    def get_user_module_providers(self):
336
        return self.user.auth_providers.active().filter(module=self.module)
337

  
338
    def get_existing_providers(self):
339
        return ""
340

  
341
    def verified_exists(self):
342
        return self.get_provider_model().objects.verified(
343
            self.module, identifier=self.identifier)
344

  
345
    def get_user_policy(self, policy, default=None):
346

  
347
        if policy == 'switch' and default and not self.get_add_policy:
348
            return not self.get_policy('remove')
349

  
350
        if not self.user:
351
            return default
352

  
353
        if policy == 'remove' and default is True:
354
            return self.get_user_providers().count() > 1
355

  
356
        if policy == 'add' and default is True:
357
            limit = self.get_policy('limit')
358
            if limit <= self.get_user_module_providers().count():
359
                return False
360

  
361
            if self.identifier:
362
                if self.verified_exists():
363
                    return False
364

  
365
        return default
366

  
367
    def get_user_policies(self):
368
        from astakos.im.models import AuthProviderPolicyProfile
369
        return AuthProviderPolicyProfile.objects.for_user(self.user,
370
                                                          self.module)
371

  
372
    def get_policy(self, policy):
373
        module_default = self.module_policies.get(policy)
374
        settings_key = '%s_POLICY' % policy.upper()
375
        settings_default = self.get_setting(settings_key, module_default)
376

  
377
        if self.user:
378
            user_policies = self.get_user_policies()
379
            settings_default = user_policies.get(policy, settings_default)
380

  
381
        return self.get_user_policy(policy, settings_default)
382

  
383
    def get_message(self, msg, **extra_params):
384
        """
385
        Retrieve an auth provider message
386
        """
387
        if msg.endswith('_msg'):
388
            msg = msg.replace('_msg', '')
389
        params = self._message_params(**extra_params)
390

  
391
        # is message ???
392
        tpl = self.message_tpls_compiled.get(msg.lower(), None)
393
        if not tpl:
394
            msg_key = 'AUTH_PROVIDER_%s' % msg.upper()
395
            try:
396
                tpl = getattr(astakos_messages, msg_key)
397
            except AttributeError, e:
398
                try:
399
                    msg_key = msg.upper()
400
                    tpl = getattr(astakos_messages, msg_key)
401
                except AttributeError, e:
402
                    tpl = ''
403

  
404
        in_settings = self.get_setting(msg)
405
        if in_settings:
406
            tpl = in_settings
407

  
408
        return tpl.format(**params)
102 409

  
103 410
    @property
104
    def provider_details(self):
411
    def urls(self):
412
        urls = {
413
            'login': reverse(self.login_view),
414
            'add': reverse(self.login_view),
415
            'profile': reverse('edit_profile'),
416
        }
105 417
        if self.user:
106
            if self.identifier:
107
                self._provider_details = \
108
                    self.user.get_auth_providers().get(module=self.module,
109
                                                       identifier=self.identifier).__dict__
110
            else:
111
                self._provider_details = self.user.get(module=self.module).__dict__
112
        return self._provider_details
418
            urls.update({
419
                'resend_activation': self.user.get_resend_activation_url(),
420
            })
421
        if self.identifier and self._instance:
422
            urls.update({
423
                'switch': reverse(self.login_view) + '?switch_from=%d' % \
424
                    self._instance.pk,
425
                'remove': reverse('remove_auth_provider',
426
                                  kwargs={'pk': self._instance.pk})
427
            })
428
        urls.update(self.module_urls)
429
        return urls
430

  
431
    def get_setting_key(self, name):
432
        return 'ASTAKOS_AUTH_PROVIDER_%s_%s' % (self.module.upper(),
433
                                                name.upper())
434

  
435
    def get_global_setting_key(self, name):
436
        return 'ASTAKOS_AUTH_PROVIDERS_%s' % name.upper()
437

  
438
    def has_global_setting(self, name):
439
        return hasattr(settings, self.get_global_setting_key(name))
440

  
441
    def has_setting(self, name):
442
        return hasattr(settings, self.get_setting_key(name))
113 443

  
114
    def __init__(self, user=None, identifier=None, provider_details=None):
115
        self.user = user
116
        self.identifier = identifier
444
    def get_setting(self, name, default=None):
445
        attr = self.get_setting_key(name)
446
        if not self.has_setting(name):
447
            return self.get_global_setting(name, default)
448
        return getattr(settings, attr, default)
117 449

  
118
        self._provider_details = None
119
        if provider_details:
120
            self._provider_details = provider_details
121

  
122
        for tpl in ['login_prompt', 'login', 'signup_prompt']:
123
            tpl_name = '%s_%s' % (tpl, 'template')
124
            override = self.get_setting(tpl_name)
125
            if override:
126
                setattr(self, tpl_name, override)
127

  
128
        for key in ['one_per_user']:
129
            override = self.get_setting(key)
130
            if override != None:
131
                setattr(self, key, override)
132

  
133
        self.login_message = self.login_message or self.get_title_display
134
        if self.logout_message and "%" in self.logout_message:
135
            logout_text_display = self.logout_from_provider_text or 'at %s' % self.get_title_display
136
            self.logout_message = self.logout_message % {'provider':
137
                                                         logout_text_display}
138
        else:
139
            self.logout_message = self.logout_message or ''
450
    def get_global_setting(self, name, default=None):
451
        attr = self.get_global_setting_key(name)
452
        if not self.has_global_setting(name):
453
            return default
454
        return getattr(settings, attr, default)
455

  
456
    @property
457
    def provider_details(self):
458
        if self._provider_details:
459
            return self._provider_details
140 460

  
141
        if not self.icon_url:
142
            self.icon_url = '%s%s' % (settings.MEDIA_URL, 'im/auth/icons/%s.png' %
143
                                       self.module.lower())
461
        self._provider_details = {}
144 462

  
145
        if not self.icon_medium_url:
146
            self.icon_medium_url = '%s%s' % (settings.MEDIA_URL, 'im/auth/icons-medium/%s.png' %
147
                                       self.module.lower())
463
        if self._instance:
464
            self._provider_details = self._instance.__dict__
148 465

  
149
        if not self.method_prompt:
150
            self.method_prompt = _('%s login method') % self.get_title_display
466
        if self.user and self.identifier:
467
            if self.identifier:
468
                try:
469
                    self._provider_details = \
470
                        self.user.get_auth_providers().get(
471
                            module=self.module,
472
                            identifier=self.identifier).__dict__
473
                except Exception:
474
                    return {}
475
        return self._provider_details
151 476

  
152 477
    def __getattr__(self, key):
153 478
        if not key.startswith('get_'):
154 479
            return super(AuthProvider, self).__getattribute__(key)
155 480

  
156
        if key.endswith('_display') or key.endswith('template'):
157
            attr = key.replace('_display', '').replace('get_','')
158
            settings_attr = self.get_setting(attr.upper())
159
            if not settings_attr:
160
                return getattr(self, attr)
161
            return _(settings_attr)
162
        else:
163
            return super(AuthProvider, self).__getattr__(key)
164

  
165
    def get_logout_message(self):
166
        content = ''
167
        if self.remote_logout_url:
168
            content = '<a href="%s" title="Logout from %%s"></a>' % self.remote_logou_url
169
        return content % (self.get_logout_message_display % self.get_title_display)
170

  
171
    def get_setting(self, name, default=None):
172
        attr = 'ASTAKOS_AUTH_PROVIDER_%s_%s' % (self.module.upper(), name.upper())
173
        attr_sec = 'ASTAKOS_%s_%s' % (self.module.upper(), name.upper())
174
        if not hasattr(settings, attr):
175
            return getattr(settings, attr_sec, default)
481
        key = key.replace('get_', '')
482
        if key.endswith('_msg'):
483
            return self.get_message(key)
176 484

  
177
        return getattr(settings, attr, default)
485
        if key.endswith('_policy'):
486
            return self.get_policy(key.replace('_policy', ''))
178 487

  
179
    def is_available_for_remove(self):
180
        return self.is_active() and self.get_setting('CAN_REMOVE', True)
488
        if key.endswith('_url'):
489
            key = key.replace('_url', '')
490
            return self.urls.get(key)
181 491

  
182
    def is_available_for_login(self):
183
        """ A user can login using authentication provider"""
184
        return self.is_active() and self.get_setting('CAN_LOGIN',
185
                                                     self.is_active())
492
        if key.endswith('_icon'):
493
            key = key.replace('_msg', '_icon')
494
            return settings.MEDIA_URL + self.get_message(key)
186 495

  
187
    def is_available_for_create(self):
188
        """ A user can create an account using this provider"""
189
        return self.is_active() and self.get_setting('CAN_CREATE',
190
                                                   self.is_active())
496
        if key.endswith('_setting'):
497
            key = key.replace('_setting', '')
498
            return self.get_message(key)
191 499

  
192
    def is_available_for_add(self):
193
        """ A user can assign provider authentication method"""
194
        return self.is_active() and self.get_setting('CAN_ADD',
195
                                                   self.is_active())
500
        if key.endswith('_template'):
501
            key = key.replace('_template', '')
502
            return self.get_template(key)
196 503

  
197
    def is_required(self):
198
        """Provider required (user cannot remove the last one)"""
199
        return self.is_active() and self.get_setting('REQUIRED', False)
504
        return super(AuthProvider, self).__getattribute__(key)
200 505

  
201 506
    def is_active(self):
202
        return self.module in astakos_settings.IM_MODULES
507
        return self.module_enabled
203 508

  
204 509

  
205 510
class LocalAuthProvider(AuthProvider):
206 511
    module = 'local'
207
    title = _('Local password')
208
    description = _('Create a local password for your account')
209
    add_prompt =  _('Enable Classic login for your account')
210
    details_tpl = _('Username: %(username)s')
211
    login_prompt = _('Classic login (username/password)')
212
    signup_prompt = _('New to ~okeanos ?')
213
    signup_link_prompt = _('create an account now')
512

  
214 513
    login_view = 'password_change'
215 514
    remote_authenticate = False
216
    logout_message = ''
217

  
218
    one_per_user = True
515
    username_key = 'user_email'
219 516

  
220
    login_template = 'im/auth/local_login_form.html'
221
    login_prompt_template = 'im/auth/local_login_prompt.html'
222
    signup_prompt_template = 'im/auth/local_signup_prompt.html'
517
    messages = {
518
        'title': _('Classic'),
519
        'login_prompt': _('Classic login (username/password)'),
520
        'login_success': _('Logged in successfully.'),
521
        'method_details': 'Username: {username}',
522
        'logout_success_extra': ' '
523
    }
223 524

  
224 525
    @property
225
    def extra_actions(self):
226
        return [(_('Change password'), reverse('password_change')), ]
526
    def urls(self):
527
        urls = super(LocalAuthProvider, self).urls
528
        urls['change_password'] = reverse('password_change')
529
        if self.user:
530
            urls['add'] = reverse('password_change')
531
        if self._instance:
532
            urls.update({
533
                'remove': reverse('remove_auth_provider',
534
                                  kwargs={'pk': self._instance.pk})
535
            })
536
            if 'switch' in urls:
537
                del urls['switch']
538
        return urls
539

  
540
    def remove_from_user(self):
541
        super(LocalAuthProvider, self).remove_from_user()
542
        self.user.set_unusable_password()
543
        self.user.save()
544
        for group_name in self.get_add_groups_policy:
545
            group = Group.objects.get(name=group_name)
546
            self.user.groups.remove(group)
227 547

  
228 548

  
229 549
class ShibbolethAuthProvider(AuthProvider):
230 550
    module = 'shibboleth'
231
    title = _('Academic account')
232
    add_prompt = _('Enable Academic login for your account')
233
    details_tpl = _('Identifier: %(identifier)s')
234
    user_title = _('Academic account (%(identifier)s)')
235
    primary_login_prompt = _('If you are a student, professor or researcher you '
236
                             'can login using your academic account.')
237 551
    login_view = 'astakos.im.target.shibboleth.login'
552
    username_key = 'identifier'
238 553

  
239
    login_template = 'im/auth/shibboleth_login.html'
240
    login_prompt_template = 'im/auth/third_party_provider_generic_login_prompt.html'
241
    logout_from_provider_text = 'Please close all browser windows to complete logout from your Academic account, too.'
242
    logout_message = logout_from_provider_text
243

  
244
    method_prompt = _('Academic account')
554
    messages = {
555
        'title': _('Academic'),
556
        'login_description': _('If you are a student, professor or researcher'
557
                               ' you can login using your academic account.'),
558
        'method_details': 'Account: {username}',
559
        'logout_extra': _('Please close all browser windows to complete '
560
                          'logout from your Academic account, too.')
561
    }
245 562

  
246 563

  
247 564
class TwitterAuthProvider(AuthProvider):
248 565
    module = 'twitter'
249
    title = _('Twitter')
250
    add_prompt = _('Enable Twitter login for your account')
251
    details_tpl = _('Username: %(info_screen_name)s')
252
    user_title = _('Twitter (%(info_screen_name)s)')
253 566
    login_view = 'astakos.im.target.twitter.login'
567
    username_key = 'provider_info_screen_name'
254 568

  
255
    login_template = 'im/auth/third_party_provider_generic_login.html'
256
    login_prompt_template = 'im/auth/third_party_provider_generic_login_prompt.html'
569
    messages = {
570
        'title': _('Twitter'),
571
        'method_details': 'Screen name: {username}',
572
    }
257 573

  
258 574

  
259 575
class GoogleAuthProvider(AuthProvider):
260 576
    module = 'google'
261
    title = _('Google')
262
    add_prompt = _('Enable Google login for your account')
263
    details_tpl = _('Email: %(info_email)s')
264
    user_title = _('Google (%(info_email)s)')
265 577
    login_view = 'astakos.im.target.google.login'
578
    username_key = 'provider_info_email'
266 579

  
267
    login_template = 'im/auth/third_party_provider_generic_login.html'
268
    login_prompt_template = 'im/auth/third_party_provider_generic_login_prompt.html'
580
    messages = {
581
        'title': _('Google'),
582
        'method_details': 'Email: {username}',
583
    }
269 584

  
270 585

  
271 586
class LinkedInAuthProvider(AuthProvider):
272 587
    module = 'linkedin'
273
    title = _('LinkedIn')
274
    add_prompt = _('Enable LinkedIn login for your account')
275
    details_tpl = _('Email: %(info_emailAddress)s')
276
    user_title = _('LinkedIn (%(info_emailAddress)s)')
277 588
    login_view = 'astakos.im.target.linkedin.login'
589
    username_key = 'provider_info_email'
278 590

  
279
    login_template = 'im/auth/third_party_provider_generic_login.html'
280
    login_prompt_template = 'im/auth/third_party_provider_generic_login_prompt.html'
591
    messages = {
592
        'title': _('LinkedIn'),
593
        'method_details': 'Email: {username}',
594
    }
281 595

  
282 596

  
283
def get_provider(id, user_obj=None, default=None, identifier=None, provider_details={}):
597
# Utility method
598
def get_provider(module, user_obj=None, identifier=None, **params):
284 599
    """
285 600
    Return a provider instance from the auth providers registry.
286 601
    """
287
    if not id in PROVIDERS:
288
        raise Exception('Invalid auth provider requested "%s"' % id)
289

  
290
    return PROVIDERS.get(id, default)(user_obj, identifier, provider_details)
602
    if not module in PROVIDERS:
603
        raise Exception('Invalid auth provider "%s"' % id)
291 604

  
605
    return PROVIDERS.get(module)(user_obj, identifier, **params)
b/snf-astakos-app/astakos/im/forms.py
271 271
            terms_link_html = '<a href="%s" target="_blank">%s</a>' \
272 272
                % (reverse('latest_terms'), _("the terms"))
273 273
            self.fields['has_signed_terms'].label = \
274
                    mark_safe("I agree with %s" % terms_link_html)
274
                mark_safe("I agree with %s" % terms_link_html)
275 275

  
276 276
    def clean_email(self):
277 277
        email = self.cleaned_data['email']
278 278
        if not email:
279 279
            raise forms.ValidationError(_(astakos_messages.REQUIRED_FIELD))
280 280
        if reserved_verified_email(email):
281
            provider = auth_providers.get_provider(self.request.REQUEST.get('provider', 'local'))
282
            extra_message = _(astakos_messages.EXISTING_EMAIL_THIRD_PARTY_NOTIFICATION) % \
283
                    (provider.get_title_display, reverse('edit_profile'))
281
            provider_id = self.request.REQUEST.get('provider', 'local')
282
            provider = auth_providers.get_provider(provider_id)
283
            extra_message = provider.get_add_to_existing_account_msg
284 284

  
285
            raise forms.ValidationError(_(astakos_messages.EMAIL_USED) + ' ' + \
286
                                        extra_message)
285
            raise forms.ValidationError(mark_safe(_(astakos_messages.EMAIL_USED) + ' ' +
286
                                        extra_message))
287 287
        return email
288 288

  
289 289
    def clean_has_signed_terms(self):
......
294 294

  
295 295
    def post_store_user(self, user, request):
296 296
        pending = PendingThirdPartyUser.objects.get(
297
                                token=request.POST.get('third_party_token'),
298
                                third_party_identifier= \
299
                            self.cleaned_data.get('third_party_identifier'))
300
        return user.add_pending_auth_provider(pending)
297
            token=request.POST.get('third_party_token'),
298
            third_party_identifier=
299
            self.cleaned_data.get('third_party_identifier'))
300
        provider = pending.get_provider(user)
301
        provider.add_to_user()
302
        pending.delete()
301 303

  
302 304
    def save(self, commit=True):
303 305
        user = super(ThirdPartyUserCreationForm, self).save(commit=False)
......
406 408
            try:
407 409
                user = AstakosUser.objects.get_by_identifier(username)
408 410
                if not user.has_auth_provider('local'):
409
                    provider = auth_providers.get_provider('local')
411
                    provider = auth_providers.get_provider('local', user)
410 412
                    raise forms.ValidationError(
411
                        _(provider.get_message('NOT_ACTIVE_FOR_USER')))
413
                        provider.get_login_disabled_msg)
412 414
            except AstakosUser.DoesNotExist:
413 415
                pass
414 416

  
......
418 420
            if self.user_cache is None:
419 421
                raise
420 422
            if not self.user_cache.is_active:
421
                raise forms.ValidationError(self.user_cache.get_inactive_message())
423
                msg = self.user_cache.get_inactive_message('local')
424
                raise forms.ValidationError(msg)
422 425
            if self.request:
423 426
                if not self.request.session.test_cookie_worked():
424 427
                    raise
......
505 508
    clean_email: to handle local auth provider checks
506 509
    """
507 510
    def clean_email(self):
508
        email = super(ExtendedPasswordResetForm, self).clean_email()
511
        # we override the default django auth clean_email to provide more
512
        # detailed messages in case of inactive users
513
        email = self.cleaned_data['email']
509 514
        try:
510 515
            user = AstakosUser.objects.get_by_identifier(email)
511

  
516
            self.users_cache = [user]
512 517
            if not user.is_active:
513
                raise forms.ValidationError(_(astakos_messages.ACCOUNT_INACTIVE))
518
                raise forms.ValidationError(user.get_inactive_message('local'))
514 519

  
520
            provider = auth_providers.get_provider('local', user)
515 521
            if not user.has_usable_password():
516
                provider = auth_providers.get_provider('local')
517
                available_providers = user.auth_providers.all()
518
                available_providers = ",".join(p.settings.get_title_display for p in \
519
                                                   available_providers)
520
                message = astakos_messages.UNUSABLE_PASSWORD % \
521
                    (provider.get_method_prompt_display, available_providers)
522
                raise forms.ValidationError(message)
522
                msg = provider.get_unusable_password_msg
523
                raise forms.ValidationError(msg)
523 524

  
524 525
            if not user.can_change_password():
525
                raise forms.ValidationError(_(astakos_messages.AUTH_PROVIDER_CANNOT_CHANGE_PASSWORD))
526
        except AstakosUser.DoesNotExist, e:
526
                msg = provider.get_cannot_change_password_msg
527
                raise forms.ValidationError(msg)
528

  
529
        except AstakosUser.DoesNotExist:
527 530
            raise forms.ValidationError(_(astakos_messages.EMAIL_UNKNOWN))
528 531
        return email
529 532

  
......
661 664
            self.user = AstakosUser.objects.get(id=self.user.id)
662 665
            if NEWPASSWD_INVALIDATE_TOKEN or self.cleaned_data.get('renew'):
663 666
                self.user.renew_token()
664
            #self.user.flush_sessions()
665
            if not self.user.has_auth_provider('local'):
666
                self.user.add_auth_provider('local', auth_backend='astakos')
667

  
668
            provider = auth_providers.get_provider('local', self.user)
669
            if provider.get_add_policy:
670
                provider.add_to_user()
667 671

  
668 672
        except BaseException, e:
669 673
            logger.exception(e)
b/snf-astakos-app/astakos/im/management/commands/user-auth-policy-add.py
1
# Copyright 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
import string
35

  
36
from optparse import make_option
37

  
38
from django.core.management.base import BaseCommand, CommandError
39

  
40
from astakos.im.models import AuthProviderPolicyProfile as Profile
41

  
42
option_list = list(BaseCommand.option_list) + [
43
    make_option('--update',
44
                action='store_true',
45
                dest='update',
46
                default=False,
47
                help="Update an existing profile."),
48
    make_option('--exclusive',
49
                action='store_true',
50
                dest='exclusive',
51
                default=False,
52
                help="Apply policies to all authentication providers "
53
                     "except the one provided."),
54
]
55

  
56
POLICIES = ['add', 'remove', 'create', 'login', 'limit', 'required',
57
            'automoderate']
58

  
59
for p in POLICIES:
60
    option_list.append(make_option('--unset-%s-policy' % p,
61
                                   action='store_true',
62
                                   dest='unset_policy_%s' % p,
63
                                   help="Unset %s policy (only when --update)"
64
                                   % p.title()))
65
    option_list.append(make_option('--%s-policy' % p,
66
                                   action='store',
67
                                   dest='policy_%s' % p,
68
                                   help="%s policy" % p.title()))
69

  
70

  
71
class Command(BaseCommand):
72
    args = "<name> <provider_name>"
73
    help = "Create a new authentication provider policy profile"
74
    option_list = option_list
75

  
76
    def handle(self, *args, **options):
77
        if len(args) < 2:
78
            raise CommandError("Invalid number of arguments")
79

  
80
        profile = None
81
        update = options.get('update')
82
        name = args[0].strip()
83
        provider = args[1].strip()
84

  
85
        if Profile.objects.filter(name=name).count():
86
            if update:
87
                profile = Profile.objects.get(name=name)
88
            else:
89
                raise CommandError("Profile with the same name already exists")
90

  
91
        if not profile:
92
            profile = Profile()
93

  
94
        profile.name = name
95
        profile.provider = provider
96
        profile.is_exclusive = options.get('exclusive')
97

  
98
        for policy, value in options.iteritems():
99
            if policy.startswith('policy_') and value is not None:
100
                if isinstance(value, basestring) and value[0] in string.digits:
101
                    value = int(value)
102
                if value == 'False' or value == '0':
103
                    value = False
104
                if value == 'True' or value == '1':
105
                    value = True
106
                setattr(profile, policy, value)
107

  
108
            if update and policy.startswith('unset_'):
109
                policy = policy.replace('unset_', '')
110
                setattr(profile, policy, None)
111

  
112

  
113
        profile.save()
114
        if update:
115
            print "Profile updated"
116
        else:
117
            print "Profile stored"
b/snf-astakos-app/astakos/im/management/commands/user-auth-policy-list.py
1
# Copyright 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 optparse import make_option
35

  
36
from django.core.management.base import NoArgsCommand
37

  
38
from astakos.im.models import AuthProviderPolicyProfile
39

  
40
from ._common import format
41

  
42

  
43
class Command(NoArgsCommand):
44
    help = "List existing authentication provider policy profiles"
45

  
46
    option_list = NoArgsCommand.option_list + (
47
        make_option('-c',
48
                    action='store_true',
49
                    dest='csv',
50
                    default=False,
51
                    help="Use pipes to separate values"),
52
    )
53

  
54
    def handle_noargs(self, **options):
55
        profiles = AuthProviderPolicyProfile.objects.all()
56

  
57
        labels = ['id', 'name', 'provider', 'exclusive', 'groups', 'users']
58
        columns = [3, 20, 13, 7, 50, 50]
59

  
60
        if not options['csv']:
61
            line = ' '.join(l.rjust(w) for l, w in zip(labels, columns))
62
            self.stdout.write(line + '\n')
63
            sep = '-' * len(line)
64
            self.stdout.write(sep + '\n')
65

  
66
        for profile in profiles:
67
            id = str(profile.pk)
68
            name = profile.name
69
            provider = profile.provider
70
            exclusive = str(profile.is_exclusive)
71
            groups = ",".join([g.name for g in profile.groups.all()])
72
            users = ",".join([u.email for u in profile.users.all()])
73

  
74
            field_values = [id, name, provider, exclusive, groups, users]
75
            fields = (format(elem) for elem in field_values)
76

  
77
            if options['csv']:
78
                line = '|'.join(fields)
79
            else:
80
                line = ' '.join(f.rjust(w) for f, w in zip(fields, columns))
81

  
82
            self.stdout.write(line + '\n')
83

  
b/snf-astakos-app/astakos/im/management/commands/user-auth-policy-remove.py
1
# Copyright 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 django.core.management.base import BaseCommand, CommandError
35

  
36
from astakos.im.models import AuthProviderPolicyProfile as Profile
37

  
38

  
39
class Command(BaseCommand):
40
    args = "<profile_name>"
41
    help = "Remove an authentication provider policy"
42

  
43
    option_list = BaseCommand.option_list + ()
44

  
45
    def handle(self, *args, **options):
46
        if len(args) != 1:
47
            raise CommandError("Invalid number of arguments")
48

  
49
        try:
50
            profile = Profile.objects.get(name=args[0])
51
            profile.delete()
52
        except Profile.DoesNotExist:
53
            raise CommandError("Invalid profile name")
b/snf-astakos-app/astakos/im/management/commands/user-auth-policy-set.py
1
# Copyright 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 optparse import make_option
35

  
36
from django.db import transaction
37
from django.core.management.base import BaseCommand, CommandError
38

  
39
from astakos.im.models import AuthProviderPolicyProfile as Profile
40
from astakos.im.models import AstakosUser, Group
41

  
42
option_list = BaseCommand.option_list + (
43
    make_option('--group',
44
                action='append',
45
                dest='groups',
46
                default=[],
47
                help="Assign profile to the provided group id. Option may "
48
                     "be used more than once."),
49
    make_option('--user',
50
                action='append',
51
                dest='users',
52
                default=[],
53
                help="Assign profile to the provided user id. Option may "
54
                     "be used more than once.")
55
)
56

  
57

  
58
@transaction.commit_on_success
59
def update_profile(profile, users, groups):
60
    profile.groups.all().delete()
61
    profile.users.all().delete()
62
    profile.groups.add(*groups)
63
    profile.users.add(*users)
64

  
65

  
66
class Command(BaseCommand):
67
    args = "<name> <provider_name>"
68
    help = "Assign an existing authentication provider policy profile to " + \
69
           "a user or group. All previously set "
70
    option_list = option_list
71

  
72
    def handle(self, *args, **options):
73
        if len(args) < 1:
74
            raise CommandError("Invalid number of arguments")
75

  
76
        name = args[0].strip()
77
        try:
78
            profile = Profile.objects.get(name=name)
79
        except Profile.DoesNotExist:
80
            raise CommandError("Invalid profile name")
81

  
82
        users = []
83
        try:
84
            users = [AstakosUser.objects.get(pk=int(pk)) for pk in
85
                     options.get('users')]
86
        except AstakosUser.DoesNotExist:
87
            raise CommandError("Invalid user id")
88

  
89
        groups = []
90
        try:
91
            groups = [Group.objects.get(pk=int(pk)) for pk in
92
                      options.get('groups')]
93
        except Group.DoesNotExist:
94
            raise CommandError("Invalid group id")
95

  
96
        update_profile(profile, users, groups)
b/snf-astakos-app/astakos/im/management/commands/user-auth-policy-show.py
1
# Copyright 2012, 2013 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 django.core.management.base import BaseCommand, CommandError
35

  
36
from astakos.im.models import AuthProviderPolicyProfile as Profile
37
from synnefo.lib.ordereddict import OrderedDict
38

  
39
from ._common import format
40

  
41
import uuid
42

  
43

  
44
class Command(BaseCommand):
45
    args = "<profile_name>"
46
    help = "Show authentication provider profile details"
47

  
48
    def handle(self, *args, **options):
49
        if len(args) != 1:
50
            raise CommandError("Please profile name")
51

  
52
        try:
53
            profile = Profile.objects.get(name=args[0])
54
        except Profile.DoesNotExist:
55
            raise CommandError("Profile does not exist")
56

  
57
        kv = OrderedDict(
58
            [
59
                ('id', profile.id),
60
                ('is active', str(profile.active)),
61
                ('name', profile.name),
62
                ('is exclusive', profile.is_exclusive),
63
                ('policies', profile.policies),
64
                ('groups', profile.groups.all()),
65
                ('users', profile.users.all())
66
            ])
67

  
68
        self.stdout.write(format(kv))
69
        self.stdout.write('\n')
b/snf-astakos-app/astakos/im/management/commands/user-group-add.py
1
# Copyright 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 django.core.management.base import BaseCommand, CommandError
35

  
36
from astakos.im.models import Group
37

  
38

  
39
class Command(BaseCommand):
40
    args = "<group name>"
41
    help = "Create a group with the given name"
42

  
43
    option_list = BaseCommand.option_list + ()
44

  
45
    def handle(self, *args, **options):
46
        if len(args) != 1:
47
            raise CommandError("Invalid number of arguments")
48

  
49
        Group.objects.get_or_create(name=args[0].strip())
50
        print "Group created"
b/snf-astakos-app/astakos/im/management/commands/user-group-list.py
1
# Copyright 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 optparse import make_option
35

  
36
from django.core.management.base import NoArgsCommand
37

  
38
from django.db.models import Count
39
from astakos.im.models import Group
40

  
41
from ._common import format
42

  
43

  
44
class Command(NoArgsCommand):
45
    help = "List available groups"
46

  
47
    option_list = NoArgsCommand.option_list + (
48
        make_option('-c',
49
                    action='store_true',
50
                    dest='csv',
51
                    default=False,
52
                    help="Use pipes to separate values"),
53
    )
54

  
55
    def handle_noargs(self, **options):
56
        objects = Group.objects.annotate(
57
            users_count=Count('user')).order_by('id')
58

  
59
        labels = ['id', 'name', 'users count']
60
        columns = [3, 40, 20]
61

  
62
        if not options['csv']:
63
            line = ' '.join(l.rjust(w) for l, w in zip(labels, columns))
64
            self.stdout.write(line + '\n')
65
            sep = '-' * len(line)
66
            self.stdout.write(sep + '\n')
67

  
68
        for group in objects:
69
            id = str(group.pk)
70
            name = str(group.name)
71
            user_count = str(group.users_count)
72
            field_values = [id, name, user_count]
73
            fields = (format(elem) for elem in field_values)
74

  
75
            if options['csv']:
76
                line = '|'.join(fields)
77
            else:
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff