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

Commit fc0e9ef

Browse files
committed
Merge branch 'develop' of github.com:IdentityPython/JWTConnect-Python-OidcMsg into develop
2 parents f46a659 + 609290e commit fc0e9ef

File tree

6 files changed

+168
-101
lines changed

6 files changed

+168
-101
lines changed

Diff for: setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ def run_tests(self):
6767
"Programming Language :: Python :: 3.8",
6868
"Topic :: Software Development :: Libraries :: Python Modules"],
6969
install_requires=[
70-
"cryptojwt>=1.5.0",
70+
"cryptojwt>=1.6.0",
7171
"pyOpenSSL",
7272
"filelock>=3.0.12",
7373
'pyyaml>=5.1.2'

Diff for: src/oidcmsg/__init__.py

+35-35
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
__author__ = "Roland Hedberg"
2-
__version__ = "1.5.0"
2+
__version__ = "1.5.1"
33

44
import os
55
from typing import Dict
@@ -34,37 +34,37 @@ def proper_path(path):
3434
return path
3535

3636

37-
def add_base_path(conf: Dict[str, str], item_paths: dict, base_path: str):
38-
"""
39-
This is for adding a base path to path specified in a configuration
40-
41-
:param conf: Configuration
42-
:param item_paths: The relative item path
43-
:param base_path: An absolute path to add to the relative
44-
"""
45-
for section, items in item_paths.items():
46-
if section == "":
47-
part = conf
48-
else:
49-
part = conf.get(section)
50-
51-
if part:
52-
if isinstance(items, list):
53-
for attr in items:
54-
_path = part.get(attr)
55-
if _path:
56-
if _path.startswith("/"):
57-
continue
58-
elif _path == "":
59-
part[attr] = "./" + _path
60-
else:
61-
part[attr] = os.path.join(base_path, _path)
62-
elif items is None:
63-
if part.startswith("/"):
64-
continue
65-
elif part == "":
66-
conf[section] = "./"
67-
else:
68-
conf[section] = os.path.join(base_path, part)
69-
else: # Assume items is dictionary like
70-
add_base_path(part, items, base_path)
37+
# def add_base_path(conf: Dict[str, str], item_paths: dict, base_path: str):
38+
# """
39+
# This is for adding a base path to path specified in a configuration
40+
#
41+
# :param conf: Configuration
42+
# :param item_paths: The relative item path
43+
# :param base_path: An absolute path to add to the relative
44+
# """
45+
# for section, items in item_paths.items():
46+
# if section == "":
47+
# part = conf
48+
# else:
49+
# part = conf.get(section)
50+
#
51+
# if part:
52+
# if isinstance(items, list):
53+
# for attr in items:
54+
# _path = part.get(attr)
55+
# if _path:
56+
# if _path.startswith("/"):
57+
# continue
58+
# elif _path == "":
59+
# part[attr] = "./" + _path
60+
# else:
61+
# part[attr] = os.path.join(base_path, _path)
62+
# elif items is None:
63+
# if part.startswith("/"):
64+
# continue
65+
# elif part == "":
66+
# conf[section] = "./"
67+
# else:
68+
# conf[section] = os.path.join(base_path, part)
69+
# else: # Assume items is dictionary like
70+
# add_base_path(part, items, base_path)

Diff for: src/oidcmsg/configure.py

+124-43
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@
99
from oidcmsg.logging import configure_logging
1010
from oidcmsg.util import load_yaml_config
1111

12-
DEFAULT_FILE_ATTRIBUTE_NAMES = ['server_key', 'server_cert', 'filename', 'template_dir',
13-
'private_path', 'public_path', 'db_file']
12+
DEFAULT_FILE_ATTRIBUTE_NAMES = ['server_key', 'server_cert', 'filename',
13+
'private_path', 'public_path', 'db_file', 'jwks_file']
1414

15-
URIS = ["redirect_uris", 'issuer', 'base_url']
15+
DEFAULT_DIR_ATTRIBUTE_NAMES = ['template_dir']
1616

1717

1818
def lower_or_upper(config, param, default=None):
@@ -22,17 +22,31 @@ def lower_or_upper(config, param, default=None):
2222
return res
2323

2424

25-
def add_base_path(conf: dict, base_path: str, file_attributes: List[str]):
25+
def add_path_to_filename(filename, base_path):
26+
if filename == "" or filename.startswith("/"):
27+
return filename
28+
else:
29+
return os.path.join(base_path, filename)
30+
31+
32+
def add_path_to_directory_name(directory_name, base_path):
33+
if directory_name.startswith("/"):
34+
return directory_name
35+
elif directory_name == "":
36+
return "./" + directory_name
37+
else:
38+
return os.path.join(base_path, directory_name)
39+
40+
41+
def add_base_path(conf: dict, base_path: str, attributes: List[str], attribute_type: str = "file"):
2642
for key, val in conf.items():
27-
if key in file_attributes:
28-
if val.startswith("/"):
29-
continue
30-
elif val == "":
31-
conf[key] = "./" + val
43+
if key in attributes:
44+
if attribute_type == "file":
45+
conf[key] = add_path_to_filename(val, base_path)
3246
else:
33-
conf[key] = os.path.join(base_path, val)
47+
conf[key] = add_path_to_directory_name(val, base_path)
3448
if isinstance(val, dict):
35-
conf[key] = add_base_path(val, base_path, file_attributes)
49+
conf[key] = add_base_path(val, base_path, attributes, attribute_type)
3650

3751
return conf
3852

@@ -53,41 +67,71 @@ def set_domain_and_port(conf: dict, uris: List[str], domain: str, port: int):
5367
return conf
5468

5569

56-
class Base:
70+
class Base(dict):
5771
""" Configuration base class """
5872

73+
parameter = {}
74+
uris = ["issuer", "base_url"]
75+
5976
def __init__(self,
6077
conf: Dict,
6178
base_path: str = '',
6279
file_attributes: Optional[List[str]] = None,
80+
dir_attributes: Optional[List[str]] = None,
81+
domain: Optional[str] = "",
82+
port: Optional[int] = 0,
6383
):
84+
dict.__init__(self)
85+
self._file_attributes = file_attributes or DEFAULT_FILE_ATTRIBUTE_NAMES
86+
self._dir_attributes = dir_attributes or DEFAULT_DIR_ATTRIBUTE_NAMES
6487

65-
if file_attributes is None:
66-
file_attributes = DEFAULT_FILE_ATTRIBUTE_NAMES
67-
68-
if base_path and file_attributes:
88+
if base_path:
6989
# this adds a base path to all paths in the configuration
70-
add_base_path(conf, base_path, file_attributes)
90+
if self._file_attributes:
91+
add_base_path(conf, base_path, self._file_attributes, "file")
92+
if self._dir_attributes:
93+
add_base_path(conf, base_path, self._dir_attributes, "dir")
7194

72-
def __getitem__(self, item):
73-
if item in self.__dict__:
74-
return self.__dict__[item]
95+
# entity info
96+
self.domain = domain or conf.get("domain", "127.0.0.1")
97+
self.port = port or conf.get("port", 80)
98+
99+
self.conf = set_domain_and_port(conf, self.uris, self.domain, self.port)
100+
101+
def __getattr__(self, item, default=None):
102+
if item in self:
103+
return self[item]
75104
else:
76-
raise KeyError
105+
return default
77106

78-
def get(self, item, default=None):
79-
return getattr(self, item, default)
107+
def __setattr__(self, key, value):
108+
if key in self:
109+
raise KeyError('{} has already been set'.format(key))
110+
super(Base, self).__setitem__(key, value)
111+
112+
def __setitem__(self, key, value):
113+
if key in self:
114+
raise KeyError('{} has already been set'.format(key))
115+
super(Base, self).__setitem__(key, value)
80116

81-
def __contains__(self, item):
82-
return item in self.__dict__
117+
def get(self, item, default=None):
118+
return self.__getattr__(item, default)
83119

84120
def items(self):
85-
for key in self.__dict__:
121+
for key in self.keys():
86122
if key.startswith('__') and key.endswith('__'):
87123
continue
88124
yield key, getattr(self, key)
89125

90-
def extend(self, entity_conf, conf, base_path, file_attributes, domain, port):
126+
def extend(self,
127+
conf: Dict,
128+
base_path: str,
129+
domain: str,
130+
port: int,
131+
entity_conf: Optional[List[dict]] = None,
132+
file_attributes: Optional[List[str]] = None,
133+
dir_attributes: Optional[List[str]] = None,
134+
):
91135
for econf in entity_conf:
92136
_path = econf.get("path")
93137
_cnf = conf
@@ -98,11 +142,49 @@ def extend(self, entity_conf, conf, base_path, file_attributes, domain, port):
98142
_cls = econf["class"]
99143
setattr(self, _attr,
100144
_cls(_cnf, base_path=base_path, file_attributes=file_attributes,
101-
domain=domain, port=port))
145+
domain=domain, port=port, dir_attributes=dir_attributes))
146+
147+
def complete_paths(self, conf: Dict, keys: List[str], default_config: Dict, base_path: str):
148+
for key in keys:
149+
_val = conf.get(key)
150+
if _val is None and key in default_config:
151+
_val = default_config[key]
152+
if key in self._file_attributes:
153+
_val = add_path_to_filename(_val, base_path)
154+
elif key in self._dir_attributes:
155+
_val = add_path_to_directory_name(_val, base_path)
156+
if not _val:
157+
continue
158+
159+
setattr(self, key, _val)
160+
161+
def format(self, conf, base_path: str, domain: str, port: int,
162+
file_attributes: Optional[List[str]] = None,
163+
dir_attributes: Optional[List[str]] = None) -> None:
164+
"""
165+
Formats parts of the configuration. That includes replacing the strings {domain} and {port}
166+
with the used domain and port and making references to files and directories absolute
167+
rather then relative. The formatting is done in place.
168+
169+
:param dir_attributes:
170+
:param conf: The configuration part
171+
:param base_path: The base path used to make file/directory refrences absolute
172+
:param file_attributes: Attribute names that refer to files or directories.
173+
:param domain: The domain name
174+
:param port: The port used
175+
"""
176+
if isinstance(conf, dict):
177+
if file_attributes:
178+
add_base_path(conf, base_path, file_attributes, attribute_type="file")
179+
if dir_attributes:
180+
add_base_path(conf, base_path, dir_attributes, attribute_type="dir")
181+
if isinstance(conf, dict):
182+
set_domain_and_port(conf, self.uris, domain=domain, port=port)
102183

103184

104185
class Configuration(Base):
105-
"""Server Configuration"""
186+
"""Entity Configuration Base"""
187+
uris = ["redirect_uris", 'issuer', 'base_url', 'server_name']
106188

107189
def __init__(self,
108190
conf: Dict,
@@ -111,27 +193,24 @@ def __init__(self,
111193
file_attributes: Optional[List[str]] = None,
112194
domain: Optional[str] = "",
113195
port: Optional[int] = 0,
196+
dir_attributes: Optional[List[str]] = None,
114197
):
115-
Base.__init__(self, conf, base_path=base_path, file_attributes=file_attributes)
198+
Base.__init__(self, conf, base_path=base_path, file_attributes=file_attributes,
199+
dir_attributes=dir_attributes, domain=domain, port=port)
116200

117-
log_conf = conf.get('logging')
201+
log_conf = self.conf.get('logging')
118202
if log_conf:
119203
self.logger = configure_logging(config=log_conf).getChild(__name__)
120204
else:
121205
self.logger = logging.getLogger('oidcrp')
122206

123-
self.web_conf = lower_or_upper(conf, "webserver")
124-
125-
# entity info
126-
if not domain:
127-
domain = conf.get("domain", "127.0.0.1")
128-
129-
if not port:
130-
port = conf.get("port", 80)
207+
self.web_conf = lower_or_upper(self.conf, "webserver")
131208

132209
if entity_conf:
133-
self.extend(entity_conf=entity_conf, conf=conf, base_path=base_path,
134-
file_attributes=file_attributes, domain=domain, port=port)
210+
self.extend(conf=self.conf, base_path=base_path,
211+
domain=self.domain, port=self.port, entity_conf=entity_conf,
212+
file_attributes=self._file_attributes,
213+
dir_attributes=self._dir_attributes)
135214

136215

137216
def create_from_config_file(cls,
@@ -140,7 +219,9 @@ def create_from_config_file(cls,
140219
entity_conf: Optional[List[dict]] = None,
141220
file_attributes: Optional[List[str]] = None,
142221
domain: Optional[str] = "",
143-
port: Optional[int] = 0):
222+
port: Optional[int] = 0,
223+
dir_attributes: Optional[List[str]] = None
224+
):
144225
if filename.endswith(".yaml"):
145226
"""Load configuration as YAML"""
146227
_cnf = load_yaml_config(filename)
@@ -158,4 +239,4 @@ def create_from_config_file(cls,
158239
return cls(_cnf,
159240
entity_conf=entity_conf,
160241
base_path=base_path, file_attributes=file_attributes,
161-
domain=domain, port=port)
242+
domain=domain, port=port, dir_attributes=dir_attributes)

Diff for: tests/server_conf.json

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
"httpc_params": {
3939
"verify": false
4040
},
41+
"hash_seed": "MustangSally",
4142
"keys": {
4243
"private_path": "private/jwks.json",
4344
"key_defs": [

Diff for: tests/test_03_time_util.py

-6
Original file line numberDiff line numberDiff line change
@@ -258,9 +258,3 @@ def test_later_than_str():
258258
b = in_a_while(seconds=20)
259259
assert later_than(b, a)
260260
assert later_than(a, b) is False
261-
262-
263-
def test_utc_time():
264-
utc_now = utc_time_sans_frac()
265-
expected_utc_now = int((datetime.utcnow() - datetime(1970, 1, 1)).total_seconds())
266-
assert utc_now == expected_utc_now

Diff for: tests/test_20_config.py

+7-16
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
from oidcmsg.configure import Configuration
1111
from oidcmsg.configure import create_from_config_file
1212
from oidcmsg.configure import lower_or_upper
13-
from oidcmsg.configure import set_domain_and_port
1413
from oidcmsg.util import rndstr
1514

1615
_dirname = os.path.dirname(os.path.abspath(__file__))
@@ -26,23 +25,14 @@ def __init__(self,
2625
domain: Optional[str] = "",
2726
port: Optional[int] = 0,
2827
file_attributes: Optional[List[str]] = None,
29-
uris: Optional[List[str]] = None
28+
uris: Optional[List[str]] = None,
29+
dir_attributes: Optional[List[str]] = None
3030
):
31-
32-
Base.__init__(self, conf, base_path=base_path, file_attributes=file_attributes)
31+
Base.__init__(self, conf, base_path=base_path, file_attributes=file_attributes,
32+
dir_attributes=dir_attributes)
3333

3434
self.keys = lower_or_upper(conf, 'keys')
3535

36-
if not domain:
37-
domain = conf.get("domain", "127.0.0.1")
38-
39-
if not port:
40-
port = conf.get("port", 80)
41-
42-
if uris is None:
43-
uris = URIS
44-
conf = set_domain_and_port(conf, uris, domain, port)
45-
4636
self.hash_seed = lower_or_upper(conf, 'hash_seed', rndstr(32))
4737
self.base_url = conf.get("base_url")
4838
self.httpc_params = conf.get("httpc_params", {"verify": False})
@@ -74,5 +64,6 @@ def test_entity_config(filename):
7464
assert configuration.httpc_params == {"verify": False}
7565
assert configuration['keys']
7666
ni = dict(configuration.items())
77-
assert len(ni) == 4
78-
assert set(ni.keys()) == {'keys', 'base_url', 'httpc_params', 'hash_seed'}
67+
assert len(ni) == 9
68+
assert set(ni.keys()) == {'base_url', '_dir_attributes', '_file_attributes', 'hash_seed',
69+
'httpc_params', 'keys', 'conf', 'port', 'domain'}

0 commit comments

Comments
 (0)