Изменил подтверждение почты
This commit is contained in:
parent
040f10a2ed
commit
6b3dad8566
5 changed files with 34 additions and 11 deletions
|
@ -8,7 +8,7 @@ from app.config import settings
|
||||||
def create_registration_confirmation_template(
|
def create_registration_confirmation_template(
|
||||||
username: str,
|
username: str,
|
||||||
email_to: EmailStr,
|
email_to: EmailStr,
|
||||||
confirmation_code: str,
|
confirmation_link: str,
|
||||||
):
|
):
|
||||||
email = EmailMessage()
|
email = EmailMessage()
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ def create_registration_confirmation_template(
|
||||||
email.set_content(
|
email.set_content(
|
||||||
f"""
|
f"""
|
||||||
<h1>{username}, лови аптечку</h1>
|
<h1>{username}, лови аптечку</h1>
|
||||||
<h2>{confirmation_code}</h2>
|
{confirmation_link}
|
||||||
""",
|
""",
|
||||||
subtype="html"
|
subtype="html"
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
|
import json
|
||||||
import smtplib
|
import smtplib
|
||||||
import random
|
import random
|
||||||
import string
|
import string
|
||||||
|
|
||||||
|
from cryptography.fernet import Fernet
|
||||||
from pydantic import EmailStr
|
from pydantic import EmailStr
|
||||||
|
|
||||||
|
|
||||||
|
@ -19,15 +21,25 @@ def generate_confirmation_code(length=6):
|
||||||
|
|
||||||
@celery.task
|
@celery.task
|
||||||
def send_registration_confirmation_email(
|
def send_registration_confirmation_email(
|
||||||
|
user_id: int,
|
||||||
username: str,
|
username: str,
|
||||||
email_to: EmailStr,
|
email_to: EmailStr,
|
||||||
MODE: str
|
MODE: str
|
||||||
):
|
):
|
||||||
confirmation_code = generate_confirmation_code()
|
confirmation_code = generate_confirmation_code()
|
||||||
|
|
||||||
if MODE == 'TEST':
|
if MODE == 'TEST':
|
||||||
return confirmation_code
|
return confirmation_code
|
||||||
|
|
||||||
|
load = {"user_id": user_id, "username": username, "email": email_to, "confirmation_code": confirmation_code}
|
||||||
|
str_load = json.dumps(load)
|
||||||
|
cipher_suite = Fernet(settings.INVITATION_LINK_TOKEN_KEY)
|
||||||
|
invitation_token = cipher_suite.encrypt(str_load.encode())
|
||||||
|
|
||||||
|
confirmation_link = settings.INVITATION_LINK_HOST + '/api/users/email_verification/' + invitation_token.decode()
|
||||||
|
|
||||||
msg_content = create_registration_confirmation_template(
|
msg_content = create_registration_confirmation_template(
|
||||||
username=username, email_to=email_to, confirmation_code=confirmation_code
|
username=username, email_to=email_to, confirmation_link=confirmation_link
|
||||||
)
|
)
|
||||||
|
|
||||||
with smtplib.SMTP_SSL(settings.SMTP_HOST, settings.SMTP_PORT) as server:
|
with smtplib.SMTP_SSL(settings.SMTP_HOST, settings.SMTP_PORT) as server:
|
||||||
|
|
|
@ -150,7 +150,7 @@ class UserCodesDAO(BaseDAO):
|
||||||
AND now() - usersverificationcodes.date_of_creation < INTERVAL '30 minutes'
|
AND now() - usersverificationcodes.date_of_creation < INTERVAL '30 minutes'
|
||||||
"""
|
"""
|
||||||
query = (select(UsersVerificationCodes.__table__.columns)
|
query = (select(UsersVerificationCodes.__table__.columns)
|
||||||
.where((func.now() - UsersVerificationCodes.date_of_creation) < text("INTERVAL '30 minutes'"))
|
.where((func.now() - UsersVerificationCodes.date_of_creation) < text("INTERVAL '10 minutes'"))
|
||||||
.filter_by(**filter_by))
|
.filter_by(**filter_by))
|
||||||
|
|
||||||
async with async_session_maker() as session:
|
async with async_session_maker() as session:
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
import json
|
||||||
|
|
||||||
|
from cryptography.fernet import Fernet
|
||||||
from fastapi import APIRouter, Response, Depends, status, Request
|
from fastapi import APIRouter, Response, Depends, status, Request
|
||||||
from fastapi.responses import RedirectResponse
|
from fastapi.responses import RedirectResponse
|
||||||
|
|
||||||
|
@ -50,7 +53,10 @@ async def check_existing_email(email: SEmail):
|
||||||
|
|
||||||
@router.post("/register", response_model=SUserToken, status_code=status.HTTP_201_CREATED)
|
@router.post("/register", response_model=SUserToken, status_code=status.HTTP_201_CREATED)
|
||||||
async def register_user(response: Response, user_data: SUserRegister):
|
async def register_user(response: Response, user_data: SUserRegister):
|
||||||
|
if user_data.password != user_data.password2:
|
||||||
|
raise PasswordsMismatchException
|
||||||
await check_existing_user(user_data)
|
await check_existing_user(user_data)
|
||||||
|
|
||||||
hashed_password = get_password_hash(user_data.password)
|
hashed_password = get_password_hash(user_data.password)
|
||||||
user_id = await UserDAO.add(
|
user_id = await UserDAO.add(
|
||||||
email=user_data.email,
|
email=user_data.email,
|
||||||
|
@ -60,7 +66,7 @@ async def register_user(response: Response, user_data: SUserRegister):
|
||||||
)
|
)
|
||||||
|
|
||||||
result = send_registration_confirmation_email.delay(
|
result = send_registration_confirmation_email.delay(
|
||||||
username=user_data.username, email_to=user_data.email, MODE=settings.MODE
|
user_id=user_id, username=user_data.username, email_to=user_data.email, MODE=settings.MODE
|
||||||
)
|
)
|
||||||
result = result.get()
|
result = result.get()
|
||||||
|
|
||||||
|
@ -73,12 +79,16 @@ async def register_user(response: Response, user_data: SUserRegister):
|
||||||
return {"access_token": access_token}
|
return {"access_token": access_token}
|
||||||
|
|
||||||
|
|
||||||
@router.post('/email_verification', status_code=status.HTTP_200_OK, response_model=SEmailVerification)
|
@router.get('/email_verification/{user_code}', status_code=status.HTTP_200_OK, response_model=SEmailVerification)
|
||||||
async def email_verification(user_code: SUserCode, user: Users = Depends(get_current_user)):
|
async def email_verification(user_code: str):
|
||||||
|
invitation_token = user_code.encode()
|
||||||
|
cipher_suite = Fernet(settings.INVITATION_LINK_TOKEN_KEY)
|
||||||
|
user_data = cipher_suite.decrypt(invitation_token).decode("utf-8")
|
||||||
|
user_data = json.loads(user_data)
|
||||||
user_codes = await UserCodesDAO.get_user_codes(
|
user_codes = await UserCodesDAO.get_user_codes(
|
||||||
user_id=user.id, description="Код подтверждения почты", code=user_code.user_code
|
user_id=user_data["user_id"], description="Код подтверждения почты", code=user_data["confirmation_code"]
|
||||||
)
|
)
|
||||||
if not user_codes or not await UserDAO.change_data(user_id=user.id, role=VERIFICATED_USER):
|
if not user_codes or not await UserDAO.change_data(user_id=user_data["user_id"], role=VERIFICATED_USER):
|
||||||
raise WrongCodeException
|
raise WrongCodeException
|
||||||
return {'email_verification': True}
|
return {'email_verification': True}
|
||||||
|
|
||||||
|
@ -127,12 +137,12 @@ async def change_avatar(user_data: SUserAvatar, current_user: Users = Depends(ge
|
||||||
|
|
||||||
@router.patch("/change_password", status_code=status.HTTP_200_OK)
|
@router.patch("/change_password", status_code=status.HTTP_200_OK)
|
||||||
async def change_password(new_password: SUserPassword, current_user: Users = Depends(get_current_user)):
|
async def change_password(new_password: SUserPassword, current_user: Users = Depends(get_current_user)):
|
||||||
|
if new_password.new_password != new_password.new_password2:
|
||||||
|
raise PasswordsMismatchException
|
||||||
await check_verificated_user_with_exc(user_id=current_user.id)
|
await check_verificated_user_with_exc(user_id=current_user.id)
|
||||||
existing_user = await UserDAO.find_one_or_none(id=current_user.id)
|
existing_user = await UserDAO.find_one_or_none(id=current_user.id)
|
||||||
if not verify_password(new_password.current_password, existing_user.hashed_password):
|
if not verify_password(new_password.current_password, existing_user.hashed_password):
|
||||||
raise IncorrectPasswordException
|
raise IncorrectPasswordException
|
||||||
if new_password.new_password != new_password.new_password2:
|
|
||||||
raise PasswordsMismatchException
|
|
||||||
hashed_password = get_password_hash(new_password.new_password)
|
hashed_password = get_password_hash(new_password.new_password)
|
||||||
await UserDAO.change_data(current_user.id, hashed_password=hashed_password)
|
await UserDAO.change_data(current_user.id, hashed_password=hashed_password)
|
||||||
send_password_change_email.delay(current_user.username, current_user.email, MODE=settings.MODE)
|
send_password_change_email.delay(current_user.username, current_user.email, MODE=settings.MODE)
|
||||||
|
|
|
@ -15,6 +15,7 @@ class SUserRegister(BaseModel):
|
||||||
email: EmailStr
|
email: EmailStr
|
||||||
username: str = Query(None, min_length=2, max_length=30)
|
username: str = Query(None, min_length=2, max_length=30)
|
||||||
password: str = Query(None, min_length=8)
|
password: str = Query(None, min_length=8)
|
||||||
|
password2: str = Query(None, min_length=8)
|
||||||
date_of_birth: date
|
date_of_birth: date
|
||||||
|
|
||||||
@field_validator("date_of_birth")
|
@field_validator("date_of_birth")
|
||||||
|
|
Loading…
Add table
Reference in a new issue