Skip to content
This repository was archived by the owner on Jun 12, 2021. It is now read-only.

Commit 5113406

Browse files
committed
Replaced build_services with init_services.
1 parent f78b5dc commit 5113406

6 files changed

Lines changed: 123 additions & 79 deletions

File tree

src/oidcservice/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010

1111
__author__ = 'Roland Hedberg'
12-
__version__ = '0.6.3'
12+
__version__ = '0.6.4'
1313

1414

1515
OIDCONF_PATTERN = "{}/.well-known/openid-configuration"

src/oidcservice/oidc/__init__.py

Lines changed: 19 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,25 @@
11
#
2-
import inspect
3-
import sys
4-
from glob import glob
5-
from os.path import basename
6-
from os.path import dirname
7-
from os.path import join
8-
9-
from oidcservice.service import Service
10-
# from oidcservice.oauth2 import factory as oauth2_factory
11-
122

133
DEFAULT_SERVICES = {
14-
'ProviderInfoDiscovery': {},
15-
'Registration': {},
16-
'Authorization': {},
17-
'AccessToken': {},
18-
'RefreshAccessToken': {},
19-
'UserInfo': {}
4+
"discovery": {
5+
'class': 'oidcservice.oidc.provider_info_discovery'
6+
'.ProviderInfoDiscovery'
7+
},
8+
'registration': {
9+
'class': 'oidcservice.oidc.registration.Registration'
10+
},
11+
'authorization': {
12+
'class': 'oidcservice.oidc.authorization.Authorization'
13+
},
14+
'access_token': {
15+
'class': 'oidcservice.oidc.access_token.AccessToken'
16+
},
17+
'refresh_access_token': {
18+
'class': 'oidcservice.oidc.refresh_access_token.RefreshAccessToken'
19+
},
20+
'userinfo': {
21+
'class': 'oidcservice.oidc.userinfo.UserInfo'
22+
}
2023
}
2124

2225
WF_URL = "https://{}/.well-known/webfinger"
@@ -35,25 +38,3 @@
3538
'registration': ['registration'],
3639
'end_sesssion': ['end_session']
3740
}
38-
39-
40-
# def factory(req_name, **kwargs):
41-
# pwd = dirname(__file__)
42-
# if pwd not in sys.path:
43-
# sys.path.insert(0, pwd)
44-
# for x in glob(join(pwd, '*.py')):
45-
# _mod = basename(x)[:-3]
46-
# if not _mod.startswith('__'):
47-
# # _mod = basename(x)[:-3]
48-
# if _mod not in sys.modules:
49-
# __import__(_mod, globals(), locals())
50-
#
51-
# for name, obj in inspect.getmembers(sys.modules[_mod]):
52-
# if inspect.isclass(obj) and issubclass(obj, Service):
53-
# try:
54-
# if obj.__name__ == req_name:
55-
# return obj(**kwargs)
56-
# except AttributeError:
57-
# pass
58-
#
59-
# return oauth2_factory(req_name, **kwargs)

src/oidcservice/service.py

Lines changed: 71 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,20 @@
22
from urllib.parse import urlparse
33

44
from cryptojwt.jwt import JWT
5+
from oidcmsg.message import Message
6+
from oidcmsg.oauth2 import ResponseMessage
7+
from oidcmsg.oauth2 import is_error_message
58

9+
from oidcservice import util
610
from oidcservice.client_auth import factory as ca_factory
711
from oidcservice.exception import ResponseError
812
from oidcservice.state_interface import StateInterface
9-
from oidcservice.util import get_http_body
10-
from oidcservice.util import get_http_url
1113
from oidcservice.util import JOSE_ENCODED
1214
from oidcservice.util import JSON_ENCODED
1315
from oidcservice.util import URL_ENCODED
14-
15-
from oidcmsg.oauth2 import is_error_message
16-
from oidcmsg.oauth2 import ResponseMessage
17-
from oidcmsg.message import Message
18-
16+
from oidcservice.util import get_http_body
17+
from oidcservice.util import get_http_url
18+
from oidcservice.util import importer
1919

2020
__author__ = 'Roland Hedberg'
2121

@@ -46,9 +46,9 @@ def __init__(self, service_context, state_db, conf=None,
4646
StateInterface.__init__(self, state_db)
4747

4848
if client_authn_factory is None:
49-
self.client_authn_factory=ca_factory
49+
self.client_authn_factory = ca_factory
5050
else:
51-
self.client_authn_factory=client_authn_factory
51+
self.client_authn_factory = client_authn_factory
5252

5353
self.service_context = service_context
5454
self.default_request_args = {}
@@ -94,7 +94,8 @@ def gather_request_args(self, **kwargs):
9494
ar_args[prop] = self.conf['request_args'][prop]
9595
except KeyError:
9696
try:
97-
ar_args[prop] = self.service_context.register_args[prop]
97+
ar_args[prop] = self.service_context.register_args[
98+
prop]
9899
except KeyError:
99100
try:
100101
ar_args[prop] = self.default_request_args[prop]
@@ -337,11 +338,11 @@ def get_request_parameters(self, request_body_type="", method="",
337338
_info['url'] = get_http_url(endpoint_url, request, method=method)
338339

339340
# If there is to be a body part
340-
if method == 'POST':
341+
if method == 'POST':
341342
# How should it be serialized
342343
if request_body_type == 'urlencoded':
343344
content_type = URL_ENCODED
344-
elif request_body_type in ['jws','jwe', 'jose']:
345+
elif request_body_type in ['jws', 'jwe', 'jose']:
345346
content_type = JOSE_ENCODED
346347
else: # request_body_type == 'json'
347348
content_type = JSON_ENCODED
@@ -424,7 +425,7 @@ def parse_response(self, info, sformat="", state="", **kwargs):
424425

425426
logger.debug('response format: {}'.format(sformat))
426427

427-
if sformat in ['jose','jws','jwe']:
428+
if sformat in ['jose', 'jws', 'jwe']:
428429
resp = self.post_parse_response(info, state=state)
429430

430431
if not resp:
@@ -511,19 +512,50 @@ def get_conf_attr(self, attr, default=None):
511512
return default
512513

513514

514-
def build_services(service_definitions, service_factory, module_dirs,
515-
service_context, state_db, client_authn_factory=None):
515+
# def build_services(service_definitions, service_factory, module_dirs,
516+
# service_context, state_db, client_authn_factory=None):
517+
# """
518+
# This function will build a number of :py:class:`oidcservice.service.Service`
519+
# instances based on the service definitions provided.
520+
#
521+
# :param service_definitions: A dictionary of service definitions. The keys
522+
# are the names of the subclasses. The values are configurations.
523+
# :param service_factory: A factory that can initiate a service class
524+
# :param module_dirs: The directories in which to search for service modules.
525+
# Directory names are expected to be relative to the oidcservice package.
526+
# e.g. ['oidc', 'oauth2]. The directories will be search in order until
527+
# a matching module is found.
528+
# :param service_context: A reference to the service context, this is the same
529+
# for all service instances.
530+
# :param state_db: A reference to the state database. Shared by all the
531+
# services.
532+
# :param client_authn_factory: A list of methods the services can use to
533+
# authenticate the client to a service.
534+
# :return: A dictionary, with service name as key and the service instance as
535+
# value.
536+
# """
537+
# service = {}
538+
# for service_name, service_configuration in service_definitions.items():
539+
# _srv = service_factory(service_name,
540+
# module_dirs,
541+
# service_context=service_context,
542+
# state_db=state_db,
543+
# client_authn_factory=client_authn_factory,
544+
# conf=service_configuration)
545+
# try:
546+
# service[_srv.service_name] = _srv
547+
# except AttributeError:
548+
# raise ValueError("Could not load '{}'".format(service_name))
549+
#
550+
# return service
551+
552+
553+
def init_services(service_definitions, service_context, state_db,
554+
client_authn_factory=None):
516555
"""
517-
This function will build a number of :py:class:`oidcservice.service.Service`
518-
instances based on the service definitions provided.
519-
520-
:param service_definitions: A dictionary of service definitions. The keys
521-
are the names of the subclasses. The values are configurations.
522-
:param service_factory: A factory that can initiate a service class
523-
:param module_dirs: The directories in which to search for service modules.
524-
Directory names are expected to be relative to the oidcservice package.
525-
e.g. ['oidc', 'oauth2]. The directories will be search in order until
526-
a matching module is found.
556+
Initiates a set of services
557+
558+
:param service_definitions: A dictionary cotaining service definitions
527559
:param service_context: A reference to the service context, this is the same
528560
for all service instances.
529561
:param state_db: A reference to the state database. Shared by all the
@@ -535,12 +567,20 @@ def build_services(service_definitions, service_factory, module_dirs,
535567
"""
536568
service = {}
537569
for service_name, service_configuration in service_definitions.items():
538-
_srv = service_factory(service_name,
539-
module_dirs,
540-
service_context=service_context,
541-
state_db=state_db,
542-
client_authn_factory=client_authn_factory,
543-
conf=service_configuration)
570+
try:
571+
kwargs = service_configuration['kwargs']
572+
except KeyError:
573+
kwargs = {}
574+
575+
kwargs.update({'service_context': service_context,
576+
'state_db': state_db,
577+
'client_authn_factory': client_authn_factory})
578+
579+
if isinstance(service_configuration['class'], str):
580+
_srv = util.importer(service_configuration['class'])(**kwargs)
581+
else:
582+
_srv = service_configuration['class'](**kwargs)
583+
544584
try:
545585
service[_srv.service_name] = _srv
546586
except AttributeError:

src/oidcservice/util.py

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import importlib
12
import logging
23
from urllib.parse import parse_qs
34
from urllib.parse import urlsplit
@@ -62,5 +63,28 @@ def get_http_body(req, content_type=URL_ENCODED):
6263
"Unsupported content type: '%s'" % content_type)
6364

6465

65-
def load_yaml_config(file):
66-
return yaml.load(file)
66+
def load_yaml_config(filename):
67+
with open(filename, "rt", encoding='utf-8') as file:
68+
config_dict = yaml.load(file)
69+
return config_dict
70+
71+
72+
def modsplit(s):
73+
"""Split importable"""
74+
if ':' in s:
75+
c = s.split(':')
76+
if len(c) != 2:
77+
raise ValueError("Syntax error: {s}")
78+
return c[0], c[1]
79+
else:
80+
c = s.split('.')
81+
if len(c) < 2:
82+
raise ValueError("Syntax error: {s}")
83+
return '.'.join(c[:-1]), c[-1]
84+
85+
86+
def importer(name):
87+
"""Import by name"""
88+
c1, c2 = modsplit(name)
89+
module = importlib.import_module(c1)
90+
return getattr(module, c2)

tests/test_09_client_auth.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
from oidcservice.client_auth import valid_service_context
2222
from oidcservice.oidc import DEFAULT_SERVICES
2323
from oidcservice.service_factory import service_factory
24-
from oidcservice.service import build_services
24+
from oidcservice.service import init_services
2525
from oidcservice.service_context import ServiceContext
2626
from oidcservice.state_interface import InMemoryStateDataBase
2727
from oidcservice.state_interface import State
@@ -70,8 +70,7 @@ def services():
7070
state='ABCDE').to_json()
7171
db.set('ABCDE', State(iss='Issuer', auth_request=auth_request,
7272
auth_response=auth_response).to_json())
73-
return build_services(DEFAULT_SERVICES, service_factory, ['oidc'],
74-
get_service_context(), db)
73+
return init_services(DEFAULT_SERVICES, get_service_context(), db)
7574

7675

7776
def test_quote():

tests/test_20_conversation.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@
1414
from oidcmsg.oidc import OpenIDSchema
1515
from oidcmsg.oidc import ProviderConfigurationResponse
1616
from oidcmsg.oidc import RegistrationResponse
17+
from oidcservice.oidc.webfinger import WebFinger
1718

19+
from oidcservice.service import init_services
1820
from oidcservice.service_context import ServiceContext
1921
from oidcservice.oidc import DEFAULT_SERVICES
20-
from oidcservice.service_factory import service_factory
21-
from oidcservice.service import build_services
2222
from oidcservice.state_interface import InMemoryStateDataBase
2323

2424
# ================== SETUP ===========================
@@ -116,9 +116,9 @@ def test_conversation():
116116
)
117117

118118
service_spec = DEFAULT_SERVICES.copy()
119-
service_spec['WebFinger'] = {}
119+
service_spec['WebFinger'] = {'class': WebFinger}
120120

121-
service = build_services(service_spec, service_factory, ['oidc'],
121+
service = init_services(service_spec,
122122
state_db=InMemoryStateDataBase(),
123123
service_context=service_context)
124124

0 commit comments

Comments
 (0)