authorization: update for changes in the database
Since the User DB is not going to be large cache the users in local memory and sync with the DB when changes are made to the local user store. Signed-off-by: Eric Callahan <arksine.code@gmail.com>
This commit is contained in:
parent
46f74329d3
commit
b43f4623fc
|
@ -75,7 +75,8 @@ class Authorization:
|
||||||
self.force_logins = config.getboolean('force_logins', False)
|
self.force_logins = config.getboolean('force_logins', False)
|
||||||
database: DBComp = self.server.lookup_component('database')
|
database: DBComp = self.server.lookup_component('database')
|
||||||
database.register_local_namespace('authorized_users', forbidden=True)
|
database.register_local_namespace('authorized_users', forbidden=True)
|
||||||
self.users = database.wrap_namespace('authorized_users')
|
self.user_db = database.wrap_namespace('authorized_users')
|
||||||
|
self.users: Dict[str, Dict[str, Any]] = self.user_db.as_dict()
|
||||||
api_user: Optional[Dict[str, Any]] = self.users.get(API_USER, None)
|
api_user: Optional[Dict[str, Any]] = self.users.get(API_USER, None)
|
||||||
if api_user is None:
|
if api_user is None:
|
||||||
self.api_key = uuid.uuid4().hex
|
self.api_key = uuid.uuid4().hex
|
||||||
|
@ -126,7 +127,8 @@ class Authorization:
|
||||||
self.users[username] = user_info
|
self.users[username] = user_info
|
||||||
continue
|
continue
|
||||||
self.public_jwks[jwk_id] = self._generate_public_jwk(priv_key)
|
self.public_jwks[jwk_id] = self._generate_public_jwk(priv_key)
|
||||||
|
# sync user changes to the database
|
||||||
|
self.user_db.sync(self.users)
|
||||||
self.trusted_users: Dict[IPAddr, Any] = {}
|
self.trusted_users: Dict[IPAddr, Any] = {}
|
||||||
self.oneshot_tokens: Dict[str, OneshotToken] = {}
|
self.oneshot_tokens: Dict[str, OneshotToken] = {}
|
||||||
self.permitted_paths: Set[str] = set()
|
self.permitted_paths: Set[str] = set()
|
||||||
|
@ -229,6 +231,9 @@ class Authorization:
|
||||||
self.server.register_notification("authorization:user_created")
|
self.server.register_notification("authorization:user_created")
|
||||||
self.server.register_notification("authorization:user_deleted")
|
self.server.register_notification("authorization:user_deleted")
|
||||||
|
|
||||||
|
def _sync_user(self, username: str) -> None:
|
||||||
|
self.user_db[username] = self.users[username]
|
||||||
|
|
||||||
async def component_init(self) -> None:
|
async def component_init(self) -> None:
|
||||||
self.prune_timer.start(delay=PRUNE_CHECK_TIME)
|
self.prune_timer.start(delay=PRUNE_CHECK_TIME)
|
||||||
|
|
||||||
|
@ -236,7 +241,8 @@ class Authorization:
|
||||||
action = web_request.get_action()
|
action = web_request.get_action()
|
||||||
if action.upper() == 'POST':
|
if action.upper() == 'POST':
|
||||||
self.api_key = uuid.uuid4().hex
|
self.api_key = uuid.uuid4().hex
|
||||||
self.users[f'{API_USER}.api_key'] = self.api_key
|
self.users[API_USER]['api_key'] = self.api_key
|
||||||
|
self._sync_user(API_USER)
|
||||||
return self.api_key
|
return self.api_key
|
||||||
|
|
||||||
async def _handle_oneshot_request(self, web_request: WebRequest) -> str:
|
async def _handle_oneshot_request(self, web_request: WebRequest) -> str:
|
||||||
|
@ -256,8 +262,9 @@ class Authorization:
|
||||||
if username in RESERVED_USERS:
|
if username in RESERVED_USERS:
|
||||||
raise self.server.error(
|
raise self.server.error(
|
||||||
f"Invalid log out request for user {username}")
|
f"Invalid log out request for user {username}")
|
||||||
self.users.pop(f"{username}.jwt_secret", None)
|
self.users[username].pop("jwt_secret", None)
|
||||||
jwk_id: str = self.users.pop(f"{username}.jwk_id", "")
|
jwk_id: str = self.users[username].pop("jwk_id", None)
|
||||||
|
self._sync_user(username)
|
||||||
self.public_jwks.pop(jwk_id, None)
|
self.public_jwks.pop(jwk_id, None)
|
||||||
return {
|
return {
|
||||||
"username": username,
|
"username": username,
|
||||||
|
@ -342,7 +349,8 @@ class Authorization:
|
||||||
raise self.server.error("Invalid Password")
|
raise self.server.error("Invalid Password")
|
||||||
new_hashed_pass = hashlib.pbkdf2_hmac(
|
new_hashed_pass = hashlib.pbkdf2_hmac(
|
||||||
'sha256', new_pass.encode(), salt, HASH_ITER).hex()
|
'sha256', new_pass.encode(), salt, HASH_ITER).hex()
|
||||||
self.users[f'{username}.password'] = new_hashed_pass
|
self.users[username]['password'] = new_hashed_pass
|
||||||
|
self._sync_user(username)
|
||||||
return {
|
return {
|
||||||
'username': username,
|
'username': username,
|
||||||
'action': "user_password_reset"
|
'action': "user_password_reset"
|
||||||
|
@ -371,6 +379,7 @@ class Authorization:
|
||||||
'created_on': time.time()
|
'created_on': time.time()
|
||||||
}
|
}
|
||||||
self.users[username] = user_info
|
self.users[username] = user_info
|
||||||
|
self._sync_user(username)
|
||||||
action = "user_created"
|
action = "user_created"
|
||||||
else:
|
else:
|
||||||
if username not in self.users:
|
if username not in self.users:
|
||||||
|
@ -389,6 +398,7 @@ class Authorization:
|
||||||
user_info['jwt_secret'] = private_key.hex_seed().decode()
|
user_info['jwt_secret'] = private_key.hex_seed().decode()
|
||||||
user_info['jwk_id'] = jwk_id
|
user_info['jwk_id'] = jwk_id
|
||||||
self.users[username] = user_info
|
self.users[username] = user_info
|
||||||
|
self._sync_user(username)
|
||||||
self.public_jwks[jwk_id] = self._generate_public_jwk(private_key)
|
self.public_jwks[jwk_id] = self._generate_public_jwk(private_key)
|
||||||
else:
|
else:
|
||||||
private_key = self._load_private_key(jwt_secret_hex)
|
private_key = self._load_private_key(jwt_secret_hex)
|
||||||
|
@ -424,8 +434,10 @@ class Authorization:
|
||||||
user_info: Optional[Dict[str, Any]] = self.users.get(username)
|
user_info: Optional[Dict[str, Any]] = self.users.get(username)
|
||||||
if user_info is None:
|
if user_info is None:
|
||||||
raise self.server.error(f"No registered user: {username}")
|
raise self.server.error(f"No registered user: {username}")
|
||||||
self.public_jwks.pop(self.users.get(f"{username}.jwk_id"), None)
|
if 'jwk_id' in user_info:
|
||||||
|
self.public_jwks.pop(user_info['jwk_id'], None)
|
||||||
del self.users[username]
|
del self.users[username]
|
||||||
|
del self.user_db[username]
|
||||||
event_loop = self.server.get_event_loop()
|
event_loop = self.server.get_event_loop()
|
||||||
event_loop.delay_callback(
|
event_loop.delay_callback(
|
||||||
.005, self.server.send_event,
|
.005, self.server.send_event,
|
||||||
|
|
Loading…
Reference in New Issue