##// END OF EJS Templates
logging: removed log.warning calls
super-admin -
r4999:4ec92282 default
parent child Browse files
Show More
@@ -1,121 +1,121 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2012-2020 RhodeCode GmbH
3 # Copyright (C) 2012-2020 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 time
21 import time
22 import logging
22 import logging
23
23
24 from pyramid.exceptions import ConfigurationError
24 from pyramid.exceptions import ConfigurationError
25 from zope.interface import implementer
25 from zope.interface import implementer
26
26
27 from rhodecode.authentication.interface import IAuthnPluginRegistry
27 from rhodecode.authentication.interface import IAuthnPluginRegistry
28 from rhodecode.model.settings import SettingsModel
28 from rhodecode.model.settings import SettingsModel
29 from rhodecode.lib.utils2 import safe_str
29 from rhodecode.lib.utils2 import safe_str
30 from rhodecode.lib.statsd_client import StatsdClient
30 from rhodecode.lib.statsd_client import StatsdClient
31 from rhodecode.lib import rc_cache
31 from rhodecode.lib import rc_cache
32
32
33 log = logging.getLogger(__name__)
33 log = logging.getLogger(__name__)
34
34
35
35
36 @implementer(IAuthnPluginRegistry)
36 @implementer(IAuthnPluginRegistry)
37 class AuthenticationPluginRegistry(object):
37 class AuthenticationPluginRegistry(object):
38
38
39 # INI settings key to set a fallback authentication plugin.
39 # INI settings key to set a fallback authentication plugin.
40 fallback_plugin_key = 'rhodecode.auth_plugin_fallback'
40 fallback_plugin_key = 'rhodecode.auth_plugin_fallback'
41
41
42 def __init__(self, settings):
42 def __init__(self, settings):
43 self._plugins = {}
43 self._plugins = {}
44 self._fallback_plugin = settings.get(self.fallback_plugin_key, None)
44 self._fallback_plugin = settings.get(self.fallback_plugin_key, None)
45
45
46 def add_authn_plugin(self, config, plugin):
46 def add_authn_plugin(self, config, plugin):
47 plugin_id = plugin.get_id()
47 plugin_id = plugin.get_id()
48 if plugin_id in self._plugins.keys():
48 if plugin_id in self._plugins.keys():
49 raise ConfigurationError(
49 raise ConfigurationError(
50 'Cannot register authentication plugin twice: "%s"', plugin_id)
50 'Cannot register authentication plugin twice: "%s"', plugin_id)
51 else:
51 else:
52 log.debug('Register authentication plugin: "%s"', plugin_id)
52 log.debug('Register authentication plugin: "%s"', plugin_id)
53 self._plugins[plugin_id] = plugin
53 self._plugins[plugin_id] = plugin
54
54
55 def get_plugins(self):
55 def get_plugins(self):
56 def sort_key(plugin):
56 def sort_key(plugin):
57 return str.lower(safe_str(plugin.get_display_name()))
57 return str.lower(safe_str(plugin.get_display_name()))
58
58
59 return sorted(self._plugins.values(), key=sort_key)
59 return sorted(self._plugins.values(), key=sort_key)
60
60
61 def get_plugin(self, plugin_id):
61 def get_plugin(self, plugin_id):
62 return self._plugins.get(plugin_id, None)
62 return self._plugins.get(plugin_id, None)
63
63
64 def get_plugin_by_uid(self, plugin_uid):
64 def get_plugin_by_uid(self, plugin_uid):
65 for plugin in self._plugins.values():
65 for plugin in self._plugins.values():
66 if plugin.uid == plugin_uid:
66 if plugin.uid == plugin_uid:
67 return plugin
67 return plugin
68
68
69 def get_plugins_for_authentication(self, cache=True):
69 def get_plugins_for_authentication(self, cache=True):
70 """
70 """
71 Returns a list of plugins which should be consulted when authenticating
71 Returns a list of plugins which should be consulted when authenticating
72 a user. It only returns plugins which are enabled and active.
72 a user. It only returns plugins which are enabled and active.
73 Additionally it includes the fallback plugin from the INI file, if
73 Additionally it includes the fallback plugin from the INI file, if
74 `rhodecode.auth_plugin_fallback` is set to a plugin ID.
74 `rhodecode.auth_plugin_fallback` is set to a plugin ID.
75 """
75 """
76
76
77 cache_namespace_uid = 'cache_auth_plugins'
77 cache_namespace_uid = 'cache_auth_plugins'
78 region = rc_cache.get_or_create_region('cache_general', cache_namespace_uid)
78 region = rc_cache.get_or_create_region('cache_general', cache_namespace_uid)
79
79
80 @region.conditional_cache_on_arguments(condition=cache)
80 @region.conditional_cache_on_arguments(condition=cache)
81 def _get_auth_plugins(name, key, fallback_plugin):
81 def _get_auth_plugins(name, key, fallback_plugin):
82 plugins = []
82 plugins = []
83
83
84 # Add all enabled and active plugins to the list. We iterate over the
84 # Add all enabled and active plugins to the list. We iterate over the
85 # auth_plugins setting from DB because it also represents the ordering.
85 # auth_plugins setting from DB because it also represents the ordering.
86 enabled_plugins = SettingsModel().get_auth_plugins()
86 enabled_plugins = SettingsModel().get_auth_plugins()
87 raw_settings = SettingsModel().get_all_settings(cache=False)
87 raw_settings = SettingsModel().get_all_settings(cache=False)
88 for plugin_id in enabled_plugins:
88 for plugin_id in enabled_plugins:
89 plugin = self.get_plugin(plugin_id)
89 plugin = self.get_plugin(plugin_id)
90 if plugin is not None and plugin.is_active(
90 if plugin is not None and plugin.is_active(
91 plugin_cached_settings=raw_settings):
91 plugin_cached_settings=raw_settings):
92
92
93 # inject settings into plugin, we can re-use the DB fetched settings here
93 # inject settings into plugin, we can re-use the DB fetched settings here
94 plugin._settings = plugin._propagate_settings(raw_settings)
94 plugin._settings = plugin._propagate_settings(raw_settings)
95 plugins.append(plugin)
95 plugins.append(plugin)
96
96
97 # Add the fallback plugin from ini file.
97 # Add the fallback plugin from ini file.
98 if fallback_plugin:
98 if fallback_plugin:
99 log.warn(
99 log.warning(
100 'Using fallback authentication plugin from INI file: "%s"',
100 'Using fallback authentication plugin from INI file: "%s"',
101 fallback_plugin)
101 fallback_plugin)
102 plugin = self.get_plugin(fallback_plugin)
102 plugin = self.get_plugin(fallback_plugin)
103 if plugin is not None and plugin not in plugins:
103 if plugin is not None and plugin not in plugins:
104 plugin._settings = plugin._propagate_settings(raw_settings)
104 plugin._settings = plugin._propagate_settings(raw_settings)
105 plugins.append(plugin)
105 plugins.append(plugin)
106 return plugins
106 return plugins
107
107
108 start = time.time()
108 start = time.time()
109 plugins = _get_auth_plugins('rhodecode_auth_plugins', 'v1', self._fallback_plugin)
109 plugins = _get_auth_plugins('rhodecode_auth_plugins', 'v1', self._fallback_plugin)
110
110
111 compute_time = time.time() - start
111 compute_time = time.time() - start
112 log.debug('cached method:%s took %.4fs', _get_auth_plugins.__name__, compute_time)
112 log.debug('cached method:%s took %.4fs', _get_auth_plugins.__name__, compute_time)
113
113
114 statsd = StatsdClient.statsd
114 statsd = StatsdClient.statsd
115 if statsd:
115 if statsd:
116 elapsed_time_ms = round(1000.0 * compute_time) # use ms only
116 elapsed_time_ms = round(1000.0 * compute_time) # use ms only
117 statsd.timing("rhodecode_auth_plugins_timing.histogram", elapsed_time_ms,
117 statsd.timing("rhodecode_auth_plugins_timing.histogram", elapsed_time_ms,
118 use_decimals=False)
118 use_decimals=False)
119
119
120 return plugins
120 return plugins
121
121
@@ -1,155 +1,155 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2012-2020 RhodeCode GmbH
3 # Copyright (C) 2012-2020 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 = _('Authentication Plugins')
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, sort_key=None):
91 def get_sorted_list(self, sort_key=None):
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 default_sort_key(resource):
95 def default_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 or default_sort_key)
99 return sorted(active, key=sort_key or default_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.warning('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