mirror of
https://github.com/FutureOfMedTech-FITM-hack/backend.git
synced 2024-11-21 22:16:33 +03:00
updated user registration, user info
This commit is contained in:
parent
8ac1c37e5d
commit
5961d7dbe0
|
@ -9,14 +9,14 @@ from . import schemas, services
|
|||
from .schemas import User
|
||||
|
||||
|
||||
async def get_user(session: AsyncSession, username: str) -> User | None:
|
||||
r = await session.execute(select(UserScheme).where(UserScheme.username == username))
|
||||
async def get_user_by_email(session: AsyncSession, email: str) -> User | None:
|
||||
r = await session.execute(select(UserScheme).where(UserScheme.email == email))
|
||||
user = r.scalars().first()
|
||||
return user
|
||||
|
||||
|
||||
async def get_user_by_email(session: AsyncSession, email: str) -> User | None:
|
||||
r = await session.execute(select(UserScheme).where(UserScheme.email == email))
|
||||
async def get_user(session: AsyncSession, pk: int) -> User | None:
|
||||
r = await session.execute(select(UserScheme).where(UserScheme.id == pk))
|
||||
user = r.scalars().first()
|
||||
return user
|
||||
|
||||
|
@ -37,17 +37,15 @@ async def get_users(
|
|||
|
||||
|
||||
async def create_user(session: AsyncSession, user: schemas.UserCreate) -> UserScheme:
|
||||
if await get_user(session, user.username):
|
||||
raise HTTPException(status_code=400, detail="Username already taken")
|
||||
|
||||
if await get_user_by_email(session, user.email):
|
||||
raise HTTPException(status_code=400, detail="Email already taken")
|
||||
raise HTTPException(status_code=422, detail="Email already taken")
|
||||
|
||||
hashed_password = services.get_password_hash(user.password)
|
||||
db_user = UserScheme(
|
||||
email=user.email,
|
||||
username=user.username,
|
||||
fullname=user.fullname,
|
||||
gender=user.gender,
|
||||
born=user.born.date(),
|
||||
hashed_password=hashed_password,
|
||||
disabled=False,
|
||||
)
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
from datetime import datetime
|
||||
|
||||
from pydantic import BaseModel, EmailStr
|
||||
|
||||
|
||||
|
@ -7,11 +9,11 @@ class Token(BaseModel):
|
|||
|
||||
|
||||
class TokenData(BaseModel):
|
||||
username: str
|
||||
email: EmailStr
|
||||
|
||||
|
||||
class UserBase(BaseModel):
|
||||
username: str
|
||||
email: EmailStr
|
||||
|
||||
|
||||
class UserLogin(UserBase):
|
||||
|
@ -20,13 +22,13 @@ class UserLogin(UserBase):
|
|||
|
||||
class UserCreate(UserBase):
|
||||
password: str
|
||||
email: EmailStr
|
||||
fullname: str
|
||||
gender: str
|
||||
born: datetime
|
||||
|
||||
|
||||
class UserPublicInfo(UserBase):
|
||||
id: int
|
||||
email: EmailStr
|
||||
fullname: str | None
|
||||
disabled: bool
|
||||
|
||||
|
@ -36,8 +38,7 @@ class UserPublicInfo(UserBase):
|
|||
|
||||
class User(UserBase):
|
||||
id: int
|
||||
email: EmailStr
|
||||
fullname: str | None
|
||||
fullname: str
|
||||
hashed_password: str
|
||||
disabled: bool
|
||||
is_manager: bool
|
||||
|
|
|
@ -32,8 +32,8 @@ def get_password_hash(password: str) -> str:
|
|||
return pwd_context.hash(password)
|
||||
|
||||
|
||||
async def get_user(session: AsyncSession, username: str) -> User:
|
||||
db_user = await crud.get_user(session, username=username)
|
||||
async def get_user(session: AsyncSession, email: str) -> User:
|
||||
db_user = await crud.get_user_by_email(session, email=email)
|
||||
if db_user is None:
|
||||
raise HTTPException(status_code=404, detail="User not found")
|
||||
return db_user
|
||||
|
@ -78,13 +78,13 @@ async def get_current_user(
|
|||
)
|
||||
try:
|
||||
payload = jwt.decode(token, SECRET_KEY, algorithms=[JWT_ALGORITHM])
|
||||
username: str = payload.get("sub")
|
||||
if username is None:
|
||||
email: str = payload.get("sub")
|
||||
if email is None:
|
||||
raise credentials_exception
|
||||
token_data = TokenData(username=username)
|
||||
token_data = TokenData(email=email)
|
||||
except JWTError:
|
||||
raise credentials_exception
|
||||
user = await get_user(session, token_data.username)
|
||||
user = await get_user(session, token_data.email)
|
||||
if user is None:
|
||||
raise credentials_exception
|
||||
return user
|
||||
|
@ -96,3 +96,16 @@ async def get_current_active_user(
|
|||
if current_user.disabled:
|
||||
raise HTTPException(status_code=400, detail="Inactive user")
|
||||
return current_user
|
||||
|
||||
|
||||
async def get_current_active_manager(
|
||||
current_user: User = Depends(get_current_user),
|
||||
) -> User:
|
||||
if current_user.disabled:
|
||||
raise HTTPException(status_code=400, detail="Inactive user")
|
||||
if not current_user.is_manager:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="You are not allowed to access this info",
|
||||
)
|
||||
return current_user
|
||||
|
|
|
@ -23,7 +23,7 @@ async def login_for_access_token(
|
|||
data: UserLogin,
|
||||
session: AsyncSession = Depends(get_db_session),
|
||||
) -> Dict[str, str]:
|
||||
user = await authenticate_user(session, data.username, data.password)
|
||||
user = await authenticate_user(session, data.email, data.password)
|
||||
if not user:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
|
@ -32,7 +32,7 @@ async def login_for_access_token(
|
|||
)
|
||||
access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
|
||||
access_token = create_access_token(
|
||||
data={"sub": user.username},
|
||||
data={"sub": user.email},
|
||||
expires_delta=access_token_expires,
|
||||
)
|
||||
return {"access_token": access_token, "token_type": "bearer"}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
from datetime import date
|
||||
|
||||
from pydantic import EmailStr
|
||||
from sqlalchemy import Boolean, Column, Integer, String
|
||||
from sqlalchemy import Boolean, Column, Date, Integer, String
|
||||
|
||||
from med_backend.db.base import Base
|
||||
|
||||
|
@ -10,12 +12,11 @@ class UserScheme(Base):
|
|||
__tablename__ = "users"
|
||||
|
||||
id: int = Column(Integer, primary_key=True, index=True)
|
||||
username: str = Column(String, unique=True, index=True, nullable=False)
|
||||
email: EmailStr = Column(String, unique=True, index=True, nullable=False)
|
||||
fullname: str = Column(String, default="")
|
||||
hashed_password: str = Column(String)
|
||||
gender: str = Column(String, default="Не выбран")
|
||||
age: int = Column(Integer, default=0)
|
||||
born: date = Column(Date, nullable=False)
|
||||
latest_form_result: str = Column(String, default="ok")
|
||||
|
||||
is_manager: bool = Column(Boolean, default=False)
|
||||
|
|
|
@ -1,12 +1,34 @@
|
|||
from pydantic import EmailStr
|
||||
from datetime import date, datetime
|
||||
|
||||
from med_backend.auth.schemas import UserBase
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from pydantic import BaseModel, EmailStr, root_validator
|
||||
|
||||
|
||||
class ExtendedUser(UserBase):
|
||||
class ExtendedUser(BaseModel):
|
||||
id: int
|
||||
fullname: str
|
||||
age: int
|
||||
gender: str
|
||||
born: date
|
||||
|
||||
@root_validator(pre=False)
|
||||
def _set_fields(cls, values):
|
||||
"""This is a validator that sets the field values based on the
|
||||
the user's account type.
|
||||
|
||||
Args:
|
||||
values (dict): Stores the attributes of the User object.
|
||||
|
||||
Returns:
|
||||
dict: The attributes of the user object with the user's fields.
|
||||
"""
|
||||
values["key"] = values["id"]
|
||||
values["fio"] = values["fullname"]
|
||||
values["age"] = relativedelta(datetime.now(), values["born"]).years
|
||||
|
||||
values.pop("id")
|
||||
values.pop("fullname")
|
||||
values.pop("born")
|
||||
return values
|
||||
|
||||
|
||||
class ListUser(ExtendedUser):
|
||||
|
@ -17,7 +39,6 @@ class ListUser(ExtendedUser):
|
|||
|
||||
|
||||
class FullUser(ListUser):
|
||||
gender: str
|
||||
email: EmailStr
|
||||
|
||||
class Config:
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from starlette import status
|
||||
|
||||
from med_backend.auth.crud import get_users
|
||||
from med_backend.auth import crud
|
||||
from med_backend.auth.schemas import User
|
||||
from med_backend.auth.services import get_current_active_user
|
||||
from med_backend.auth.services import get_current_active_manager
|
||||
from med_backend.db.dependencies import get_db_session
|
||||
from med_backend.users.schemas import ListUser
|
||||
from med_backend.users.schemas import FullUser, ListUser
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
@ -15,13 +14,20 @@ router = APIRouter()
|
|||
async def get_all_users(
|
||||
skip: int = 0,
|
||||
limit: int = 100,
|
||||
current_user: User = Depends(get_current_active_user),
|
||||
current_user: User = Depends(get_current_active_manager),
|
||||
session: AsyncSession = Depends(get_db_session),
|
||||
):
|
||||
if not current_user.is_manager:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="You are not allowed to access this info",
|
||||
)
|
||||
users = await get_users(session, skip, limit)
|
||||
users = await crud.get_users(session, skip, limit)
|
||||
return users
|
||||
|
||||
|
||||
@router.get("/{key}", response_model=FullUser)
|
||||
async def get_user(
|
||||
key: int,
|
||||
current_user: User = Depends(get_current_active_manager),
|
||||
session: AsyncSession = Depends(get_db_session),
|
||||
):
|
||||
user = await crud.get_user(session, key)
|
||||
if not user:
|
||||
raise HTTPException(status_code=404, detail="User not found")
|
||||
return user
|
||||
|
|
17
poetry.lock
generated
17
poetry.lock
generated
|
@ -983,6 +983,17 @@ python-versions = "*"
|
|||
[package.dependencies]
|
||||
pytest = ">=2.6.0"
|
||||
|
||||
[[package]]
|
||||
name = "python-dateutil"
|
||||
version = "2.8.2"
|
||||
description = "Extensions to the standard Python datetime module"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
|
||||
|
||||
[package.dependencies]
|
||||
six = ">=1.5"
|
||||
|
||||
[[package]]
|
||||
name = "python-decouple"
|
||||
version = "3.6"
|
||||
|
@ -1399,7 +1410,7 @@ tokenize-rt = ">=2.1"
|
|||
[metadata]
|
||||
lock-version = "1.1"
|
||||
python-versions = "^3.9"
|
||||
content-hash = "ead3885108db4ad12e4fadd52509671806884feda6607c3364807ebb210f69a2"
|
||||
content-hash = "322a94830a4e40dca70295059b87f26843820996227f5294bb417b00ff86a0f2"
|
||||
|
||||
[metadata.files]
|
||||
anyio = [
|
||||
|
@ -2201,6 +2212,10 @@ pytest-cov = [
|
|||
pytest-env = [
|
||||
{file = "pytest-env-0.6.2.tar.gz", hash = "sha256:7e94956aef7f2764f3c147d216ce066bf6c42948bb9e293169b1b1c880a580c2"},
|
||||
]
|
||||
python-dateutil = [
|
||||
{file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"},
|
||||
{file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"},
|
||||
]
|
||||
python-decouple = [
|
||||
{file = "python-decouple-3.6.tar.gz", hash = "sha256:2838cdf77a5cf127d7e8b339ce14c25bceb3af3e674e039d4901ba16359968c7"},
|
||||
{file = "python_decouple-3.6-py3-none-any.whl", hash = "sha256:6cf502dc963a5c642ea5ead069847df3d916a6420cad5599185de6bab11d8c2e"},
|
||||
|
|
|
@ -26,6 +26,7 @@ python-decouple = "^3.6"
|
|||
python-jose = {extras = ["cryptography"], version = "^3.3.0"}
|
||||
passlib = {extras = ["bcrypt"], version = "^1.7.4"}
|
||||
python-multipart = "^0.0.5"
|
||||
python-dateutil = "^2.8.2"
|
||||
|
||||
[tool.poetry.dev-dependencies]
|
||||
pytest = "^7.1.3"
|
||||
|
|
Loading…
Reference in New Issue
Block a user