##// END OF EJS Templates
authn: Small refactoring of plugin discovery.
johbo -
r135:006df1d7 default
parent child Browse files
Show More
@@ -1,121 +1,122 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2012-2016 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 import logging
22 22 import importlib
23 23
24 24 from pkg_resources import iter_entry_points
25 25 from pyramid.authentication import SessionAuthenticationPolicy
26 26
27 27 from rhodecode.authentication.registry import AuthenticationPluginRegistry
28 28 from rhodecode.authentication.routes import root_factory
29 29 from rhodecode.authentication.routes import AuthnRootResource
30 30 from rhodecode.config.routing import ADMIN_PREFIX
31 31 from rhodecode.model.settings import SettingsModel
32 32
33 33
34 34 log = logging.getLogger(__name__)
35 35
36 # Legacy plugins are stored with this prefix in 'auth_plugins'.
36 # Plugin ID prefixes to distinct between normal and legacy plugins.
37 plugin_prefix = 'egg:'
37 38 legacy_plugin_prefix = 'py:'
38 39
39 40
40 41 # TODO: Currently this is only used to discover the authentication plugins.
41 42 # Later on this may be used in a generic way to look up and include all kinds
42 43 # of supported enterprise plugins. Therefore this has to be moved and
43 44 # refactored to a real 'plugin look up' machinery.
44 45 # TODO: When refactoring this think about splitting it up into distinct
45 46 # discover, load and include phases.
46 47 def _discover_plugins(config, entry_point='enterprise.plugins1'):
47 _discovered_plugins = {}
48
49 48 for ep in iter_entry_points(entry_point):
50 plugin_id = 'egg:{}#{}'.format(ep.dist.project_name, ep.name)
49 plugin_id = '{}:{}#{}'.format(
50 plugin_prefix, ep.dist.project_name, ep.name)
51 51 log.debug('Plugin discovered: "%s"', plugin_id)
52 module = ep.load()
53 plugin = module(plugin_id=plugin_id)
54 config.include(plugin.includeme)
52 try:
53 module = ep.load()
54 plugin = module(plugin_id=plugin_id)
55 config.include(plugin.includeme)
56 except Exception as e:
57 log.exception(
58 'Exception while loading authentication plugin '
59 '"{}": {}'.format(plugin_id, e.message))
55 60
56 return _discovered_plugins
61
62 def _import_legacy_plugin(plugin_id):
63 module_name = plugin_id.split(legacy_plugin_prefix, 1)[-1]
64 module = importlib.import_module(module_name)
65 return module.plugin_factory(plugin_id=plugin_id)
57 66
58 67
59 68 def _discover_legacy_plugins(config, prefix=legacy_plugin_prefix):
60 69 """
61 70 Function that imports the legacy plugins stored in the 'auth_plugins'
62 71 setting in database which are using the specified prefix. Normally 'py:' is
63 72 used for the legacy plugins.
64 73 """
65 74 auth_plugins = SettingsModel().get_setting_by_name('auth_plugins')
66 75 enabled_plugins = auth_plugins.app_settings_value
67 76 legacy_plugins = [id_ for id_ in enabled_plugins if id_.startswith(prefix)]
68 77
69 log.debug('Importing these legacy authentication plugins {}'.format(
70 legacy_plugins))
71
72 78 for plugin_id in legacy_plugins:
73 module_name = plugin_id.split(prefix, 1)[-1]
79 log.debug('Legacy plugin discovered: "%s"', plugin_id)
74 80 try:
75 module = importlib.import_module(module_name)
76 plugin = module.plugin_factory(plugin_id=plugin_id)
81 plugin = _import_legacy_plugin(plugin_id)
77 82 config.include(plugin.includeme)
78 except ImportError as e:
79 log.error(
80 'ImportError while importing legacy authentication plugin '
81 '"{}": {}'.format(plugin_id, e.message))
82 83 except Exception as e:
83 log.error(
84 'Exception while importing legacy authentication plugin '
84 log.exception(
85 'Exception while loading legacy authentication plugin '
85 86 '"{}": {}'.format(plugin_id, e.message))
86 87
87 88
88 89 def includeme(config):
89 90 # Set authentication policy.
90 91 authn_policy = SessionAuthenticationPolicy()
91 92 config.set_authentication_policy(authn_policy)
92 93
93 94 # Create authentication plugin registry and add it to the pyramid registry.
94 95 authn_registry = AuthenticationPluginRegistry(config.get_settings())
95 96 config.add_directive('add_authn_plugin', authn_registry.add_authn_plugin)
96 97 config.registry.registerUtility(authn_registry)
97 98
98 99 # Create authentication traversal root resource.
99 100 authn_root_resource = root_factory()
100 101 config.add_directive('add_authn_resource',
101 102 authn_root_resource.add_authn_resource)
102 103
103 104 # Add the authentication traversal route.
104 105 config.add_route('auth_home',
105 106 ADMIN_PREFIX + '/auth*traverse',
106 107 factory=root_factory)
107 108 # Add the authentication settings root views.
108 109 config.add_view('rhodecode.authentication.views.AuthSettingsView',
109 110 attr='index',
110 111 request_method='GET',
111 112 route_name='auth_home',
112 113 context=AuthnRootResource)
113 114 config.add_view('rhodecode.authentication.views.AuthSettingsView',
114 115 attr='auth_settings',
115 116 request_method='POST',
116 117 route_name='auth_home',
117 118 context=AuthnRootResource)
118 119
119 120 # Auto discover authentication plugins and include their configuration.
120 121 _discover_plugins(config)
121 122 _discover_legacy_plugins(config)
General Comments 0
You need to be logged in to leave comments. Login now