51 lines
		
	
	
		
			1.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			51 lines
		
	
	
		
			1.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
import time
 | 
						|
 | 
						|
import jwt
 | 
						|
from pydantic import TypeAdapter
 | 
						|
from pydantic.dataclasses import dataclass
 | 
						|
 | 
						|
 | 
						|
@dataclass(frozen=True)
 | 
						|
class DecodedJWT:
 | 
						|
    token_type: str
 | 
						|
    exp: int
 | 
						|
    iat: int
 | 
						|
    jti: str
 | 
						|
    user_id: int
 | 
						|
 | 
						|
 | 
						|
@dataclass(frozen=True)
 | 
						|
class Token:
 | 
						|
    access: str
 | 
						|
    refresh: str
 | 
						|
 | 
						|
    @property
 | 
						|
    def user_id(self) -> int:
 | 
						|
        access_decoded = self.__decode(self.access)
 | 
						|
        return access_decoded.user_id
 | 
						|
 | 
						|
    @property
 | 
						|
    def is_expired(self) -> bool:
 | 
						|
        now = int(time.time())
 | 
						|
        refresh_decoded = self.__decode(self.refresh)
 | 
						|
        return (now - 10) > refresh_decoded.exp
 | 
						|
 | 
						|
    @property
 | 
						|
    def is_refresh_required(self) -> bool:
 | 
						|
        now = int(time.time())
 | 
						|
        access_decoded = self.__decode(self.access)
 | 
						|
        refresh_decoded = self.__decode(self.refresh)
 | 
						|
        return (now + 10) > access_decoded.exp and (now - 10) < refresh_decoded.exp
 | 
						|
 | 
						|
    def __decode(self, token: str) -> DecodedJWT:
 | 
						|
        data = jwt.decode(token, options={"verify_signature": False})  # type: ignore
 | 
						|
        return TypeAdapter(DecodedJWT).validate_python(data)
 | 
						|
 | 
						|
 | 
						|
@dataclass(frozen=True)
 | 
						|
class User:
 | 
						|
    id: int
 | 
						|
    username: str
 | 
						|
    laboratory_ids: list[int]
 | 
						|
    is_reviewer: bool
 |