##// END OF EJS Templates
auth-plugins: updated display names of plugins, and root resource.
marcink -
r3234:83285ea3 default
parent child Browse files
Show More
@@ -1,143 +1,143 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2018 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 """
21 """
22 RhodeCode authentication plugin for built in internal auth
22 RhodeCode authentication plugin for built in internal auth
23 """
23 """
24
24
25 import logging
25 import logging
26
26
27 from rhodecode.translation import _
27 from rhodecode.translation import _
28
28
29 from rhodecode.authentication.base import RhodeCodeAuthPluginBase, hybrid_property
29 from rhodecode.authentication.base import RhodeCodeAuthPluginBase, hybrid_property
30 from rhodecode.authentication.routes import AuthnPluginResourceBase
30 from rhodecode.authentication.routes import AuthnPluginResourceBase
31 from rhodecode.lib.utils2 import safe_str
31 from rhodecode.lib.utils2 import safe_str
32 from rhodecode.model.db import User
32 from rhodecode.model.db import User
33
33
34 log = logging.getLogger(__name__)
34 log = logging.getLogger(__name__)
35
35
36
36
37 def plugin_factory(plugin_id, *args, **kwds):
37 def plugin_factory(plugin_id, *args, **kwds):
38 plugin = RhodeCodeAuthPlugin(plugin_id)
38 plugin = RhodeCodeAuthPlugin(plugin_id)
39 return plugin
39 return plugin
40
40
41
41
42 class RhodecodeAuthnResource(AuthnPluginResourceBase):
42 class RhodecodeAuthnResource(AuthnPluginResourceBase):
43 pass
43 pass
44
44
45
45
46 class RhodeCodeAuthPlugin(RhodeCodeAuthPluginBase):
46 class RhodeCodeAuthPlugin(RhodeCodeAuthPluginBase):
47
47
48 def includeme(self, config):
48 def includeme(self, config):
49 config.add_authn_plugin(self)
49 config.add_authn_plugin(self)
50 config.add_authn_resource(self.get_id(), RhodecodeAuthnResource(self))
50 config.add_authn_resource(self.get_id(), RhodecodeAuthnResource(self))
51 config.add_view(
51 config.add_view(
52 'rhodecode.authentication.views.AuthnPluginViewBase',
52 'rhodecode.authentication.views.AuthnPluginViewBase',
53 attr='settings_get',
53 attr='settings_get',
54 renderer='rhodecode:templates/admin/auth/plugin_settings.mako',
54 renderer='rhodecode:templates/admin/auth/plugin_settings.mako',
55 request_method='GET',
55 request_method='GET',
56 route_name='auth_home',
56 route_name='auth_home',
57 context=RhodecodeAuthnResource)
57 context=RhodecodeAuthnResource)
58 config.add_view(
58 config.add_view(
59 'rhodecode.authentication.views.AuthnPluginViewBase',
59 'rhodecode.authentication.views.AuthnPluginViewBase',
60 attr='settings_post',
60 attr='settings_post',
61 renderer='rhodecode:templates/admin/auth/plugin_settings.mako',
61 renderer='rhodecode:templates/admin/auth/plugin_settings.mako',
62 request_method='POST',
62 request_method='POST',
63 route_name='auth_home',
63 route_name='auth_home',
64 context=RhodecodeAuthnResource)
64 context=RhodecodeAuthnResource)
65
65
66 def get_display_name(self):
66 def get_display_name(self):
67 return _('Rhodecode')
67 return _('RhodeCode Internal')
68
68
69 @hybrid_property
69 @hybrid_property
70 def name(self):
70 def name(self):
71 return "rhodecode"
71 return "rhodecode"
72
72
73 def user_activation_state(self):
73 def user_activation_state(self):
74 def_user_perms = User.get_default_user().AuthUser().permissions['global']
74 def_user_perms = User.get_default_user().AuthUser().permissions['global']
75 return 'hg.register.auto_activate' in def_user_perms
75 return 'hg.register.auto_activate' in def_user_perms
76
76
77 def allows_authentication_from(
77 def allows_authentication_from(
78 self, user, allows_non_existing_user=True,
78 self, user, allows_non_existing_user=True,
79 allowed_auth_plugins=None, allowed_auth_sources=None):
79 allowed_auth_plugins=None, allowed_auth_sources=None):
80 """
80 """
81 Custom method for this auth that doesn't accept non existing users.
81 Custom method for this auth that doesn't accept non existing users.
82 We know that user exists in our database.
82 We know that user exists in our database.
83 """
83 """
84 allows_non_existing_user = False
84 allows_non_existing_user = False
85 return super(RhodeCodeAuthPlugin, self).allows_authentication_from(
85 return super(RhodeCodeAuthPlugin, self).allows_authentication_from(
86 user, allows_non_existing_user=allows_non_existing_user)
86 user, allows_non_existing_user=allows_non_existing_user)
87
87
88 def auth(self, userobj, username, password, settings, **kwargs):
88 def auth(self, userobj, username, password, settings, **kwargs):
89 if not userobj:
89 if not userobj:
90 log.debug('userobj was:%s skipping', userobj)
90 log.debug('userobj was:%s skipping', userobj)
91 return None
91 return None
92 if userobj.extern_type != self.name:
92 if userobj.extern_type != self.name:
93 log.warning(
93 log.warning(
94 "userobj:%s extern_type mismatch got:`%s` expected:`%s`",
94 "userobj:%s extern_type mismatch got:`%s` expected:`%s`",
95 userobj, userobj.extern_type, self.name)
95 userobj, userobj.extern_type, self.name)
96 return None
96 return None
97
97
98 user_attrs = {
98 user_attrs = {
99 "username": userobj.username,
99 "username": userobj.username,
100 "firstname": userobj.firstname,
100 "firstname": userobj.firstname,
101 "lastname": userobj.lastname,
101 "lastname": userobj.lastname,
102 "groups": [],
102 "groups": [],
103 'user_group_sync': False,
103 'user_group_sync': False,
104 "email": userobj.email,
104 "email": userobj.email,
105 "admin": userobj.admin,
105 "admin": userobj.admin,
106 "active": userobj.active,
106 "active": userobj.active,
107 "active_from_extern": userobj.active,
107 "active_from_extern": userobj.active,
108 "extern_name": userobj.user_id,
108 "extern_name": userobj.user_id,
109 "extern_type": userobj.extern_type,
109 "extern_type": userobj.extern_type,
110 }
110 }
111
111
112 log.debug("User attributes:%s", user_attrs)
112 log.debug("User attributes:%s", user_attrs)
113 if userobj.active:
113 if userobj.active:
114 from rhodecode.lib import auth
114 from rhodecode.lib import auth
115 crypto_backend = auth.crypto_backend()
115 crypto_backend = auth.crypto_backend()
116 password_encoded = safe_str(password)
116 password_encoded = safe_str(password)
117 password_match, new_hash = crypto_backend.hash_check_with_upgrade(
117 password_match, new_hash = crypto_backend.hash_check_with_upgrade(
118 password_encoded, userobj.password or '')
118 password_encoded, userobj.password or '')
119
119
120 if password_match and new_hash:
120 if password_match and new_hash:
121 log.debug('user %s properly authenticated, but '
121 log.debug('user %s properly authenticated, but '
122 'requires hash change to bcrypt', userobj)
122 'requires hash change to bcrypt', userobj)
123 # if password match, and we use OLD deprecated hash,
123 # if password match, and we use OLD deprecated hash,
124 # we should migrate this user hash password to the new hash
124 # we should migrate this user hash password to the new hash
125 # we store the new returned by hash_check_with_upgrade function
125 # we store the new returned by hash_check_with_upgrade function
126 user_attrs['_hash_migrate'] = new_hash
126 user_attrs['_hash_migrate'] = new_hash
127
127
128 if userobj.username == User.DEFAULT_USER and userobj.active:
128 if userobj.username == User.DEFAULT_USER and userobj.active:
129 log.info(
129 log.info(
130 'user `%s` authenticated correctly as anonymous user', userobj.username)
130 'user `%s` authenticated correctly as anonymous user', userobj.username)
131 return user_attrs
131 return user_attrs
132
132
133 elif userobj.username == username and password_match:
133 elif userobj.username == username and password_match:
134 log.info('user `%s` authenticated correctly', userobj.username)
134 log.info('user `%s` authenticated correctly', userobj.username)
135 return user_attrs
135 return user_attrs
136 log.warn("user `%s` used a wrong password when "
136 log.warn("user `%s` used a wrong password when "
137 "authenticating on this plugin", userobj.username)
137 "authenticating on this plugin", userobj.username)
138 return None
138 return None
139 else:
139 else:
140 log.warning(
140 log.warning(
141 'user `%s` failed to authenticate via %s, reason: account not '
141 'user `%s` failed to authenticate via %s, reason: account not '
142 'active.', username, self.name)
142 'active.', username, self.name)
143 return None
143 return None
@@ -1,151 +1,151 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2018 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 """
21 """
22 RhodeCode authentication token plugin for built in internal auth
22 RhodeCode authentication token plugin for built in internal auth
23 """
23 """
24
24
25 import logging
25 import logging
26
26
27 from rhodecode.translation import _
27 from rhodecode.translation import _
28 from rhodecode.authentication.base import (
28 from rhodecode.authentication.base import (
29 RhodeCodeAuthPluginBase, VCS_TYPE, hybrid_property)
29 RhodeCodeAuthPluginBase, VCS_TYPE, hybrid_property)
30 from rhodecode.authentication.routes import AuthnPluginResourceBase
30 from rhodecode.authentication.routes import AuthnPluginResourceBase
31 from rhodecode.model.db import User, UserApiKeys, Repository
31 from rhodecode.model.db import User, UserApiKeys, Repository
32
32
33
33
34 log = logging.getLogger(__name__)
34 log = logging.getLogger(__name__)
35
35
36
36
37 def plugin_factory(plugin_id, *args, **kwds):
37 def plugin_factory(plugin_id, *args, **kwds):
38 plugin = RhodeCodeAuthPlugin(plugin_id)
38 plugin = RhodeCodeAuthPlugin(plugin_id)
39 return plugin
39 return plugin
40
40
41
41
42 class RhodecodeAuthnResource(AuthnPluginResourceBase):
42 class RhodecodeAuthnResource(AuthnPluginResourceBase):
43 pass
43 pass
44
44
45
45
46 class RhodeCodeAuthPlugin(RhodeCodeAuthPluginBase):
46 class RhodeCodeAuthPlugin(RhodeCodeAuthPluginBase):
47 """
47 """
48 Enables usage of authentication tokens for vcs operations.
48 Enables usage of authentication tokens for vcs operations.
49 """
49 """
50
50
51 def includeme(self, config):
51 def includeme(self, config):
52 config.add_authn_plugin(self)
52 config.add_authn_plugin(self)
53 config.add_authn_resource(self.get_id(), RhodecodeAuthnResource(self))
53 config.add_authn_resource(self.get_id(), RhodecodeAuthnResource(self))
54 config.add_view(
54 config.add_view(
55 'rhodecode.authentication.views.AuthnPluginViewBase',
55 'rhodecode.authentication.views.AuthnPluginViewBase',
56 attr='settings_get',
56 attr='settings_get',
57 renderer='rhodecode:templates/admin/auth/plugin_settings.mako',
57 renderer='rhodecode:templates/admin/auth/plugin_settings.mako',
58 request_method='GET',
58 request_method='GET',
59 route_name='auth_home',
59 route_name='auth_home',
60 context=RhodecodeAuthnResource)
60 context=RhodecodeAuthnResource)
61 config.add_view(
61 config.add_view(
62 'rhodecode.authentication.views.AuthnPluginViewBase',
62 'rhodecode.authentication.views.AuthnPluginViewBase',
63 attr='settings_post',
63 attr='settings_post',
64 renderer='rhodecode:templates/admin/auth/plugin_settings.mako',
64 renderer='rhodecode:templates/admin/auth/plugin_settings.mako',
65 request_method='POST',
65 request_method='POST',
66 route_name='auth_home',
66 route_name='auth_home',
67 context=RhodecodeAuthnResource)
67 context=RhodecodeAuthnResource)
68
68
69 def get_display_name(self):
69 def get_display_name(self):
70 return _('Rhodecode Token Auth')
70 return _('Rhodecode Token')
71
71
72 @classmethod
72 @classmethod
73 def docs(cls):
73 def docs(cls):
74 return "https://docs.rhodecode.com/RhodeCode-Enterprise/auth/auth-token.html"
74 return "https://docs.rhodecode.com/RhodeCode-Enterprise/auth/auth-token.html"
75
75
76 @hybrid_property
76 @hybrid_property
77 def name(self):
77 def name(self):
78 return "authtoken"
78 return "authtoken"
79
79
80 def user_activation_state(self):
80 def user_activation_state(self):
81 def_user_perms = User.get_default_user().AuthUser().permissions['global']
81 def_user_perms = User.get_default_user().AuthUser().permissions['global']
82 return 'hg.register.auto_activate' in def_user_perms
82 return 'hg.register.auto_activate' in def_user_perms
83
83
84 def allows_authentication_from(
84 def allows_authentication_from(
85 self, user, allows_non_existing_user=True,
85 self, user, allows_non_existing_user=True,
86 allowed_auth_plugins=None, allowed_auth_sources=None):
86 allowed_auth_plugins=None, allowed_auth_sources=None):
87 """
87 """
88 Custom method for this auth that doesn't accept empty users. And also
88 Custom method for this auth that doesn't accept empty users. And also
89 allows users from all other active plugins to use it and also
89 allows users from all other active plugins to use it and also
90 authenticate against it. But only via vcs mode
90 authenticate against it. But only via vcs mode
91 """
91 """
92 from rhodecode.authentication.base import get_authn_registry
92 from rhodecode.authentication.base import get_authn_registry
93 authn_registry = get_authn_registry()
93 authn_registry = get_authn_registry()
94
94
95 active_plugins = set(
95 active_plugins = set(
96 [x.name for x in authn_registry.get_plugins_for_authentication()])
96 [x.name for x in authn_registry.get_plugins_for_authentication()])
97 active_plugins.discard(self.name)
97 active_plugins.discard(self.name)
98
98
99 allowed_auth_plugins = [self.name] + list(active_plugins)
99 allowed_auth_plugins = [self.name] + list(active_plugins)
100 # only for vcs operations
100 # only for vcs operations
101 allowed_auth_sources = [VCS_TYPE]
101 allowed_auth_sources = [VCS_TYPE]
102
102
103 return super(RhodeCodeAuthPlugin, self).allows_authentication_from(
103 return super(RhodeCodeAuthPlugin, self).allows_authentication_from(
104 user, allows_non_existing_user=False,
104 user, allows_non_existing_user=False,
105 allowed_auth_plugins=allowed_auth_plugins,
105 allowed_auth_plugins=allowed_auth_plugins,
106 allowed_auth_sources=allowed_auth_sources)
106 allowed_auth_sources=allowed_auth_sources)
107
107
108 def auth(self, userobj, username, password, settings, **kwargs):
108 def auth(self, userobj, username, password, settings, **kwargs):
109 if not userobj:
109 if not userobj:
110 log.debug('userobj was:%s skipping', userobj)
110 log.debug('userobj was:%s skipping', userobj)
111 return None
111 return None
112
112
113 user_attrs = {
113 user_attrs = {
114 "username": userobj.username,
114 "username": userobj.username,
115 "firstname": userobj.firstname,
115 "firstname": userobj.firstname,
116 "lastname": userobj.lastname,
116 "lastname": userobj.lastname,
117 "groups": [],
117 "groups": [],
118 'user_group_sync': False,
118 'user_group_sync': False,
119 "email": userobj.email,
119 "email": userobj.email,
120 "admin": userobj.admin,
120 "admin": userobj.admin,
121 "active": userobj.active,
121 "active": userobj.active,
122 "active_from_extern": userobj.active,
122 "active_from_extern": userobj.active,
123 "extern_name": userobj.user_id,
123 "extern_name": userobj.user_id,
124 "extern_type": userobj.extern_type,
124 "extern_type": userobj.extern_type,
125 }
125 }
126
126
127 log.debug('Authenticating user with args %s', user_attrs)
127 log.debug('Authenticating user with args %s', user_attrs)
128 if userobj.active:
128 if userobj.active:
129 # calling context repo for token scopes
129 # calling context repo for token scopes
130 scope_repo_id = None
130 scope_repo_id = None
131 if self.acl_repo_name:
131 if self.acl_repo_name:
132 repo = Repository.get_by_repo_name(self.acl_repo_name)
132 repo = Repository.get_by_repo_name(self.acl_repo_name)
133 scope_repo_id = repo.repo_id if repo else None
133 scope_repo_id = repo.repo_id if repo else None
134
134
135 token_match = userobj.authenticate_by_token(
135 token_match = userobj.authenticate_by_token(
136 password, roles=[UserApiKeys.ROLE_VCS],
136 password, roles=[UserApiKeys.ROLE_VCS],
137 scope_repo_id=scope_repo_id)
137 scope_repo_id=scope_repo_id)
138
138
139 if userobj.username == username and token_match:
139 if userobj.username == username and token_match:
140 log.info(
140 log.info(
141 'user `%s` successfully authenticated via %s',
141 'user `%s` successfully authenticated via %s',
142 user_attrs['username'], self.name)
142 user_attrs['username'], self.name)
143 return user_attrs
143 return user_attrs
144 log.warn(
144 log.warn(
145 'user `%s` failed to authenticate via %s, reason: bad or '
145 'user `%s` failed to authenticate via %s, reason: bad or '
146 'inactive token.', username, self.name)
146 'inactive token.', username, self.name)
147 else:
147 else:
148 log.warning(
148 log.warning(
149 'user `%s` failed to authenticate via %s, reason: account not '
149 'user `%s` failed to authenticate via %s, reason: account not '
150 'active.', username, self.name)
150 'active.', username, self.name)
151 return None
151 return None
@@ -1,155 +1,155 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2012-2018 RhodeCode GmbH
3 # Copyright (C) 2012-2018 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import logging
21 import logging
22 import collections
22 import collections
23
23
24 from pyramid.exceptions import ConfigurationError
24 from pyramid.exceptions import ConfigurationError
25
25
26 from rhodecode.lib.utils2 import safe_str
26 from rhodecode.lib.utils2 import safe_str
27 from rhodecode.model.settings import SettingsModel
27 from rhodecode.model.settings import SettingsModel
28 from rhodecode.translation import _
28 from rhodecode.translation import _
29
29
30
30
31 log = logging.getLogger(__name__)
31 log = logging.getLogger(__name__)
32
32
33
33
34 class AuthnResourceBase(object):
34 class AuthnResourceBase(object):
35 __name__ = None
35 __name__ = None
36 __parent__ = None
36 __parent__ = None
37
37
38 def get_root(self):
38 def get_root(self):
39 current = self
39 current = self
40 while current.__parent__ is not None:
40 while current.__parent__ is not None:
41 current = current.__parent__
41 current = current.__parent__
42 return current
42 return current
43
43
44
44
45 class AuthnPluginResourceBase(AuthnResourceBase):
45 class AuthnPluginResourceBase(AuthnResourceBase):
46
46
47 def __init__(self, plugin):
47 def __init__(self, plugin):
48 self.plugin = plugin
48 self.plugin = plugin
49 self.__name__ = plugin.get_url_slug()
49 self.__name__ = plugin.get_url_slug()
50 self.display_name = plugin.get_display_name()
50 self.display_name = plugin.get_display_name()
51
51
52
52
53 class AuthnRootResource(AuthnResourceBase):
53 class AuthnRootResource(AuthnResourceBase):
54 """
54 """
55 This is the root traversal resource object for the authentication settings.
55 This is the root traversal resource object for the authentication settings.
56 """
56 """
57
57
58 def __init__(self):
58 def __init__(self):
59 self._store = collections.OrderedDict()
59 self._store = collections.OrderedDict()
60 self._resource_name_map = {}
60 self._resource_name_map = {}
61 self.display_name = _('Global')
61 self.display_name = _('Authentication Plugins')
62
62
63 def __getitem__(self, key):
63 def __getitem__(self, key):
64 """
64 """
65 Customized get item function to return only items (plugins) that are
65 Customized get item function to return only items (plugins) that are
66 activated.
66 activated.
67 """
67 """
68 if self._is_item_active(key):
68 if self._is_item_active(key):
69 return self._store[key]
69 return self._store[key]
70 else:
70 else:
71 raise KeyError('Authentication plugin "{}" is not active.'.format(
71 raise KeyError('Authentication plugin "{}" is not active.'.format(
72 key))
72 key))
73
73
74 def __iter__(self):
74 def __iter__(self):
75 for key in self._store.keys():
75 for key in self._store.keys():
76 if self._is_item_active(key):
76 if self._is_item_active(key):
77 yield self._store[key]
77 yield self._store[key]
78
78
79 def _is_item_active(self, key):
79 def _is_item_active(self, key):
80 activated_plugins = SettingsModel().get_auth_plugins()
80 activated_plugins = SettingsModel().get_auth_plugins()
81 plugin_id = self.get_plugin_id(key)
81 plugin_id = self.get_plugin_id(key)
82 return plugin_id in activated_plugins
82 return plugin_id in activated_plugins
83
83
84 def get_plugin_id(self, resource_name):
84 def get_plugin_id(self, resource_name):
85 """
85 """
86 Return the plugin id for the given traversal resource name.
86 Return the plugin id for the given traversal resource name.
87 """
87 """
88 # TODO: Store this info in the resource element.
88 # TODO: Store this info in the resource element.
89 return self._resource_name_map[resource_name]
89 return self._resource_name_map[resource_name]
90
90
91 def get_sorted_list(self):
91 def get_sorted_list(self):
92 """
92 """
93 Returns a sorted list of sub resources for displaying purposes.
93 Returns a sorted list of sub resources for displaying purposes.
94 """
94 """
95 def sort_key(resource):
95 def sort_key(resource):
96 return str.lower(safe_str(resource.display_name))
96 return str.lower(safe_str(resource.display_name))
97
97
98 active = [item for item in self]
98 active = [item for item in self]
99 return sorted(active, key=sort_key)
99 return sorted(active, key=sort_key)
100
100
101 def get_nav_list(self, sort=True):
101 def get_nav_list(self, sort=True):
102 """
102 """
103 Returns a sorted list of resources for displaying the navigation.
103 Returns a sorted list of resources for displaying the navigation.
104 """
104 """
105 if sort:
105 if sort:
106 nav_list = self.get_sorted_list()
106 nav_list = self.get_sorted_list()
107 else:
107 else:
108 nav_list = [item for item in self]
108 nav_list = [item for item in self]
109
109
110 nav_list.insert(0, self)
110 nav_list.insert(0, self)
111 return nav_list
111 return nav_list
112
112
113 def add_authn_resource(self, config, plugin_id, resource):
113 def add_authn_resource(self, config, plugin_id, resource):
114 """
114 """
115 Register a traversal resource as a sub element to the authentication
115 Register a traversal resource as a sub element to the authentication
116 settings. This method is registered as a directive on the pyramid
116 settings. This method is registered as a directive on the pyramid
117 configurator object and called by plugins.
117 configurator object and called by plugins.
118 """
118 """
119
119
120 def _ensure_unique_name(name, limit=100):
120 def _ensure_unique_name(name, limit=100):
121 counter = 1
121 counter = 1
122 current = name
122 current = name
123 while current in self._store.keys():
123 while current in self._store.keys():
124 current = '{}{}'.format(name, counter)
124 current = '{}{}'.format(name, counter)
125 counter += 1
125 counter += 1
126 if counter > limit:
126 if counter > limit:
127 raise ConfigurationError(
127 raise ConfigurationError(
128 'Cannot build unique name for traversal resource "%s" '
128 'Cannot build unique name for traversal resource "%s" '
129 'registered by plugin "%s"', name, plugin_id)
129 'registered by plugin "%s"', name, plugin_id)
130 return current
130 return current
131
131
132 # Allow plugin resources with identical names by rename duplicates.
132 # Allow plugin resources with identical names by rename duplicates.
133 unique_name = _ensure_unique_name(resource.__name__)
133 unique_name = _ensure_unique_name(resource.__name__)
134 if unique_name != resource.__name__:
134 if unique_name != resource.__name__:
135 log.warn('Name collision for traversal resource "%s" registered '
135 log.warn('Name collision for traversal resource "%s" registered '
136 'by authentication plugin "%s"', resource.__name__,
136 'by authentication plugin "%s"', resource.__name__,
137 plugin_id)
137 plugin_id)
138 resource.__name__ = unique_name
138 resource.__name__ = unique_name
139
139
140 log.debug('Register traversal resource "%s" for plugin "%s"',
140 log.debug('Register traversal resource "%s" for plugin "%s"',
141 unique_name, plugin_id)
141 unique_name, plugin_id)
142 self._resource_name_map[unique_name] = plugin_id
142 self._resource_name_map[unique_name] = plugin_id
143 resource.__parent__ = self
143 resource.__parent__ = self
144 self._store[unique_name] = resource
144 self._store[unique_name] = resource
145
145
146
146
147 root = AuthnRootResource()
147 root = AuthnRootResource()
148
148
149
149
150 def root_factory(request=None):
150 def root_factory(request=None):
151 """
151 """
152 Returns the root traversal resource instance used for the authentication
152 Returns the root traversal resource instance used for the authentication
153 settings route.
153 settings route.
154 """
154 """
155 return root
155 return root
General Comments 0
You need to be logged in to leave comments. Login now