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

Commit cf1450a

Browse files
committed
Made the Base class a write once dictionary.
As a side effect 'endpoint' now MUST have a value. It can not be {}.
1 parent a01c7c1 commit cf1450a

3 files changed

Lines changed: 94 additions & 76 deletions

File tree

src/oidcop/configure.py

Lines changed: 80 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@
6767
},
6868
"httpc_params": {"verify": False},
6969
"issuer": "https://{domain}:{port}",
70-
"session_key": {"filename": "private/session_jwk.json", "type": "OCT", "use": "sig", },
70+
# "session_key": {"filename": "private/session_jwk.json", "type": "OCT", "use": "sig", },
7171
"template_dir": "templates",
7272
"token_handler_args": {
7373
"jwks_file": "private/token_jwks.json",
@@ -106,9 +106,6 @@ def add_base_path(conf: Union[dict, str], base_path: str, file_attributes: List[
106106
return conf
107107

108108

109-
URIS = ["issuer", "base_url"]
110-
111-
112109
def set_domain_and_port(conf: dict, uris: List[str], domain: str, port: int):
113110
for key, val in conf.items():
114111
if key in uris:
@@ -155,42 +152,59 @@ def create_from_config_file(
155152
)
156153

157154

158-
class Base:
155+
class Base(dict):
159156
""" Configuration base class """
160157

161158
parameter = {}
162159

163160
def __init__(
164161
self, conf: Dict, base_path: str = "", file_attributes: Optional[List[str]] = None,
165162
):
163+
dict.__init__(self)
164+
166165
if file_attributes is None:
167166
file_attributes = DEFAULT_FILE_ATTRIBUTE_NAMES
168167

169168
if base_path and file_attributes:
170169
# this adds a base path to all paths in the configuration
171170
add_base_path(conf, base_path, file_attributes)
172171

173-
def __getitem__(self, item):
174-
if item in self.__dict__:
175-
return self.__dict__[item]
176-
else:
177-
raise KeyError
172+
def __getattr__(self, item):
173+
return self[item]
178174

179-
def get(self, item, default=None):
180-
return getattr(self, item, default)
175+
def __setattr__(self, key, value):
176+
if key in self:
177+
raise KeyError('{} has already been set'.format(key))
178+
super(Base, self).__setitem__(key, value)
181179

182-
def __contains__(self, item):
183-
return item in self.__dict__
184-
185-
def items(self):
186-
for key in self.__dict__:
187-
if key.startswith("__") and key.endswith("__"):
188-
continue
189-
yield key, getattr(self, key)
180+
def __setitem__(self, key, value):
181+
if key in self:
182+
raise KeyError('{} has already been set'.format(key))
183+
super(Base, self).__setitem__(key, value)
190184

191185

192186
class EntityConfiguration(Base):
193187
default_config = AS_DEFAULT_CONFIG
188+
uris = ["issuer", "base_url"]
189+
parameter = {
190+
"add_on": None,
191+
"authz": None,
192+
"authentication": None,
193+
"base_url": "",
194+
"capabilities": None,
195+
"claims_interface": None,
196+
"cookie_handler": None,
197+
"endpoint": {},
198+
"httpc_params": {},
199+
"issuer": "",
200+
"keys": None,
201+
"session_key": None,
202+
"template_dir": None,
203+
"token_handler_args": {},
204+
"userinfo": None,
205+
"password": None,
206+
"salt": None,
207+
}
194208

195209
def __init__(
196210
self,
@@ -205,74 +219,64 @@ def __init__(
205219
conf = copy.deepcopy(conf)
206220
Base.__init__(self, conf, base_path, file_attributes)
207221

208-
self.add_on = None
209-
self.authz = None
210-
self.authentication = None
211-
self.base_url = ""
212-
self.capabilities = None
213-
self.claims_interface = None
214-
self.cookie_handler = None
215-
self.endpoint = {}
216-
self.httpc_params = {}
217-
self.issuer = ""
218-
self.keys = None
219-
self.session_key = None
220-
self.template_dir = None
221-
self.token_handler_args = {}
222-
self.userinfo = None
223-
self.password = None
224-
self.salt = None
225-
226222
if file_attributes is None:
227223
file_attributes = DEFAULT_FILE_ATTRIBUTE_NAMES
228224

229-
for key in self.__dict__.keys():
225+
if not domain:
226+
domain = conf.get("domain", "127.0.0.1")
227+
228+
if not port:
229+
port = conf.get("port", 80)
230+
231+
for key in self.parameter.keys():
230232
_val = conf.get(key)
231233
if not _val:
232234
if key in self.default_config:
233-
_dc = copy.deepcopy(self.default_config[key])
234-
add_base_path(_dc, base_path, file_attributes)
235-
_val = _dc
235+
_val = copy.deepcopy(self.default_config[key])
236+
self.format(_val, base_path=base_path, file_attributes=file_attributes,
237+
domain=domain, port=port)
236238
else:
237239
continue
238-
setattr(self, key, _val)
239240

240-
if self.template_dir is None:
241-
self.template_dir = os.path.abspath("templates")
242-
else:
243-
self.template_dir = os.path.abspath(self.template_dir)
244-
245-
if not domain:
246-
domain = conf.get("domain", "127.0.0.1")
241+
if key == "template_dir":
242+
_val = os.path.abspath(_val)
247243

248-
if not port:
249-
port = conf.get("port", 80)
244+
setattr(self, key, _val)
250245

251-
set_domain_and_port(conf, URIS, domain=domain, port=port)
246+
# try:
247+
# _dir = self.template_dir
248+
# except AttributeError:
249+
# self.template_dir = os.path.abspath("templates")
250+
# else:
251+
# self.template_dir =
252+
253+
def format(self, conf, base_path, file_attributes, domain, port):
254+
"""
255+
Formats parts of the configuration. That includes replacing the strings {domain} and {port}
256+
with the used domain and port and making references to files and directories absolute
257+
rather then relative. The formatting is done in place.
258+
259+
:param conf: The configuration part
260+
:param base_path: The base path used to make file/directory refrences absolute
261+
:param file_attributes: Attribute names that refer to files or directories.
262+
:param domain: The domain name
263+
:param port: The port used
264+
"""
265+
add_base_path(conf, base_path, file_attributes)
266+
if isinstance(conf, dict):
267+
set_domain_and_port(conf, self.uris, domain=domain, port=port)
252268

253269

254270
class OPConfiguration(EntityConfiguration):
255271
"Provider configuration"
256272
default_config = OP_DEFAULT_CONFIG
257-
258-
def __init__(
259-
self,
260-
conf: Dict,
261-
base_path: Optional[str] = "",
262-
entity_conf: Optional[List[dict]] = None,
263-
domain: Optional[str] = "",
264-
port: Optional[int] = 0,
265-
file_attributes: Optional[List[str]] = None,
266-
):
267-
# OP special
268-
self.id_token = None
269-
self.login_hint2acrs = {}
270-
self.login_hint_lookup = None
271-
self.sub_func = {}
272-
273-
EntityConfiguration.__init__(self, conf=conf, base_path=base_path,
274-
entity_conf=entity_conf, domain=domain, port=port,
275-
file_attributes=file_attributes)
273+
parameter = EntityConfiguration.parameter.copy()
274+
parameter.update({
275+
"id_token": None,
276+
"login_hint2acrs": {},
277+
"login_hint_lookup": None,
278+
"sub_func": {}
279+
})
276280

277281

278282
class ASConfiguration(EntityConfiguration):
@@ -294,6 +298,7 @@ def __init__(
294298

295299
class Configuration(Base):
296300
"""Server Configuration"""
301+
uris = ["issuer", "base_url"]
297302

298303
def __init__(
299304
self,
@@ -320,7 +325,7 @@ def __init__(
320325
if not port:
321326
port = conf.get("port", 80)
322327

323-
set_domain_and_port(conf, URIS, domain=domain, port=port)
328+
set_domain_and_port(conf, self.uris, domain=domain, port=port)
324329

325330
if entity_conf:
326331
for econf in entity_conf:
@@ -515,7 +520,8 @@ def __init__(
515520
"login_hint2acrs": {
516521
"class": "oidcop.login_hint.LoginHint2Acrs",
517522
"kwargs": {
518-
"scheme_map": {"email": ["urn:oasis:names:tc:SAML:2.0:ac:classes:InternetProtocolPassword"]}
523+
"scheme_map": {
524+
"email": ["urn:oasis:names:tc:SAML:2.0:ac:classes:InternetProtocolPassword"]}
519525
},
520526
},
521527
"session_key": {"filename": "private/session_jwk.json", "type": "OCT", "use": "sig", },

tests/test_12_user_authn.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,13 @@ def create_endpoint_context(self):
3333
"password": "mycket hemligt",
3434
"grant_expires_in": 300,
3535
"verify_ssl": False,
36-
"endpoint": {},
36+
"endpoint": {
37+
"authorization": {
38+
"path": "{}/authorization",
39+
"class": 'oidcop.oidc.authorization.Authorization',
40+
"kwargs": {},
41+
}
42+
},
3743
"keys": {"uri_path": "static/jwks.json", "key_defs": KEYDEFS},
3844
"authentication": {
3945
"user": {

tests/test_24_oidc_authorization_endpoint.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1054,7 +1054,13 @@ def create_endpoint_context(self):
10541054
"grant_expires_in": 300,
10551055
"refresh_token_expires_in": 86400,
10561056
"verify_ssl": False,
1057-
"endpoint": {},
1057+
"endpoint": {
1058+
"authorization": {
1059+
"path": "{}/authorization",
1060+
"class": Authorization,
1061+
"kwargs": {},
1062+
}
1063+
},
10581064
"keys": {"uri_path": "static/jwks.json", "key_defs": KEYDEFS},
10591065
"authentication": {
10601066
"user": {

0 commit comments

Comments
 (0)