change username, email and password, token login
parent
bd0eeec213
commit
28e72d7467
|
@ -199,27 +199,31 @@
|
|||
},
|
||||
"cryptography": {
|
||||
"hashes": [
|
||||
"sha256:059e348f9a3c1950937e1b5d7ba1f8e968508ab181e75fc32b879452f08356db",
|
||||
"sha256:1a5472d40c8f8e91ff7a3d8ac6dfa363d8e3138b961529c996f3e2df0c7a411a",
|
||||
"sha256:1a8e6c2de6fbbcc5e14fd27fb24414507cb3333198ea9ab1258d916f00bc3039",
|
||||
"sha256:1fee5aacc7367487b4e22484d3c7e547992ed726d14864ee33c0176ae43b0d7c",
|
||||
"sha256:5d092fdfedaec4cbbffbf98cddc915ba145313a6fdaab83c6e67f4e6c218e6f3",
|
||||
"sha256:5f0ff6e18d13a3de56f609dd1fd11470918f770c6bd5d00d632076c727d35485",
|
||||
"sha256:7bfc55a5eae8b86a287747053140ba221afc65eb06207bedf6e019b8934b477c",
|
||||
"sha256:7fa01527046ca5facdf973eef2535a27fec4cb651e4daec4d043ef63f6ecd4ca",
|
||||
"sha256:8dde71c4169ec5ccc1087bb7521d54251c016f126f922ab2dfe6649170a3b8c5",
|
||||
"sha256:8f4ab7021127a9b4323537300a2acfb450124b2def3756f64dc3a3d2160ee4b5",
|
||||
"sha256:948224d76c4b6457349d47c0c98657557f429b4e93057cf5a2f71d603e2fc3a3",
|
||||
"sha256:9a6c7a3c87d595608a39980ebaa04d5a37f94024c9f24eb7d10262b92f739ddb",
|
||||
"sha256:b46e37db3cc267b4dea1f56da7346c9727e1209aa98487179ee8ebed09d21e43",
|
||||
"sha256:b4ceb5324b998ce2003bc17d519080b4ec8d5b7b70794cbd2836101406a9be31",
|
||||
"sha256:cb33ccf15e89f7ed89b235cff9d49e2e62c6c981a6061c9c8bb47ed7951190bc",
|
||||
"sha256:d198820aba55660b4d74f7b5fd1f17db3aa5eb3e6893b0a41b75e84e4f9e0e4b",
|
||||
"sha256:d34579085401d3f49762d2f7d6634d6b6c2ae1242202e860f4d26b046e3a1006",
|
||||
"sha256:eb8163f5e549a22888c18b0d53d6bb62a20510060a22fd5a995ec8a05268df8a",
|
||||
"sha256:f73bff05db2a3e5974a6fd248af2566134d8981fd7ab012e5dd4ddb1d9a70699"
|
||||
"sha256:01f1d9e537f9a15b037d5d9ee442b8c22e3ae11ce65ea1f3316a41c78756b711",
|
||||
"sha256:079347de771f9282fbfe0e0236c716686950c19dee1b76240ab09ce1624d76d7",
|
||||
"sha256:182be4171f9332b6741ee818ec27daff9fb00349f706629f5cbf417bd50e66fd",
|
||||
"sha256:192255f539d7a89f2102d07d7375b1e0a81f7478925b3bc2e0549ebf739dae0e",
|
||||
"sha256:2a034bf7d9ca894720f2ec1d8b7b5832d7e363571828037f9e0c4f18c1b58a58",
|
||||
"sha256:342f3767e25876751e14f8459ad85e77e660537ca0a066e10e75df9c9e9099f0",
|
||||
"sha256:439c3cc4c0d42fa999b83ded80a9a1fb54d53c58d6e59234cfe97f241e6c781d",
|
||||
"sha256:49c3222bb8f8e800aead2e376cbef687bc9e3cb9b58b29a261210456a7783d83",
|
||||
"sha256:674b669d5daa64206c38e507808aae49904c988fa0a71c935e7006a3e1e83831",
|
||||
"sha256:7a9a3bced53b7f09da251685224d6a260c3cb291768f54954e28f03ef14e3766",
|
||||
"sha256:7af244b012711a26196450d34f483357e42aeddb04128885d95a69bd8b14b69b",
|
||||
"sha256:7d230bf856164de164ecb615ccc14c7fc6de6906ddd5b491f3af90d3514c925c",
|
||||
"sha256:84609ade00a6ec59a89729e87a503c6e36af98ddcd566d5f3be52e29ba993182",
|
||||
"sha256:9a6673c1828db6270b76b22cc696f40cde9043eb90373da5c2f8f2158957f42f",
|
||||
"sha256:9b6d717393dbae53d4e52684ef4f022444fc1cce3c48c38cb74fca29e1f08eaa",
|
||||
"sha256:9c3fe6534d59d071ee82081ca3d71eed3210f76ebd0361798c74abc2bcf347d4",
|
||||
"sha256:a719399b99377b218dac6cf547b6ec54e6ef20207b6165126a280b0ce97e0d2a",
|
||||
"sha256:b332cba64d99a70c1e0836902720887fb4529ea49ea7f5462cf6640e095e11d2",
|
||||
"sha256:d124682c7a23c9764e54ca9ab5b308b14b18eba02722b8659fb238546de83a76",
|
||||
"sha256:d73f419a56d74fef257955f51b18d046f3506270a5fd2ac5febbfa259d6c0fa5",
|
||||
"sha256:f0dc40e6f7aa37af01aba07277d3d64d5a03dc66d682097541ec4da03cc140ee",
|
||||
"sha256:f14ad275364c8b4e525d018f6716537ae7b6d369c094805cae45300847e0894f",
|
||||
"sha256:f772610fe364372de33d76edcd313636a25684edb94cee53fd790195f5989d14"
|
||||
],
|
||||
"version": "==41.0.1"
|
||||
"version": "==41.0.2"
|
||||
},
|
||||
"dnspython": {
|
||||
"hashes": [
|
||||
|
|
|
@ -46,7 +46,7 @@ def upgrade() -> None:
|
|||
sa.Column('location', sa.String(), nullable=True),
|
||||
sa.Column('status', sa.String(), nullable=True),
|
||||
sa.Column('sign', sa.String(), nullable=True),
|
||||
sa.Column('avatar', sa.String(), nullable=True),
|
||||
sa.Column('avatars', sa.String(), nullable=True),
|
||||
sa.Column('user_id', sa.String(length=26), nullable=False),
|
||||
sa.ForeignKeyConstraint(['user_id'], ['user_account.id'], ondelete='CASCADE'),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
|
|
|
@ -10,16 +10,20 @@ from ..database.db import async_session
|
|||
from ..database.models import UserAccount, UserProfile, Contact
|
||||
|
||||
|
||||
async def select_user_by(condition: Literal['email', 'username'], value: str) -> Tuple[bool, UserAccount]:
|
||||
async with async_session() as session:
|
||||
if condition == 'email':
|
||||
async def select_user_by(condition: Literal['email', 'username', 'id'], value: str) -> Tuple[bool, UserAccount]:
|
||||
session = async_session()
|
||||
res: ScalarResult[UserAccount] = ScalarResult[UserAccount]
|
||||
match condition:
|
||||
case 'email':
|
||||
res = await session.scalars(select(UserAccount).where(UserAccount.email == value))
|
||||
else:
|
||||
case 'username':
|
||||
res = await session.scalars(select(UserAccount).where(UserAccount.username == value))
|
||||
case 'id':
|
||||
res = await session.scalars(select(UserAccount).where(UserAccount.id == value))
|
||||
|
||||
user = res.first()
|
||||
user = res.first()
|
||||
|
||||
return (True, user) if user else (False, None)
|
||||
return (True, user) if user else (False, None)
|
||||
|
||||
|
||||
async def insert_user(username: str, password: str, email: str):
|
||||
|
@ -27,8 +31,10 @@ async def insert_user(username: str, password: str, email: str):
|
|||
id = ulid.new().str
|
||||
user = UserAccount(id=id, username=username, password=password, email=email)
|
||||
profile = UserProfile(nickname=username)
|
||||
contact = Contact(friends={id: {'friendRemark': None, 'friendGroup': '我的好友'}}, friend_groups=['我的好友'],
|
||||
group_chats={})
|
||||
contact = Contact(
|
||||
friends={id: {'friendRemark': None, 'friendGroup': '我的好友'}}, friend_groups=['我的好友'],
|
||||
group_chats={}
|
||||
)
|
||||
user.profile = profile
|
||||
user.contact = contact
|
||||
session.add(user)
|
||||
|
@ -75,3 +81,28 @@ async def update_profile_avatar(id: str, avatar_name: str):
|
|||
)
|
||||
await session.commit()
|
||||
await session.close()
|
||||
|
||||
|
||||
async def update_account(account: Literal['username', 'email', 'password'], id: str, value: str):
|
||||
session = async_session()
|
||||
match account:
|
||||
case 'username':
|
||||
await session.execute(
|
||||
update(UserAccount)
|
||||
.where(UserAccount.id == id)
|
||||
.values(username=value)
|
||||
)
|
||||
case 'email':
|
||||
await session.execute(
|
||||
update(UserAccount)
|
||||
.where(UserAccount.id == id)
|
||||
.values(email=value)
|
||||
)
|
||||
case 'password':
|
||||
await session.execute(
|
||||
update(UserAccount)
|
||||
.where(UserAccount.id == id)
|
||||
.values(password=value)
|
||||
)
|
||||
await session.commit()
|
||||
await session.close()
|
||||
|
|
|
@ -1,7 +1,16 @@
|
|||
from fastapi import Depends
|
||||
from fastapi.responses import Response, JSONResponse
|
||||
from jose import ExpiredSignatureError, JWTError
|
||||
|
||||
from .utils import token_handler as th
|
||||
|
||||
|
||||
def verify_token(token: str = Depends(th.oauth2_scheme)):
|
||||
th.verify_signin_token(token)
|
||||
def verify_token(response: Response, token: str = Depends(th.oauth2_scheme)):
|
||||
try:
|
||||
token, _ = th.verify_signin_token(token)
|
||||
if token:
|
||||
response.headers['Authorization'] = token
|
||||
except ExpiredSignatureError:
|
||||
return JSONResponse({'code': 9999, 'msg': 'Token Expire'})
|
||||
except JWTError:
|
||||
return JSONResponse({'code': 9998, 'msg': 'Token Is Not Right'})
|
||||
|
|
|
@ -1,15 +1,18 @@
|
|||
from fastapi import FastAPI, Depends
|
||||
|
||||
from .dependencies import verify_token
|
||||
from .utils.email_code import smtp
|
||||
from .routers.signin import router as signin_router
|
||||
from .routers.signup import router as signup_router
|
||||
from .routers.user_profile import router as user_profile_router
|
||||
from .routers.user_account import router as user_account_router
|
||||
|
||||
|
||||
app = FastAPI()
|
||||
app.include_router(signup_router)
|
||||
app.include_router(signin_router)
|
||||
app.include_router(user_profile_router)
|
||||
app.include_router(user_profile_router, dependencies=[Depends(verify_token)])
|
||||
app.include_router(user_account_router, dependencies=[Depends(verify_token)])
|
||||
|
||||
|
||||
@app.on_event('shutdown')
|
||||
|
|
|
@ -26,11 +26,17 @@ class UserAccountResponse(BaseResponseModel):
|
|||
|
||||
|
||||
class TokenCreationResponse(BaseResponseModel):
|
||||
data: str
|
||||
token: str
|
||||
|
||||
|
||||
class TokenSigninResponse(BaseResponseModel):
|
||||
data: Optional[_UserAccount] = None
|
||||
token: Optional[str] = None
|
||||
|
||||
|
||||
class UserProfileResponse(BaseResponseModel):
|
||||
data: _UserProfile
|
||||
|
||||
|
||||
class UserAvatarResponse(BaseResponseModel):
|
||||
data: str
|
||||
data: str
|
||||
|
|
|
@ -3,17 +3,19 @@ from fastapi import Depends
|
|||
from fastapi.security import OAuth2PasswordRequestForm
|
||||
from pydantic import BaseModel
|
||||
|
||||
from jose import ExpiredSignatureError, JWTError
|
||||
|
||||
from ..crud.user_crud import select_user_by
|
||||
from ..utils.password import verify_password
|
||||
from ..utils.token_handler import create_signin_token, oauth2_scheme
|
||||
from ..response_models.user_response import UserAccountResponse, TokenCreationResponse
|
||||
from ..utils.token_handler import create_signin_token, oauth2_scheme, verify_signin_token
|
||||
from ..response_models.user_response import UserAccountResponse, TokenCreationResponse, TokenSigninResponse
|
||||
|
||||
router = APIRouter(prefix='/signin', tags=['signin'])
|
||||
|
||||
|
||||
class TokenPayload(BaseModel):
|
||||
id: str
|
||||
phone_mac: str
|
||||
device_id: str
|
||||
|
||||
|
||||
@router.post('/username', response_model=UserAccountResponse)
|
||||
|
@ -36,9 +38,19 @@ async def signin_by_username(form_data: OAuth2PasswordRequestForm = Depends()):
|
|||
@router.post('/token', response_model=TokenCreationResponse)
|
||||
async def create_token(token_payload: TokenPayload):
|
||||
token = create_signin_token(**token_payload.model_dump())
|
||||
return {'code': 10200, 'msg': 'Create Token Successfully', 'data': token}
|
||||
return {'code': 10200, 'msg': 'Create Token Successfully', 'token': token}
|
||||
|
||||
|
||||
@router.get('/token')
|
||||
@router.get('/token', response_model=TokenSigninResponse)
|
||||
async def signin_by_token(token: str = Depends(oauth2_scheme)):
|
||||
pass
|
||||
try:
|
||||
new_token, id = verify_signin_token(token)
|
||||
_, user = await select_user_by('id', id)
|
||||
if new_token:
|
||||
return {'code': 10200, 'msg': 'Sign in Successfully', 'data': user.to_dict(), 'token': new_token}
|
||||
else:
|
||||
return {'code': 10200, 'msg': 'Sign in Successfully', 'data': user.to_dict(), 'token': token}
|
||||
except ExpiredSignatureError:
|
||||
return {'code': 9999, 'msg': 'Token has Expired', 'data': None, 'token': None}
|
||||
except JWTError:
|
||||
return {'code': 9998, 'msg': 'Token Is Not Right', 'data': None, 'token': None}
|
|
@ -0,0 +1,73 @@
|
|||
from fastapi import APIRouter, BackgroundTasks
|
||||
from pydantic import BaseModel
|
||||
|
||||
from ..crud import user_crud
|
||||
from ..utils import password
|
||||
from ..utils.email_code import send_email, has_code, verify_code
|
||||
|
||||
router = APIRouter(prefix='/user_account', tags=['user_account'])
|
||||
|
||||
|
||||
class ChangedAccount(BaseModel):
|
||||
id: str
|
||||
username: str | None = None
|
||||
email: str | None = None
|
||||
password: str | None = None
|
||||
code: str | None = None
|
||||
|
||||
|
||||
@router.post('/change/username')
|
||||
async def change_username(changed_account: ChangedAccount):
|
||||
is_existed, user = await user_crud.select_user_by('username', changed_account.username)
|
||||
if is_existed:
|
||||
return {'code': 10401, 'msg': f'This Username ({changed_account.username}) Has Been Used'}
|
||||
|
||||
await user_crud.update_account('username', changed_account.id, changed_account.username)
|
||||
|
||||
return {'code': 10400, 'msg': 'Update Username Successfully'}
|
||||
|
||||
|
||||
@router.get('/get/email_code')
|
||||
async def get_change_email_code(email: str, background_tasks: BackgroundTasks):
|
||||
is_existed, _ = await user_crud.select_user_by('email', email)
|
||||
if is_existed:
|
||||
return {'code': 10401, 'msg': f'This Email ({email}) Has Been Used'}
|
||||
|
||||
if has_code(email):
|
||||
return {'code': 10402, 'msg': f'Code of Email ({email}) Is Still Available'}
|
||||
|
||||
background_tasks.add_task(send_email, email)
|
||||
return {'code': 10400, 'msg': 'Send Verification Code Successfully'}
|
||||
|
||||
|
||||
@router.post('/change/email')
|
||||
async def change_email(changed_account: ChangedAccount):
|
||||
is_correct = verify_code(changed_account.email, changed_account.code)
|
||||
if not is_correct:
|
||||
return {'code': 10403, 'msg': f'Email Code ({changed_account.code}) Is Not Correct'}
|
||||
|
||||
await user_crud.update_account('email', changed_account.id, changed_account.email)
|
||||
|
||||
return {'code': 10400, 'msg': 'Update Email Successfully'}
|
||||
|
||||
|
||||
@router.get('/get/password_code')
|
||||
async def get_change_password_code(email: str, background_tasks: BackgroundTasks):
|
||||
if has_code(email):
|
||||
return {'code': 10402, 'msg': f'Code of Email ({email}) Is Still Available'}
|
||||
|
||||
background_tasks.add_task(send_email, email)
|
||||
return {'code': 10400, 'msg': 'Send Verification Code Successfully'}
|
||||
|
||||
|
||||
@router.post('/change/password')
|
||||
async def change_password(changed_account: ChangedAccount):
|
||||
is_correct = verify_code(changed_account.email, changed_account.code)
|
||||
if not is_correct:
|
||||
return {'code': 10403, 'msg': f'Email Code ({changed_account.code}) Is Not Correct'}
|
||||
|
||||
hashed_password = password.get_hashed_password(changed_account.password)
|
||||
|
||||
await user_crud.update_account('password', changed_account.id, hashed_password)
|
||||
|
||||
return {'code': 10400, 'msg': 'Update Email Successfully'}
|
|
@ -1,25 +1,25 @@
|
|||
from typing import Optional
|
||||
|
||||
from fastapi import APIRouter, Depends
|
||||
from fastapi import APIRouter
|
||||
from pydantic import BaseModel
|
||||
from fastapi.responses import FileResponse
|
||||
from fastapi.responses import FileResponse, JSONResponse
|
||||
from fastapi.encoders import jsonable_encoder
|
||||
|
||||
from anyio import open_file
|
||||
|
||||
from ..crud import user_crud
|
||||
from ..dependencies import verify_token
|
||||
from ..response_models.user_response import UserProfileResponse, UserAvatarResponse
|
||||
from ..utils import static_file
|
||||
|
||||
|
||||
router = APIRouter(prefix='/user_profile', tags=['user_profile'], dependencies=[Depends(verify_token)])
|
||||
router = APIRouter(prefix='/user_profile', tags=['user_profile'])
|
||||
|
||||
|
||||
class Uint8List(BaseModel):
|
||||
file: list
|
||||
|
||||
|
||||
class ModifiedProfile(BaseModel):
|
||||
class ChangedProfile(BaseModel):
|
||||
id: str
|
||||
nickname: Optional[str] = None
|
||||
location: Optional[str] = None
|
||||
|
@ -31,7 +31,11 @@ class ModifiedProfile(BaseModel):
|
|||
@router.get('/my', response_model=UserProfileResponse)
|
||||
async def get_profile(id: str):
|
||||
profile = await user_crud.select_profile(id)
|
||||
return {'code': 10300, 'msg': 'Get My Profile Successfully', 'data': profile.to_dict_all()}
|
||||
return JSONResponse(
|
||||
content=jsonable_encoder(
|
||||
{'code': 10300, 'msg': 'Get My Profile Successfully', 'data': profile.to_dict_all()},
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@router.get('/avatar')
|
||||
|
@ -40,8 +44,8 @@ async def download_avatar(avatar_filename: str):
|
|||
return FileResponse(avatar_dir_path / avatar_filename)
|
||||
|
||||
|
||||
@router.post('/modify/avatar', response_model=UserAvatarResponse)
|
||||
async def modify_avatar(id: str, file: Uint8List):
|
||||
@router.post('/change/avatar', response_model=UserAvatarResponse)
|
||||
async def change_avatar(id: str, file: Uint8List):
|
||||
avatar_dir_path = static_file.create_avatar_dir()
|
||||
avatar_filename = static_file.create_avatar_filename()
|
||||
|
||||
|
@ -53,22 +57,22 @@ async def modify_avatar(id: str, file: Uint8List):
|
|||
return {'code': 10300, 'msg': 'Update Avatar Successfully', 'data': avatar_filename}
|
||||
|
||||
|
||||
@router.post('/modify/{aspect}')
|
||||
async def modify_profile(aspect: str, modified_profile: ModifiedProfile):
|
||||
@router.post('/change/{aspect}')
|
||||
async def change_profile(aspect: str, changed_profile: ChangedProfile):
|
||||
match aspect:
|
||||
case 'basic':
|
||||
await user_crud.update_profile_basic(
|
||||
modified_profile.id,
|
||||
modified_profile.nickname,
|
||||
modified_profile.location,
|
||||
modified_profile.birthday,
|
||||
modified_profile.gender,
|
||||
changed_profile.id,
|
||||
changed_profile.nickname,
|
||||
changed_profile.location,
|
||||
changed_profile.birthday,
|
||||
changed_profile.gender,
|
||||
)
|
||||
case 'sign':
|
||||
await user_crud.update_profile_sign(
|
||||
modified_profile.id,
|
||||
modified_profile.sign
|
||||
changed_profile.id,
|
||||
changed_profile.sign
|
||||
)
|
||||
case _:
|
||||
return {'code': 10301, 'msg': f'No /modify/{aspect} Path'}
|
||||
return {'code': 10301, 'msg': f'No /change/{aspect} Path'}
|
||||
return {'code': 10300, 'msg': f'Update {aspect} Profile Successfully'}
|
|
@ -41,7 +41,6 @@ def send_email(to: str):
|
|||
|
||||
msg.set_content(email_content)
|
||||
smtp.send_message(msg)
|
||||
smtp.quit()
|
||||
|
||||
|
||||
def generate_code(email: str) -> str:
|
||||
|
@ -56,3 +55,9 @@ def verify_code(email: str, code: str) -> bool:
|
|||
key = f'code:{email}'
|
||||
value = redis_server.get(key)
|
||||
return code == value
|
||||
|
||||
|
||||
def has_code(email: str) -> bool:
|
||||
key = f'code:{email}'
|
||||
value = redis_server.get(key)
|
||||
return True if value else False
|
||||
|
|
|
@ -9,7 +9,7 @@ alphabet = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
|
|||
|
||||
|
||||
def create_avatar_dir() -> Path:
|
||||
avatar_dir_path = Path(os.getcwd()) / 'static' / 'avatar'
|
||||
avatar_dir_path = Path(os.getcwd()) / 'static' / 'avatars'
|
||||
if not avatar_dir_path.exists():
|
||||
avatar_dir_path.mkdir()
|
||||
return avatar_dir_path
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
from datetime import datetime, timedelta
|
||||
from typing import TypedDict
|
||||
from typing import TypedDict, Tuple
|
||||
|
||||
from fastapi.security import OAuth2PasswordBearer
|
||||
|
||||
from jose import jwt, ExpiredSignatureError
|
||||
from jose import jwt, ExpiredSignatureError, JWTError
|
||||
|
||||
# openssl rand -hex 32
|
||||
SECRET_KEY = '1c3c03b79d084f0c7b41ba11d1d9a4979f72d9fc6eaaaa0a855065e8a5be0468'
|
||||
|
@ -17,27 +17,34 @@ class SigninClaim(TypedDict):
|
|||
iss: str
|
||||
iat: float
|
||||
exp: float
|
||||
phone_mac: str
|
||||
device_id: str
|
||||
|
||||
|
||||
def create_signin_token(id: str, phone_mac: str) -> str:
|
||||
def create_signin_token(id: str, device_id: str) -> str:
|
||||
claim: SigninClaim = {
|
||||
'sub': id,
|
||||
'iss': 'together',
|
||||
'iat': datetime.now().timestamp(),
|
||||
'exp': (datetime.now() + timedelta(days=23)).timestamp(),
|
||||
'phone_mac': phone_mac
|
||||
'device_id': device_id,
|
||||
}
|
||||
return jwt.encode(claim, SECRET_KEY, algorithm=ALGORITHM)
|
||||
|
||||
|
||||
def verify_signin_token(token):
|
||||
def verify_signin_token(token) -> Tuple[str | None, str]:
|
||||
try:
|
||||
claim: SigninClaim = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
|
||||
if claim['exp'] - datetime.now().timestamp() <= 10*24*60*60:
|
||||
_prolong_token(token)
|
||||
new_token = _prolong_token(token)
|
||||
return new_token, claim['sub']
|
||||
else:
|
||||
return None, claim['sub']
|
||||
except ExpiredSignatureError:
|
||||
pass
|
||||
print(f'{token} expire ========================')
|
||||
raise ExpiredSignatureError
|
||||
except JWTError:
|
||||
print(f'This token {token} is not sign by me ==========================')
|
||||
raise JWTError
|
||||
|
||||
|
||||
def _prolong_token(claim: SigninClaim) -> str:
|
||||
|
|
Loading…
Reference in New Issue