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

Commit cffdd46

Browse files
committed
State Import/Export base class.
Used for OidcContext
1 parent c754070 commit cffdd46

File tree

7 files changed

+150
-130
lines changed

7 files changed

+150
-130
lines changed

src/oidcmsg/context.py

Lines changed: 9 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,8 @@
44
from cryptojwt import KeyJar
55
from cryptojwt.key_jar import init_key_jar
66

7+
from oidcmsg.impexp import ImpExp
78
from oidcmsg.message import Message
8-
from oidcmsg.storage.init import get_storage_conf
9-
from oidcmsg.storage.init import init_storage
10-
from oidcmsg.storage.init import storage_factory
119

1210

1311
def add_issuer(conf, issuer):
@@ -22,44 +20,24 @@ def add_issuer(conf, issuer):
2220
return res
2321

2422

25-
class OidcContext:
23+
class OidcContext(ImpExp):
24+
parameter = {"keyjar": KeyJar, "issuer": None}
25+
2626
def __init__(self, config=None, keyjar=None, entity_id=''):
27+
ImpExp.__init__(self)
2728
if config is None:
2829
config = {}
2930

30-
self.db_conf = config.get('db_conf')
31-
if self.db_conf:
32-
_iss = config.get('issuer')
33-
if _iss:
34-
self.db_conf = add_issuer(self.db_conf, _iss)
35-
36-
if self.db_conf.get('default'):
37-
self.db = init_storage(self.db_conf)
38-
else:
39-
self.db = init_storage()
40-
else:
41-
self.db = init_storage()
42-
43-
self.keyjar = self._keyjar(keyjar, self.db_conf, config, entity_id=entity_id)
44-
45-
def add_boxes(self, boxes, db_conf):
46-
for key, attr in boxes.items():
47-
setattr(self, attr, init_storage(db_conf, key))
31+
self.issuer = entity_id
32+
self.keyjar = self._keyjar(keyjar, conf=config, entity_id=entity_id)
4833

49-
def _keyjar(self, keyjar=None, db_conf=None, conf=None, entity_id=''):
34+
def _keyjar(self, keyjar=None, conf=None, entity_id=''):
5035
if keyjar is None:
51-
_storage = None
52-
if db_conf:
53-
_cnf = get_storage_conf(db_conf, 'keyjar')
54-
if _cnf:
55-
_storage = storage_factory(_cnf)
56-
5736
if 'keys' in conf:
5837
args = {k: v for k, v in conf["keys"].items() if k != "uri_path"}
59-
args.update({'storage': _storage})
6038
_keyjar = init_key_jar(**args)
6139
else:
62-
_keyjar = KeyJar(storage=_storage)
40+
_keyjar = KeyJar()
6341
if 'jwks' in conf:
6442
_keyjar.import_jwks(conf['jwks'], '')
6543

@@ -74,15 +52,3 @@ def _keyjar(self, keyjar=None, db_conf=None, conf=None, entity_id=''):
7452
return _keyjar
7553
else:
7654
return keyjar
77-
78-
def set(self, item, value):
79-
if isinstance(value, Message):
80-
self.db[item] = value.to_dict()
81-
else:
82-
self.db[item] = value
83-
84-
def get(self, item):
85-
if item == 'seed':
86-
return bytes(self.db[item], 'utf-8')
87-
else:
88-
return self.db[item]

src/oidcmsg/impexp.py

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import copy
2+
from typing import Optional
3+
from urllib.parse import quote_plus
4+
5+
from cryptojwt.utils import importer
6+
from cryptojwt.utils import qualified_name
7+
8+
from oidcmsg.message import Message
9+
10+
11+
def add_issuer(conf, issuer):
12+
res = {}
13+
for key, val in conf.items():
14+
if key == 'abstract_storage_cls':
15+
res[key] = val
16+
else:
17+
_val = copy.copy(val)
18+
_val['issuer'] = quote_plus(issuer)
19+
res[key] = _val
20+
return res
21+
22+
23+
class ImpExp:
24+
parameter = {}
25+
26+
def __init__(self):
27+
pass
28+
29+
def _dump(self, cls, item, cutoff: Optional[list] = None):
30+
if cls in [None, "", [], {}]:
31+
val = item
32+
elif isinstance(item, Message):
33+
val = {qualified_name(item.__class__): item.to_dict()}
34+
elif cls == object:
35+
val = qualified_name(item)
36+
elif isinstance(cls, list):
37+
val = [self._dump(cls[0], v, cutoff) for v in item]
38+
else:
39+
val = item.dump(cutoff=cutoff)
40+
41+
return val
42+
43+
def dump(self, cutoff: Optional[list] = None) -> dict:
44+
_cutoff = cutoff or []
45+
info = {}
46+
for attr, cls in self.parameter.items():
47+
if attr in _cutoff:
48+
continue
49+
50+
item = getattr(self, attr, None)
51+
if item is None:
52+
continue
53+
54+
info[attr] = self._dump(cls, item, cutoff)
55+
56+
return info
57+
58+
def _local_adjustments(self):
59+
pass
60+
61+
def _load(self, cls, item):
62+
if cls in [None, "", [], {}]:
63+
val = item
64+
elif cls == object:
65+
val = importer(item)
66+
elif isinstance(cls, list):
67+
val = [cls[0]().load(v) for v in item]
68+
elif issubclass(cls, Message):
69+
val = cls().from_dict(item)
70+
else:
71+
val = cls().load(item)
72+
73+
return val
74+
75+
def load(self, item: dict):
76+
for attr, cls in self.parameter.items():
77+
if attr not in item:
78+
continue
79+
80+
setattr(self, attr, self._load(cls, item[attr]))
81+
82+
self._local_adjustments()
83+
return self
84+
85+
def flush(self):
86+
"""
87+
Reset the content of the instance to its pristine state
88+
89+
:return: A reference to the instance itself
90+
"""
91+
for attr, cls in self.parameter.items():
92+
if cls is None:
93+
setattr(self, attr, None)
94+
elif cls == "":
95+
setattr(self, attr, "")
96+
elif cls == []:
97+
setattr(self, attr, [])
98+
elif cls == {}:
99+
setattr(self, attr, {})
100+
else:
101+
setattr(self, attr, None)
102+
return self

src/oidcmsg/storage/converter.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ def deserialize(self, str):
1212

1313

1414
class JSON:
15-
def serialize(self, str):
16-
return json.dumps(str)
15+
def serialize(self, item):
16+
return json.dumps(item)
1717

1818
def deserialize(self, str):
1919
return json.loads(str)

tests/data/keys/cert.key

Lines changed: 0 additions & 27 deletions
This file was deleted.

tests/data/keys/jwk.json

Lines changed: 0 additions & 12 deletions
This file was deleted.

tests/data/keys/rsa.key

Lines changed: 0 additions & 15 deletions
This file was deleted.

tests/test_12_context.py

Lines changed: 37 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -31,56 +31,62 @@
3131
}
3232

3333

34-
def test_context():
34+
def test_dump_load():
3535
c = OidcContext({})
3636
assert c.keyjar is not None
37+
mem = c.dump()
38+
c2 = OidcContext().load(mem)
39+
assert c2.keyjar is not None
3740

3841

39-
class TestContext(object):
42+
class TestDumpLoad(object):
4043
@pytest.fixture(autouse=True)
4144
def setup(self):
42-
try:
43-
shutil.rmtree('db')
44-
except FileNotFoundError:
45-
pass
46-
4745
self.conf = {
48-
'issuer': 'https://example.com',
49-
'db_conf': {
50-
'keyjar': {
51-
'handler': 'oidcmsg.storage.abfile.LabeledAbstractFileSystem',
52-
'fdir': 'db/keyjar',
53-
'key_conv': 'oidcmsg.storage.converter.QPKey',
54-
'value_conv': 'cryptojwt.serialize.item.KeyIssuer',
55-
'label': 'foo'
56-
},
57-
'default': {
58-
'handler': 'oidcmsg.storage.abfile.AbstractFileSystem',
59-
'fdir': 'db',
60-
'key_conv': 'oidcmsg.storage.converter.QPKey',
61-
'value_conv': 'oidcmsg.storage.converter.JSON'
62-
}
63-
}
46+
'issuer': 'https://example.com'
6447
}
6548

6649
def test_context_with_entity_id_no_keys(self):
6750
c = OidcContext(self.conf, entity_id='https://example.com')
68-
assert c.keyjar.owners() == []
51+
mem = c.dump()
52+
c2 = OidcContext().load(mem)
53+
assert c2.keyjar.owners() == []
54+
assert c2.issuer == 'https://example.com'
6955

7056
def test_context_with_entity_id_and_keys(self):
7157
conf = copy.deepcopy(self.conf)
7258
conf['keys'] = {'key_defs': KEYDEF}
73-
7459
c = OidcContext(conf, entity_id='https://example.com')
75-
assert set(c.keyjar.owners()) == {'', 'https://example.com'}
60+
61+
mem = c.dump()
62+
c2 = OidcContext().load(mem)
63+
assert set(c2.keyjar.owners()) == {'', 'https://example.com'}
7664

7765
def test_context_with_entity_id_and_jwks(self):
7866
conf = copy.deepcopy(self.conf)
7967
conf['jwks'] = JWKS
68+
c = OidcContext(conf, entity_id='https://example.com')
69+
70+
mem = c.dump()
71+
c2 = OidcContext().load(mem)
72+
73+
assert set(c2.keyjar.owners()) == {'', 'https://example.com'}
74+
assert len(c2.keyjar.get('sig', 'RSA')) == 1
75+
assert len(c2.keyjar.get('sig', 'RSA', issuer_id='https://example.com')) == 1
76+
assert len(c2.keyjar.get('sig', 'oct')) == 1
77+
assert len(c2.keyjar.get('sig', 'oct', issuer_id='https://example.com')) == 1
78+
79+
def test_context_restore(self):
80+
conf = copy.deepcopy(self.conf)
81+
conf['keys'] = {'key_defs': KEYDEF}
8082

8183
c = OidcContext(conf, entity_id='https://example.com')
82-
assert set(c.keyjar.owners()) == {'', 'https://example.com'}
83-
assert len(c.keyjar.get('sig', 'RSA')) == 1
84-
assert len(c.keyjar.get('sig', 'RSA', issuer_id='https://example.com')) == 1
85-
assert len(c.keyjar.get('sig', 'oct')) == 1
86-
assert len(c.keyjar.get('sig', 'oct', issuer_id='https://example.com')) == 1
84+
mem = c.dump()
85+
c2 = OidcContext().load(mem)
86+
87+
assert set(c2.keyjar.owners()) == {'', 'https://example.com'}
88+
assert len(c2.keyjar.get('sig', 'EC')) == 1
89+
assert len(c2.keyjar.get('enc', 'EC')) == 1
90+
assert len(c.keyjar.get('sig', 'RSA')) == 0
91+
assert len(c.keyjar.get('sig', 'oct')) == 0
92+

0 commit comments

Comments
 (0)