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

Commit d139f1f

Browse files
authored
Merge pull request #28 from IdentityPython/external_storage
External storage
2 parents 5f3fdf7 + 0825881 commit d139f1f

12 files changed

+245
-151
lines changed

.travis.yml

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
dist: bionic
12
sudo: false
23
language: python
34
python:

setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ def run_tests(self):
6161
"Programming Language :: Python :: 3.8",
6262
"Topic :: Software Development :: Libraries :: Python Modules"],
6363
install_requires=[
64-
"cryptojwt>=1.1.0",
64+
"cryptojwt>=1.5.0",
6565
"pyOpenSSL",
6666
"filelock>=3.0.12"
6767
],

src/oidcmsg/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
__author__ = 'Roland Hedberg'
2-
__version__ = '1.1.4'
2+
__version__ = '1.2.0'
33

44
import os
55

src/oidcmsg/context.py

+9-43
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

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

src/oidcmsg/storage/abfile.py

+17-19
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import logging
22
import os
33
import time
4+
from urllib.parse import quote_plus
45

56
from filelock import FileLock
67

@@ -23,7 +24,7 @@ class AbstractFileSystem(Storage):
2324
Not directories in directories.
2425
"""
2526

26-
def __init__(self, conf_dict):
27+
def __init__(self, conf_dict, ):
2728
"""
2829
items = FileSystem(
2930
{
@@ -44,15 +45,12 @@ def __init__(self, conf_dict):
4445

4546
super().__init__(conf_dict)
4647
self.config = conf_dict
47-
_fdir = conf_dict.get('fdir', '')
48-
if '{issuer}' in _fdir:
49-
issuer = conf_dict.get('issuer')
50-
if not issuer:
51-
raise ValueError('Missing issuer value')
52-
self.fdir = _fdir.format(issuer=issuer)
53-
else:
54-
self.fdir = _fdir
5548

49+
_fdir = conf_dict.get('fdir', '.')
50+
if "issuer" in conf_dict:
51+
_fdir = os.path.join(_fdir, quote_plus(conf_dict["issuer"]))
52+
53+
self.fdir = _fdir
5654
self.fmtime = {}
5755
self.storage = {}
5856

@@ -87,11 +85,13 @@ def __getitem__(self, item):
8785
:return:
8886
"""
8987
item = self.key_conv.serialize(item)
90-
if self._is_file(item):
91-
if self.is_changed(item):
92-
logger.info("File content change in {}".format(item))
93-
fname = os.path.join(self.fdir, item)
94-
self.storage[item] = self._read_info(fname)
88+
fname = os.path.join(self.fdir, item)
89+
if self._is_file(fname):
90+
lock = FileLock('{}.lock'.format(fname))
91+
with lock:
92+
if self.is_changed(item, fname):
93+
logger.info("File content change in {}".format(item))
94+
self.storage[item] = self._read_info(fname)
9595

9696
logger.debug('Read from "%s"', item)
9797
return self.storage[item]
@@ -165,19 +165,17 @@ def get_mtime(fname):
165165

166166
return mtime
167167

168-
def _is_file(self, item):
169-
fname = os.path.join(self.fdir, item)
168+
def _is_file(self, fname):
170169
return os.path.isfile(fname)
171170

172-
def is_changed(self, item):
171+
def is_changed(self, item, fname):
173172
"""
174173
Find out if this item has been modified since last.
175174
When I get here I know that item points to an existing file.
176175
177176
:param item: A key
178177
:return: True/False
179178
"""
180-
fname = os.path.join(self.fdir, item)
181179
mtime = self.get_mtime(fname)
182180

183181
try:
@@ -223,7 +221,7 @@ def synch(self):
223221
continue
224222

225223
if f in self.fmtime:
226-
if self.is_changed(f):
224+
if self.is_changed(f, fname):
227225
self.storage[f] = self._read_info(fname)
228226
else:
229227
mtime = self.get_mtime(fname)

src/oidcmsg/storage/converter.py

+2-2
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

-27
This file was deleted.

tests/data/keys/jwk.json

-12
This file was deleted.

tests/data/keys/rsa.key

-15
This file was deleted.

0 commit comments

Comments
 (0)