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

Commit d4146f9

Browse files
authored
Merge pull request #90 from IdentityPython/write_once
Made the Base configuration class a write once dictionary.
2 parents 8b6b755 + 5266705 commit d4146f9

3 files changed

Lines changed: 93 additions & 73 deletions

File tree

src/oidcop/configure.py

Lines changed: 79 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,6 @@ def add_base_path(conf: Union[dict, str], base_path: str, file_attributes: List[
105105
return conf
106106

107107

108-
URIS = ["issuer", "base_url"]
109-
110-
111108
def set_domain_and_port(conf: dict, uris: List[str], domain: str, port: int):
112109
for key, val in conf.items():
113110
if key in uris:
@@ -154,42 +151,59 @@ def create_from_config_file(
154151
)
155152

156153

157-
class Base:
154+
class Base(dict):
158155
""" Configuration base class """
159156

160157
parameter = {}
161158

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

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

172-
def __getitem__(self, item):
173-
if item in self.__dict__:
174-
return self.__dict__[item]
175-
else:
176-
raise KeyError
177-
178-
def get(self, item, default=None):
179-
return getattr(self, item, default)
171+
def __getattr__(self, item):
172+
return self[item]
180173

181-
def __contains__(self, item):
182-
return item in self.__dict__
174+
def __setattr__(self, key, value):
175+
if key in self:
176+
raise KeyError('{} has already been set'.format(key))
177+
super(Base, self).__setitem__(key, value)
183178

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

190184

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

194208
def __init__(
195209
self,
@@ -204,72 +218,64 @@ def __init__(
204218
conf = copy.deepcopy(conf)
205219
Base.__init__(self, conf, base_path, file_attributes)
206220

207-
self.add_on = None
208-
self.authz = None
209-
self.authentication = None
210-
self.base_url = ""
211-
self.capabilities = None
212-
self.claims_interface = None
213-
self.cookie_handler = None
214-
self.endpoint = {}
215-
self.httpc_params = {}
216-
self.issuer = ""
217-
self.keys = None
218-
self.template_dir = None
219-
self.token_handler_args = {}
220-
self.userinfo = None
221-
self.session_params = None
222-
223221
if file_attributes is None:
224222
file_attributes = DEFAULT_FILE_ATTRIBUTE_NAMES
225223

226-
for key in self.__dict__.keys():
224+
if not domain:
225+
domain = conf.get("domain", "127.0.0.1")
226+
227+
if not port:
228+
port = conf.get("port", 80)
229+
230+
for key in self.parameter.keys():
227231
_val = conf.get(key)
228232
if not _val:
229233
if key in self.default_config:
230-
_dc = copy.deepcopy(self.default_config[key])
231-
add_base_path(_dc, base_path, file_attributes)
232-
_val = _dc
234+
_val = copy.deepcopy(self.default_config[key])
235+
self.format(_val, base_path=base_path, file_attributes=file_attributes,
236+
domain=domain, port=port)
233237
else:
234238
continue
235-
setattr(self, key, _val)
236239

237-
if self.template_dir is None:
238-
self.template_dir = os.path.abspath("templates")
239-
else:
240-
self.template_dir = os.path.abspath(self.template_dir)
240+
if key == "template_dir":
241+
_val = os.path.abspath(_val)
241242

242-
if not domain:
243-
domain = conf.get("domain", "127.0.0.1")
244-
245-
if not port:
246-
port = conf.get("port", 80)
243+
setattr(self, key, _val)
247244

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

250268

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

274280
class ASConfiguration(EntityConfiguration):
275281
"Authorization server configuration"
@@ -290,6 +296,7 @@ def __init__(
290296

291297
class Configuration(Base):
292298
"""Server Configuration"""
299+
uris = ["issuer", "base_url"]
293300

294301
def __init__(
295302
self,
@@ -316,7 +323,7 @@ def __init__(
316323
if not port:
317324
port = conf.get("port", 80)
318325

319-
set_domain_and_port(conf, URIS, domain=domain, port=port)
326+
set_domain_and_port(conf, self.uris, domain=domain, port=port)
320327

321328
if entity_conf:
322329
for econf in entity_conf:
@@ -511,7 +518,8 @@ def __init__(
511518
"login_hint2acrs": {
512519
"class": "oidcop.login_hint.LoginHint2Acrs",
513520
"kwargs": {
514-
"scheme_map": {"email": ["urn:oasis:names:tc:SAML:2.0:ac:classes:InternetProtocolPassword"]}
521+
"scheme_map": {
522+
"email": ["urn:oasis:names:tc:SAML:2.0:ac:classes:InternetProtocolPassword"]}
515523
},
516524
},
517525
"template_dir": "templates",

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)