2023-10-26 20:38:31 +00:00
|
|
|
from datetime import datetime, timedelta, timezone
|
2023-10-26 21:07:35 +00:00
|
|
|
|
|
|
|
from auth.jwtcodec import JWTCodec
|
2023-10-26 17:56:42 +00:00
|
|
|
from validations.auth import AuthInput
|
2023-10-26 21:07:35 +00:00
|
|
|
from base.redis import redis
|
|
|
|
from settings import SESSION_TOKEN_LIFE_SPAN, ONETIME_TOKEN_LIFE_SPAN
|
2022-09-17 18:12:14 +00:00
|
|
|
|
|
|
|
|
|
|
|
async def save(token_key, life_span, auto_delete=True):
|
|
|
|
await redis.execute("SET", token_key, "True")
|
|
|
|
if auto_delete:
|
2022-11-23 14:09:35 +00:00
|
|
|
expire_at = (datetime.now(tz=timezone.utc) + timedelta(seconds=life_span)).timestamp()
|
2022-09-17 18:12:14 +00:00
|
|
|
await redis.execute("EXPIREAT", token_key, int(expire_at))
|
|
|
|
|
|
|
|
|
2022-11-24 14:31:52 +00:00
|
|
|
class SessionToken:
|
|
|
|
@classmethod
|
|
|
|
async def verify(cls, token: str):
|
|
|
|
"""
|
|
|
|
Rules for a token to be valid.
|
|
|
|
- token format is legal
|
|
|
|
- token exists in redis database
|
|
|
|
- token is not expired
|
|
|
|
"""
|
|
|
|
try:
|
|
|
|
return JWTCodec.decode(token)
|
|
|
|
except Exception as e:
|
|
|
|
raise e
|
|
|
|
|
|
|
|
@classmethod
|
2023-01-31 06:57:35 +00:00
|
|
|
async def get(cls, payload, token):
|
|
|
|
return await TokenStorage.get(f"{payload.user_id}-{payload.username}-{token}")
|
2022-11-24 14:31:52 +00:00
|
|
|
|
|
|
|
|
2022-09-17 18:12:14 +00:00
|
|
|
class TokenStorage:
|
|
|
|
@staticmethod
|
|
|
|
async def get(token_key):
|
2023-10-26 21:07:35 +00:00
|
|
|
print('[tokenstorage.get] ' + token_key)
|
2023-01-31 06:57:35 +00:00
|
|
|
# 2041-user@domain.zn-eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoyMDQxLCJ1c2VybmFtZSI6ImFudG9uLnJld2luK3Rlc3QtbG9hZGNoYXRAZ21haWwuY29tIiwiZXhwIjoxNjcxNzgwNjE2LCJpYXQiOjE2NjkxODg2MTYsImlzcyI6ImRpc2NvdXJzIn0.Nml4oV6iMjMmc6xwM7lTKEZJKBXvJFEIZ-Up1C1rITQ
|
2022-09-17 18:12:14 +00:00
|
|
|
return await redis.execute("GET", token_key)
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
async def create_onetime(user: AuthInput) -> str:
|
|
|
|
life_span = ONETIME_TOKEN_LIFE_SPAN
|
2022-11-13 23:38:06 +00:00
|
|
|
exp = datetime.now(tz=timezone.utc) + timedelta(seconds=life_span)
|
2022-10-31 21:25:25 +00:00
|
|
|
one_time_token = JWTCodec.encode(user, exp)
|
2023-01-31 06:57:35 +00:00
|
|
|
await save(f"{user.id}-{user.username}-{one_time_token}", life_span)
|
2022-09-17 18:12:14 +00:00
|
|
|
return one_time_token
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
async def create_session(user: AuthInput) -> str:
|
|
|
|
life_span = SESSION_TOKEN_LIFE_SPAN
|
2022-11-13 23:38:06 +00:00
|
|
|
exp = datetime.now(tz=timezone.utc) + timedelta(seconds=life_span)
|
2022-10-31 21:25:25 +00:00
|
|
|
session_token = JWTCodec.encode(user, exp)
|
2023-01-31 06:57:35 +00:00
|
|
|
await save(f"{user.id}-{user.username}-{session_token}", life_span)
|
2022-09-17 18:12:14 +00:00
|
|
|
return session_token
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
async def revoke(token: str) -> bool:
|
2022-11-23 09:57:58 +00:00
|
|
|
payload = None
|
2022-09-17 18:12:14 +00:00
|
|
|
try:
|
2022-11-23 09:57:58 +00:00
|
|
|
print("[auth.tokenstorage] revoke token")
|
2022-09-17 18:12:14 +00:00
|
|
|
payload = JWTCodec.decode(token)
|
|
|
|
except: # noqa
|
|
|
|
pass
|
2022-11-23 13:34:34 +00:00
|
|
|
else:
|
2023-01-31 06:57:35 +00:00
|
|
|
await redis.execute("DEL", f"{payload.user_id}-{payload.username}-{token}")
|
2022-09-17 18:12:14 +00:00
|
|
|
return True
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
async def revoke_all(user: AuthInput):
|
|
|
|
tokens = await redis.execute("KEYS", f"{user.id}-*")
|
|
|
|
await redis.execute("DEL", *tokens)
|