2022-01-15 00:23:50 +00:00
|
|
|
import logging
|
|
|
|
import time
|
|
|
|
from typing import Optional, Dict, Any, Tuple
|
2022-04-11 05:23:55 +00:00
|
|
|
import jwt
|
|
|
|
from jwt import PyJWTError
|
2022-01-15 00:23:50 +00:00
|
|
|
|
2022-04-14 02:10:25 +00:00
|
|
|
from app.classes.models.users import HelperUsers, ApiKeys
|
2022-06-20 19:26:21 +00:00
|
|
|
from app.classes.controllers.management_controller import ManagementController
|
2022-03-08 04:40:44 +00:00
|
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
2022-01-15 00:23:50 +00:00
|
|
|
|
2022-03-23 02:50:12 +00:00
|
|
|
|
2022-01-15 00:23:50 +00:00
|
|
|
class Authentication:
|
2022-04-11 05:23:55 +00:00
|
|
|
def __init__(self, helper):
|
|
|
|
self.helper = helper
|
2022-01-15 00:23:50 +00:00
|
|
|
self.secret = "my secret"
|
2022-06-20 19:26:21 +00:00
|
|
|
try:
|
|
|
|
self.secret = ManagementController.get_crafty_api_key()
|
|
|
|
if self.secret == "":
|
|
|
|
self.secret = self.helper.random_string_generator(64)
|
|
|
|
ManagementController.set_crafty_api_key(str(self.secret))
|
|
|
|
except:
|
2022-04-11 05:23:55 +00:00
|
|
|
self.secret = self.helper.random_string_generator(64)
|
2022-06-20 19:26:21 +00:00
|
|
|
ManagementController.set_crafty_api_key(str(self.secret))
|
2022-01-15 00:23:50 +00:00
|
|
|
|
2022-04-11 05:23:55 +00:00
|
|
|
def generate(self, user_id, extra=None):
|
2022-01-15 00:23:50 +00:00
|
|
|
if extra is None:
|
|
|
|
extra = {}
|
2022-04-10 19:39:31 +00:00
|
|
|
jwt_encoded = jwt.encode(
|
2022-03-23 02:50:12 +00:00
|
|
|
{"user_id": user_id, "iat": int(time.time()), **extra},
|
2022-04-11 05:23:55 +00:00
|
|
|
self.secret,
|
2022-03-23 02:50:12 +00:00
|
|
|
algorithm="HS256",
|
2022-01-15 00:23:50 +00:00
|
|
|
)
|
2022-04-10 19:39:31 +00:00
|
|
|
return jwt_encoded
|
2022-01-15 00:23:50 +00:00
|
|
|
|
2022-04-11 05:23:55 +00:00
|
|
|
def read(self, token):
|
|
|
|
return jwt.decode(token, self.secret, algorithms=["HS256"])
|
2022-01-15 00:23:50 +00:00
|
|
|
|
2022-04-11 05:23:55 +00:00
|
|
|
def check_no_iat(self, token) -> Optional[Dict[str, Any]]:
|
2022-01-15 00:23:50 +00:00
|
|
|
try:
|
2022-04-14 12:33:53 +00:00
|
|
|
return jwt.decode(str(token), self.secret, algorithms=["HS256"])
|
2022-01-15 00:23:50 +00:00
|
|
|
except PyJWTError as error:
|
|
|
|
logger.debug("Error while checking JWT token: ", exc_info=error)
|
|
|
|
return None
|
|
|
|
|
2022-03-23 02:50:12 +00:00
|
|
|
def check(
|
2022-04-11 05:23:55 +00:00
|
|
|
self,
|
2022-03-23 02:50:12 +00:00
|
|
|
token,
|
|
|
|
) -> Optional[Tuple[Optional[ApiKeys], Dict[str, Any], Dict[str, Any]]]:
|
2022-01-15 00:23:50 +00:00
|
|
|
try:
|
2022-04-14 12:33:53 +00:00
|
|
|
data = jwt.decode(str(token), self.secret, algorithms=["HS256"])
|
2022-01-15 00:23:50 +00:00
|
|
|
except PyJWTError as error:
|
|
|
|
logger.debug("Error while checking JWT token: ", exc_info=error)
|
|
|
|
return None
|
2022-03-23 02:50:12 +00:00
|
|
|
iat: int = data["iat"]
|
2022-01-15 00:23:50 +00:00
|
|
|
key: Optional[ApiKeys] = None
|
2022-03-23 02:50:12 +00:00
|
|
|
if "token_id" in data:
|
|
|
|
key_id = data["token_id"]
|
2022-04-14 02:10:25 +00:00
|
|
|
key = HelperUsers.get_user_api_key(key_id)
|
2022-01-15 00:23:50 +00:00
|
|
|
if key is None:
|
|
|
|
return None
|
2022-03-23 02:50:12 +00:00
|
|
|
user_id: str = data["user_id"]
|
2022-04-14 02:10:25 +00:00
|
|
|
user = HelperUsers.get_user(user_id)
|
2022-03-23 06:06:13 +00:00
|
|
|
# TODO: Have a cache or something so we don't constantly
|
|
|
|
# have to query the database
|
2022-03-23 02:50:12 +00:00
|
|
|
if int(user.get("valid_tokens_from").timestamp()) < iat:
|
2022-01-15 00:23:50 +00:00
|
|
|
# Success!
|
|
|
|
return key, data, user
|
2022-06-14 12:40:57 +00:00
|
|
|
return None
|
2022-01-15 00:23:50 +00:00
|
|
|
|
2022-04-14 12:33:53 +00:00
|
|
|
def check_err(
|
|
|
|
self,
|
|
|
|
token,
|
|
|
|
) -> Tuple[Optional[ApiKeys], Dict[str, Any], Dict[str, Any]]:
|
|
|
|
# Without this function there would be runtime exceptions like the following:
|
|
|
|
# "None" object is not iterable
|
|
|
|
|
|
|
|
output = self.check(token)
|
|
|
|
if output is None:
|
|
|
|
raise Exception("Invalid token")
|
|
|
|
return output
|
|
|
|
|
2022-04-11 05:23:55 +00:00
|
|
|
def check_bool(self, token) -> bool:
|
|
|
|
return self.check(token) is not None
|