начал писать регистрацию
This commit is contained in:
parent
c0f0293ce7
commit
3d26a7f212
14
API/app/application/profiles_repository.py
Normal file
14
API/app/application/profiles_repository.py
Normal file
@ -0,0 +1,14 @@
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.domain.models import Profile
|
||||
|
||||
|
||||
class ProfilesRepository:
|
||||
def __init__(self, db: AsyncSession):
|
||||
self.db = db
|
||||
|
||||
async def create(self, profile: Profile) -> Profile:
|
||||
self.db.add(profile)
|
||||
await self.db.commit()
|
||||
await self.db.refresh(profile)
|
||||
return profile
|
||||
16
API/app/application/roles_repository.py
Normal file
16
API/app/application/roles_repository.py
Normal file
@ -0,0 +1,16 @@
|
||||
from select import select
|
||||
from typing import Optional
|
||||
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.domain.models import Role
|
||||
|
||||
|
||||
class RolesRepository:
|
||||
def __init__(self, db: AsyncSession):
|
||||
self.db = db
|
||||
|
||||
async def get_by_id(self, role_id: int) -> Optional[Role]:
|
||||
stmt = select(Role).filter_by(id=role_id)
|
||||
result = await self.db.execute(stmt)
|
||||
return result.scalars().first()
|
||||
16
API/app/application/teams_repository.py
Normal file
16
API/app/application/teams_repository.py
Normal file
@ -0,0 +1,16 @@
|
||||
from select import select
|
||||
from typing import Optional
|
||||
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.domain.models import Team
|
||||
|
||||
|
||||
class TeamsRepository:
|
||||
def __init__(self, db: AsyncSession):
|
||||
self.db = db
|
||||
|
||||
async def get_by_id(self, team_id: int) -> Optional[Team]:
|
||||
stmt = select(Team).filter_by(id=team_id)
|
||||
result = await self.db.execute(stmt)
|
||||
return result.scalars().first()
|
||||
31
API/app/application/users_repository.py
Normal file
31
API/app/application/users_repository.py
Normal file
@ -0,0 +1,31 @@
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy.orm import joinedload
|
||||
from typing_extensions import Optional
|
||||
|
||||
from app.domain.models import User
|
||||
|
||||
|
||||
class UsersRepository:
|
||||
def __init__(self, db: AsyncSession):
|
||||
self.db = db
|
||||
|
||||
async def get_by_id(self, user_id: int) -> Optional[User]:
|
||||
stmt = select(User).filter_by(id=user_id)
|
||||
result = await self.db.execute(stmt)
|
||||
return result.scalars().first()
|
||||
|
||||
async def get_by_login(self, login: str) -> Optional[User]:
|
||||
stmt = (
|
||||
select(User)
|
||||
.filter_by(login=login)
|
||||
.options(joinedload(User.role))
|
||||
)
|
||||
result = await self.db.execute(stmt)
|
||||
return result.scalars().first()
|
||||
|
||||
async def create(self, user: User) -> User:
|
||||
self.db.add(user)
|
||||
await self.db.commit()
|
||||
await self.db.refresh(user)
|
||||
return user
|
||||
19
API/app/domain/entities/base_profile.py
Normal file
19
API/app/domain/entities/base_profile.py
Normal file
@ -0,0 +1,19 @@
|
||||
import datetime
|
||||
from typing import Optional
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class BaseProfileEntity(BaseModel):
|
||||
first_name: str
|
||||
last_name: str
|
||||
patronymic: Optional[str] = None
|
||||
birthday: datetime.date
|
||||
email: Optional[str] = None
|
||||
phone: Optional[str] = None
|
||||
|
||||
role_id: int
|
||||
team_id: int
|
||||
|
||||
class Config:
|
||||
abstract = True
|
||||
9
API/app/domain/entities/base_user.py
Normal file
9
API/app/domain/entities/base_user.py
Normal file
@ -0,0 +1,9 @@
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class BaseUserEntity(BaseModel):
|
||||
login: str
|
||||
password: str
|
||||
|
||||
class Config:
|
||||
abstract = True
|
||||
7
API/app/domain/entities/profile.py
Normal file
7
API/app/domain/entities/profile.py
Normal file
@ -0,0 +1,7 @@
|
||||
from typing import Optional
|
||||
|
||||
from app.domain.entities.base_profile import BaseProfileEntity
|
||||
|
||||
|
||||
class ProfileEntity(BaseProfileEntity):
|
||||
id: Optional[int] = None
|
||||
6
API/app/domain/entities/register.py
Normal file
6
API/app/domain/entities/register.py
Normal file
@ -0,0 +1,6 @@
|
||||
from app.domain.entities.base_profile import BaseProfileEntity
|
||||
from app.domain.entities.base_user import BaseUserEntity
|
||||
|
||||
|
||||
class RegisterEntity(BaseUserEntity, BaseProfileEntity):
|
||||
pass
|
||||
12
API/app/domain/entities/user.py
Normal file
12
API/app/domain/entities/user.py
Normal file
@ -0,0 +1,12 @@
|
||||
from typing import Optional
|
||||
|
||||
from app.domain.entities.base_user import BaseUserEntity
|
||||
from app.domain.entities.profile import ProfileEntity
|
||||
|
||||
|
||||
class UserEntity(BaseUserEntity):
|
||||
id: Optional[int] = None
|
||||
|
||||
profile_id: int
|
||||
|
||||
profile: Optional[ProfileEntity] = None
|
||||
@ -11,4 +11,4 @@ class ProfilePhoto(AdvancedBaseModel):
|
||||
|
||||
profile_id = Column(Integer, ForeignKey('profiles.id'), nullable=False)
|
||||
|
||||
profile = relationship('Profile', back_populates='photos')
|
||||
profile = relationship('Profile', back_populates='profile_photos')
|
||||
@ -21,5 +21,5 @@ class Profile(AdvancedBaseModel):
|
||||
team = relationship('Team', back_populates='profiles')
|
||||
|
||||
user = relationship('User', back_populates='profile')
|
||||
profile_photo = relationship('ProfilePhoto', back_populates='profile')
|
||||
profile_photos = relationship('ProfilePhoto', back_populates='profile')
|
||||
projects = relationship('ProjectMember', back_populates='profile')
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
from sqlalchemy import Column, VARCHAR, ForeignKey, Integer
|
||||
from sqlalchemy.orm import relationship
|
||||
from werkzeug.security import check_password_hash, generate_password_hash
|
||||
|
||||
from app.domain.models.base import AdvancedBaseModel
|
||||
|
||||
@ -13,3 +14,9 @@ class User(AdvancedBaseModel):
|
||||
profile_id = Column(Integer, ForeignKey('profiles.id'), nullable=False)
|
||||
|
||||
profile = relationship('Profile', back_populates='user')
|
||||
|
||||
def check_password(self, password):
|
||||
return check_password_hash(self.password, password)
|
||||
|
||||
def set_password(self, password):
|
||||
self.password = generate_password_hash(password)
|
||||
|
||||
93
API/app/infrastructure/users_service.py
Normal file
93
API/app/infrastructure/users_service.py
Normal file
@ -0,0 +1,93 @@
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import HTTPException, status
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.application.profiles_repository import ProfilesRepository
|
||||
from app.application.roles_repository import RolesRepository
|
||||
from app.application.teams_repository import TeamsRepository
|
||||
from app.application.users_repository import UsersRepository
|
||||
from app.domain.entities.register import RegisterEntity
|
||||
from app.domain.entities.user import UserEntity
|
||||
from app.domain.models import User, Profile
|
||||
|
||||
|
||||
class UsersService:
|
||||
def __init__(self, db: AsyncSession):
|
||||
self.users_repository = UsersRepository(db)
|
||||
self.teams_repository = TeamsRepository(db)
|
||||
self.roles_repository = RolesRepository(db)
|
||||
self.profiles_repository = ProfilesRepository(db)
|
||||
|
||||
async def register_user(self, register_entity: RegisterEntity) -> Optional[UserEntity]:
|
||||
team = await self.teams_repository.get_by_id(register_entity.team_id)
|
||||
if team is None:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="The team with this ID was not found",
|
||||
)
|
||||
|
||||
role = await self.roles_repository.get_by_id(register_entity.role_id)
|
||||
if role is None:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="The role with this ID was not found",
|
||||
)
|
||||
|
||||
user_model, profile_model = self.register_entity_to_models(register_entity)
|
||||
|
||||
profile_model = await self.profiles_repository.create(profile_model)
|
||||
user_model.profile_id = profile_model.id
|
||||
user_model = await self.users_repository.create(user_model)
|
||||
|
||||
return UserEntity
|
||||
|
||||
@staticmethod
|
||||
def is_strong_password(password):
|
||||
if len(password) < 8:
|
||||
return False
|
||||
|
||||
if not any(char.isupper() for char in password):
|
||||
return False
|
||||
|
||||
if not any(char.islower() for char in password):
|
||||
return False
|
||||
|
||||
if not any(char.isdigit() for char in password):
|
||||
return False
|
||||
|
||||
if not any(char in "!@#$%^&*()_+" for char in password):
|
||||
return False
|
||||
|
||||
if not any(char.isalpha() for char in password):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def register_entity_to_models(register_entity: RegisterEntity) -> tuple[User, Profile]:
|
||||
user = User(
|
||||
login=register_entity.login,
|
||||
)
|
||||
|
||||
user.set_password(register_entity.password)
|
||||
|
||||
pofile = Profile(
|
||||
first_name=register_entity.first_name,
|
||||
last_name=register_entity.last_name,
|
||||
patronymic=register_entity.patronymic,
|
||||
birthday=register_entity.birthday,
|
||||
email=register_entity.email,
|
||||
phone=register_entity.phone,
|
||||
role_id=register_entity.role_id,
|
||||
team_id=register_entity.team_id
|
||||
)
|
||||
|
||||
return user, pofile
|
||||
|
||||
@staticmethod
|
||||
def user_model_to_entity(user_model: User) -> UserEntity:
|
||||
return UserEntity(
|
||||
id=user_model.id,
|
||||
login=user_model.login,
|
||||
)
|
||||
@ -0,0 +1,21 @@
|
||||
from fastapi import FastAPI
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
|
||||
def start_app():
|
||||
api_app = FastAPI()
|
||||
|
||||
api_app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=["http//localhost:5173"],
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
return api_app
|
||||
|
||||
app = start_app()
|
||||
|
||||
@app.get("/")
|
||||
async def root():
|
||||
return {"message": "Hello API"}
|
||||
Loading…
x
Reference in New Issue
Block a user