Skip to content

Commit

Permalink
redis value extended by email
Browse files Browse the repository at this point in the history
  • Loading branch information
utku-ozturk committed Oct 30, 2023
1 parent ab88729 commit e7edf82
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 8 deletions.
26 changes: 19 additions & 7 deletions dcicutils/redis_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,12 @@ def _build_redis_key(namespace: str, token: str) -> str:
"""
return f'{namespace}:session:{token}'

def __init__(self, *, namespace: str, jwt: str, token=None, expiration=None):
def __init__(self, *, namespace: str, jwt: str, email: str, token=None, expiration=None):
""" Creates a Redis Session object, storing a hash of the JWT into Redis and returning this
value as the session token.
:param namespace: namespace to build key under, for example the env name
:param jwt: jwt generated for this user
:param email: email verified for this user
:param token: value of token if passed, if not one will be generated
:param expiration: expiration of token if passed, if not new expiration will be generated
"""
Expand All @@ -59,11 +60,12 @@ def __init__(self, *, namespace: str, jwt: str, token=None, expiration=None):
self.namespace = namespace
self.redis_key = self._build_redis_key(self.namespace, self.session_token)
self.jwt = jwt
self.email = email
self.expiration = expiration or self._build_session_expiration()

def __eq__(self, other):
""" Evaluates equality of two session objects based on the value of the session hset """
return (self.redis_key == other.redis_key) and (self.jwt == other.jwt)
return (self.redis_key == other.redis_key) and (self.jwt == other.jwt) and (self.email == other.email)

def get_session_token(self) -> str:
""" Extracts the session token stored on this object """
Expand All @@ -80,6 +82,10 @@ def get_expiration(self) -> datetime:
def get_jwt(self) -> str:
""" Returns the JWT set on this session token object """
return self.jwt

def get_email(self) -> str:
""" Returns the email set on this session token object """
return self.email

@classmethod
def from_redis(cls, *, redis_handler: RedisBase, namespace: str, token: str):
Expand All @@ -93,27 +99,31 @@ def from_redis(cls, *, redis_handler: RedisBase, namespace: str, token: str):
redis_key = f'{namespace}:session:{token}'
redis_entry = redis_handler.get(redis_key)
if redis_entry:
jwt_and_email = redis_entry.split(':')
jwt = jwt_and_email[0]
email = jwt_and_email[1] if len(jwt_and_email) > 1 else None
expiration = redis_handler.ttl(redis_key)
return cls(namespace=namespace, jwt=redis_entry,
return cls(namespace=namespace, jwt=jwt, email=email,
token=token, expiration=expiration)

def decode_jwt(self, audience: str, secret: str, leeway: int = 30) -> dict:
def decode_jwt(self, audience: str, secret: str, leeway: int = 30, algorithms: list = ['HS256']) -> dict:
""" Decodes JWT to grab info such as the email
:param audience: audience under which to decode, typically Auth0Client
:param secret: secret to decrypt using, typically Auth0Secret
:param leeway: numerical value in seconds to account for clock drift
:return: a decoded JWT in dictionary format
"""
#TODO: verify_signature should be True
return jwt.decode(self.jwt, secret, audience=audience, leeway=leeway,
options={'verify_signature': True}, algorithms=['HS256'])
options={'verify_signature': False}, algorithms=algorithms)

def store_session_token(self, *, redis_handler: RedisBase) -> bool:
""" Stores the created session token object as an hset in Redis
:param redis_handler: handle to Redis API
:return: True if successful, raise Exception otherwise
"""
try:
redis_handler.set(self.redis_key, self.jwt, exp=self.expiration)
redis_handler.set(self.redis_key, f'{self.jwt}:{self.email or ""}', exp=self.expiration)
except Exception as e:
log.error(str(e))
raise RedisException()
Expand All @@ -129,10 +139,11 @@ def validate_session_token(self, *, redis_handler: RedisBase) -> bool:
return False # if it doesn't exist it's not valid
return True # if it does exist it must be valid since we always send with TTL

def update_session_token(self, *, redis_handler: RedisBase, jwt: str) -> bool:
def update_session_token(self, *, redis_handler: RedisBase, jwt: str, email: str) -> bool:
""" Refreshes the session token, jwt (if different) and expiration stored in Redis
:param redis_handler: handle to Redis API
:param jwt: jwt of user
:param email: email of user
:return: True if successful, raise Exception otherwise
"""
# remove old token
Expand All @@ -142,6 +153,7 @@ def update_session_token(self, *, redis_handler: RedisBase, jwt: str) -> bool:
self.redis_key = self._build_redis_key(self.namespace, self.session_token)
self.expiration = self._build_session_expiration()
self.jwt = jwt
self.email = email
return self.store_session_token(redis_handler=redis_handler)

def delete_session_token(self, *, redis_handler: RedisBase) -> bool:
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "dcicutils"
version = "8.0.0"
version = "8.0.0.1c1"
description = "Utility package for interacting with the 4DN Data Portal and other 4DN resources"
authors = ["4DN-DCIC Team <support@4dnucleome.org>"]
license = "MIT"
Expand Down

0 comments on commit e7edf82

Please sign in to comment.