From bb944daba00baf0647c1e319eea41dd6cec7a8f3 Mon Sep 17 00:00:00 2001 From: Puzanovim Date: Mon, 31 May 2021 13:57:42 +0500 Subject: [PATCH] =?UTF-8?q?=D0=BD=D0=B0=D1=81=D1=82=D1=80=D0=BE=D0=B8?= =?UTF-8?q?=D0=BB=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=BE=D1=81=D0=BF=D0=BE?= =?UTF-8?q?=D1=81=D0=BE=D0=B1=D0=BD=D0=BE=D1=81=D1=82=D1=8C=20=D0=9B=D0=9A?= =?UTF-8?q?=20=D0=B7=D0=B0=D0=BA=D0=B0=D0=B7=D1=87=D0=B8=D0=BA=D0=B0=20?= =?UTF-8?q?=D0=B8=20=D1=80=D0=B0=D0=B7=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D1=87?= =?UTF-8?q?=D0=B8=D0=BA=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/accounts/client_account/models.py | 1 - src/accounts/client_account/routers.py | 3 +- src/accounts/client_account/schemas.py | 11 ++-- src/accounts/client_account/services.py | 73 ++++++++++------------ src/accounts/developer_account/routers.py | 17 ++--- src/accounts/developer_account/services.py | 13 ++-- src/errors.py | 1 + src/users/logic.py | 29 +++++++-- src/users/schemas.py | 1 + 9 files changed, 81 insertions(+), 68 deletions(-) diff --git a/src/accounts/client_account/models.py b/src/accounts/client_account/models.py index 2bd79da..71fde65 100644 --- a/src/accounts/client_account/models.py +++ b/src/accounts/client_account/models.py @@ -1,4 +1,3 @@ -from fastapi_users.db.sqlalchemy import GUID from sqlalchemy import Boolean, Column, DateTime, ForeignKey, Integer, String, sql from ...db.db import Base diff --git a/src/accounts/client_account/routers.py b/src/accounts/client_account/routers.py index 5fa8824..bd0ce0b 100644 --- a/src/accounts/client_account/routers.py +++ b/src/accounts/client_account/routers.py @@ -21,8 +21,7 @@ async def clients_list(user: UserTable = Depends(developer_user)): @client_router.post("/", response_model=ClientDB, status_code=status.HTTP_201_CREATED) async def create_client(item: ClientAndOwnerCreate, user: UserTable = Depends(developer_user)): - new_client = await add_client(item) - return new_client + return await add_client(item) @client_router.get("/{id}", response_model=Union[ClientPage, DevClientPage], status_code=status.HTTP_200_OK) diff --git a/src/accounts/client_account/schemas.py b/src/accounts/client_account/schemas.py index 74d91a2..fc81d70 100644 --- a/src/accounts/client_account/schemas.py +++ b/src/accounts/client_account/schemas.py @@ -9,13 +9,12 @@ class ClientBase(BaseModel): name: str - avatar: Optional[str] + avatar: str class ClientCreate(ClientBase): name: Optional[str] owner_id: Optional[str] - avatar: Optional[str] class ClientAndOwnerCreate(ClientCreate): @@ -42,11 +41,13 @@ def valid_password(cls, v: str): class ClientUpdate(ClientBase): # TODO доработать изменение заказчика name: Optional[str] owner_id: Optional[str] + avatar: Optional[str] class ClientDB(ClientBase): id: int is_active: bool + avatar: str date_create: datetime date_block: Optional[datetime] owner_id: str @@ -66,19 +67,19 @@ class Client(ClientBase): licences: List[Licence] -class ClientPage(ClientBase): +class ClientPage(BaseModel): client: Client employees_list: List[EmployeeList] licences_list: List[Licence] -class DevClientPage(ClientBase): +class DevClientPage(BaseModel): client: Client employees_list: List[Employee] = [] software_list: List[SoftwareDB] -class ClientsPage(ClientBase): +class ClientsPage(BaseModel): clients_list: List[ClientShort] licences_list: List[LicenceDB] diff --git a/src/accounts/client_account/services.py b/src/accounts/client_account/services.py index b57e885..75d6b98 100644 --- a/src/accounts/client_account/services.py +++ b/src/accounts/client_account/services.py @@ -12,15 +12,15 @@ from ...desk.models import appeals from ...errors import Errors from ...reference_book.schemas import LicenceDB -from ...reference_book.services import get_licences, add_client_licence, get_client_licences, get_software_db_list, \ - add_employee_licence, get_employee_licence +from ...reference_book.services import add_client_licence, get_client_licences, get_software_db_list, \ + add_employee_licence, get_employee_licence, get_licences_db from ...users.logic import all_users, get_or_404, pre_update_user from ...users.models import users -from ...users.schemas import UserCreate, OwnerCreate, UserUpdate, Employee, UserDB, EmployeeList +from ...users.schemas import UserCreate, OwnerCreate, Employee, UserDB, EmployeeList, EmployeeUpdate from ...service import send_mail -async def get_count_appeals(employee_id: UUID4) -> int: +async def get_count_appeals(employee_id: str) -> int: query = appeals.select().where(appeals.c.author_id == employee_id) result = await database.fetch_all(query=query) return len([dict(appeal) for appeal in result]) @@ -31,8 +31,8 @@ async def get_employees(client_id: int) -> List[EmployeeList]: employees_list = [] for employee in result: employee = dict(employee) - licence: LicenceDB = await get_employee_licence(UUID4(employee["id"])) - count_appeals: int = await get_count_appeals(UUID4(employee["id"])) + licence: LicenceDB = await get_employee_licence(str(employee["id"])) + count_appeals: int = await get_count_appeals(str(employee["id"])) employees_list.append(EmployeeList(**dict({**employee, "licence": licence, "count_appeals": count_appeals}))) return employees_list @@ -48,14 +48,15 @@ async def get_clients() -> List[ClientShort]: clients_list = [] for client in result: client = dict(client) + owner = await get_client_owner(client["id"]) count_employees = await get_count_employees(client["id"]) - clients_list.append(ClientShort(**dict({**client, "count_employees": count_employees}))) + clients_list.append(ClientShort(**dict({**client, "owner": owner, "count_employees": count_employees}))) return clients_list async def get_clients_page() -> ClientsPage: clients_list = await get_clients() - licences_list = await get_licences() + licences_list = await get_licences_db() return ClientsPage(**dict({"clients_list": clients_list, "licences_list": licences_list})) @@ -77,7 +78,7 @@ async def get_dev_client_page(client_id: int) -> DevClientPage: client = await get_client(client_id) employees_list = await get_employees(client_id) software_list = await get_software_db_list() - return DevClientPage(**dict({**client, + return DevClientPage(**dict({"client": client, "employees_list": employees_list, "software_list": software_list})) @@ -105,7 +106,7 @@ async def get_client_db(client_id: int) -> Optional[ClientDB]: async def add_client(data: ClientAndOwnerCreate) -> Optional[ClientDB]: - client = ClientCreate(**data.dict()) + client = ClientCreate(**dict(data)) query = clients.insert().values({**client.dict(), "is_active": False, "owner_id": "undefined"}) try: client_id = await database.execute(query) @@ -127,41 +128,31 @@ async def add_client(data: ClientAndOwnerCreate) -> Optional[ClientDB]: date_reg=datetime.utcnow(), ) owner = await add_owner(client_id, owner) - owner_licence = await add_employee_licence(owner.id, data.owner_licence) + owner_licence = await add_employee_licence(str(owner.id), data.owner_licence) new_client = await get_client_db(client_id) return new_client -async def update_client(id: int, client: ClientUpdate) -> Optional[ClientDB]: # TODO проверить работу обновления - client_dict = client.dict() - if "owner_id" in client_dict: - client_dict["owner_id"] = str(client_dict["owner_id"]) - query = clients.update().where(clients.c.id == id).values(**client_dict) - client_id = await database.execute(query) +async def update_client(client_id: int, client: ClientUpdate) -> Optional[ClientDB]: # TODO проверить работу обновления + new_client_dict = dict(client) + old_client_dict = dict(await get_client_db(client_id)) + for field in new_client_dict: + if new_client_dict[field]: + old_client_dict[field] = new_client_dict[field] + query = clients.update().where(clients.c.id == client_id).values(**old_client_dict) + updated_client = await database.execute(query) updated_client = await get_client_db(client_id) return updated_client -async def activate_client(id: int) -> Optional[ClientDB]: - current_client = await database.fetch_one(query=clients.select().where(clients.c.id == id)) - if current_client: - current_client = dict(current_client) - current_client["is_active"] = True - await database.execute(query=clients.update().where(clients.c.id == id).values(**current_client)) - return current_client - - -async def block_client(id: int) -> Optional[ClientDB]: - current_client = await database.fetch_one(query=clients.select().where(clients.c.id == id)) - if current_client: - current_client = dict(current_client) - current_client["is_active"] = False - await database.execute(query=clients.update().where(clients.c.id == id).values(**current_client)) - return current_client +async def block_client(client_id: int) -> Optional[ClientDB]: + new_client = ClientUpdate(is_activa=False) + updated_client = await update_client(client_id, new_client) + return updated_client async def get_client_owner(client_id: int) -> Employee: - query = users.select().where((users.c.client_id == client_id) & (users.c.is_owner is True)) + query = users.select().where((users.c.client_id == client_id) & (users.c.is_owner == 1)) owner = await database.fetch_one(query=query) if owner is None: raise HTTPException( @@ -169,21 +160,20 @@ async def get_client_owner(client_id: int) -> Employee: detail=Errors.USER_NOT_FOUND ) owner = dict(owner) - licence: LicenceDB = await get_employee_licence(UUID4(owner["id"])) + licence: LicenceDB = await get_employee_licence(str(owner["id"])) return Employee(**dict({**owner, "licence": licence})) async def update_client_owner(client_id: int, new_owner_id: UUID4) -> Optional[UserDB]: client = await get_client_db(client_id) if client: + new_client = ClientUpdate(owner_id=str(new_owner_id)) if client.owner_id == "undefined": - new_client = ClientUpdate(name=client.name, owner_id=str(new_owner_id)) - await update_client(client_id, new_client) + client = await update_client(client_id, new_client) new_owner = await get_or_404(new_owner_id) else: - update_old = UserUpdate(is_owner=False) - update_new = UserUpdate(is_owner=True) - new_client = ClientUpdate(**dict(client), owner_id=new_owner_id) + update_old = EmployeeUpdate(is_owner=False) + update_new = EmployeeUpdate(is_owner=True) old_owner = await pre_update_user(UUID4(client.owner_id), update_old) new_owner = await pre_update_user(new_owner_id, update_new) client = await update_client(client_id, new_client) @@ -201,7 +191,8 @@ async def add_owner(client_id: int, owner: OwnerCreate): detail=ErrorCode.REGISTER_USER_ALREADY_EXISTS, ) - message = f"Добро пожаловать в UDV Service Desk!\n\nВаш логин в системе: {owner.email}\nВаш пароль: {owner.password}" + message = f"Добро пожаловать в UDV Service Desk!\n\n" \ + f"Ваш логин в системе: {owner.email}\nВаш пароль: {owner.password}" await send_mail(owner.email, "Вы зарегистрированы в системе", message) updated_owner = await update_client_owner(client_id, created_owner.id) return updated_owner diff --git a/src/accounts/developer_account/routers.py b/src/accounts/developer_account/routers.py index 5090d13..3072cb9 100644 --- a/src/accounts/developer_account/routers.py +++ b/src/accounts/developer_account/routers.py @@ -1,12 +1,12 @@ from typing import List -from fastapi import APIRouter, Depends, status, Response +from fastapi import APIRouter, Depends, status, Response, HTTPException from pydantic.types import UUID4 from .services import get_developer, add_developer, delete_developer from src.users.models import UserTable -from src.users.logic import developer_user, get_developers, pre_update_user, change_pwd -from src.users.schemas import UserDB, UserCreate, UserUpdate, DeveloperList +from src.users.logic import developer_user, get_developers, change_pwd, pre_update_developer +from src.users.schemas import UserDB, UserUpdate, DeveloperList, DeveloperCreate developer_router = APIRouter() @@ -18,22 +18,25 @@ async def developers_list(user: UserTable = Depends(developer_user)): @developer_router.get("/{id:uuid}", response_model=UserDB, status_code=status.HTTP_200_OK) async def developer(id: UUID4, user: UserTable = Depends(developer_user)): - return await get_developer(id) + return await get_developer(str(id)) @developer_router.post("/") -async def create_developer(item: UserCreate, user: UserTable = Depends(developer_user)): +async def create_developer(item: DeveloperCreate, user: UserTable = Depends(developer_user)): return await add_developer(item) @developer_router.patch("/{id:uuid}", response_model=UserDB, status_code=status.HTTP_201_CREATED) async def update_developer_by_id(id: UUID4, item: UserUpdate, user: UserTable = Depends(developer_user)): - return await pre_update_user(id, item) + return await pre_update_developer(id, item) @developer_router.patch("/{id:uuid}/pwd", response_model=UserDB, status_code=status.HTTP_201_CREATED) async def change_dev_pwd(id: UUID4, new_pwd: str, user: UserTable = Depends(developer_user)): - return await change_pwd(id, new_pwd) + if user.id == id: + return await change_pwd(id, new_pwd) + else: + raise HTTPException(status_code=status.HTTP_403_FORBIDDEN) @developer_router.delete("/{id:uuid}", response_class=Response, status_code=status.HTTP_204_NO_CONTENT) diff --git a/src/accounts/developer_account/services.py b/src/accounts/developer_account/services.py index 70a8d18..20b5451 100644 --- a/src/accounts/developer_account/services.py +++ b/src/accounts/developer_account/services.py @@ -11,16 +11,16 @@ from src.users.schemas import UserCreate, DeveloperCreate, UserUpdate, UserDB -async def get_developer(id: UUID4) -> Optional[UserDB]: - query = users.select().where((users.c.is_superuser is True) & (users.c.id == id)) +async def get_developer(developer_id: str) -> Optional[UserDB]: + query = users.select().where((users.c.is_superuser == 1) & (users.c.id == developer_id)) developer = await database.fetch_one(query=query) if developer: return UserDB(**dict(developer)) return None -async def add_developer(user: UserCreate) -> UserDB: - developer = DeveloperCreate(**user.dict()) +async def add_developer(developer: DeveloperCreate) -> UserDB: + developer = DeveloperCreate(**dict({**dict(developer), "is_superuser": True})) try: created_developer = await all_users.create_user(developer, safe=False) except Exception: @@ -29,8 +29,9 @@ async def add_developer(user: UserCreate) -> UserDB: status_code=status.HTTP_400_BAD_REQUEST, detail=ErrorCode.REGISTER_USER_ALREADY_EXISTS, ) - message = f"Добро пожаловать в UDV Service Desk!\n\nВаш логин в системе: {user.email}\nВаш пароль: {user.password}" - await send_mail(user.email, "Вы зарегистрированы в системе", message) + message = f"Добро пожаловать в UDV Service Desk!\n\nВаш логин в системе: " \ + f"{developer.email}\nВаш пароль: {developer.password}" + await send_mail(developer.email, "Вы зарегистрированы в системе", message) return created_developer diff --git a/src/errors.py b/src/errors.py index ca24213..5511593 100644 --- a/src/errors.py +++ b/src/errors.py @@ -22,3 +22,4 @@ class Errors: MODULE_FOR_THIS_SOFTWARE_IS_NOT_EXIST = "MODULE_FOR_THIS_SOFTWARE_IS_NOT_EXIST" CLIENT_NOT_FOUND = "CLIENT_NOT_FOUND" + FORBIDDEN_CHANGE_EMAIL = "FORBIDDEN_CHANGE_EMAIL" diff --git a/src/users/logic.py b/src/users/logic.py index 40f664d..eabe166 100644 --- a/src/users/logic.py +++ b/src/users/logic.py @@ -79,19 +79,20 @@ async def after_verification(user: UserDB, request: Request): print(f"{user.id} is now verified.") -async def get_count_dev_appeals(developer_id: UUID4): +async def get_count_dev_appeals(developer_id: str) -> int: query = appeals.select().where(appeals.c.responsible_id == developer_id) result = await database.fetch_all(query=query) return len(result) # TODO проверить не будет ли ошибки на len(None) async def get_developers() -> List[DeveloperList]: - query = users.select().where(users.c.is_superuser is True) + query = users.select().where(users.c.is_superuser == 1) result = await database.fetch_all(query=query) developers = [] for developer in result: developer = dict(developer) - count_appeals = await get_count_dev_appeals(developer["id"]) + print(developer) + count_appeals = await get_count_dev_appeals(str(developer["id"])) developers.append(DeveloperList(**dict({**developer, "count_appeals": count_appeals}))) return developers @@ -115,18 +116,29 @@ async def pre_update_user(id: UUID4, item: EmployeeUpdate) -> UserDB: licence = await update_employee_licence(id, item.licence_id) update_employee = UserUpdate(**dict(item)) update_dict = update_employee.dict(exclude_unset=True) + updated_user = await update_user(id, update_dict) + return updated_user + + +async def pre_update_developer(id: UUID4, item: UserUpdate) -> UserDB: + update_dict = item.dict(exclude_unset=True) + if "email" in update_dict.keys(): + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail=Errors.FORBIDDEN_CHANGE_EMAIL + ) updated_developer = await update_user(id, update_dict) return updated_developer async def update_user(id: UUID4, update_dict: Dict[str, Any]) -> UserDB: user = await get_or_404(id) - user = {**user} + user = dict(user) for field in update_dict: if field == "password": hashed_password = get_password_hash(update_dict[field]) user["hashed_password"] = hashed_password - else: + elif update_dict[field]: user[field] = update_dict[field] updated_user = await user_db.update(UserDB(**user)) @@ -179,7 +191,12 @@ async def change_pwd(id: UUID4, pwd: str) -> UserDB: if len(pwd) < 6: raise ValueError('Password should be at least 6 characters') updated_user = EmployeeUpdate(**dict({"password": pwd})) - return await pre_update_user(id, updated_user) + updated_user = await pre_update_user(id, updated_user) + + message = f"Добрый день!\nВы изменили свой пароль на: {pwd}\n" \ + f"Если Вы не меняли пароль обратитесь к администратору или смените его самостоятельно" + await send_mail(updated_user.email, "Вы зарегистрированы в системе", message) + return updated_user async def get_new_password(email: EmailStr) -> UserDB: diff --git a/src/users/schemas.py b/src/users/schemas.py index fb79285..73e0678 100644 --- a/src/users/schemas.py +++ b/src/users/schemas.py @@ -56,6 +56,7 @@ class PreEmployeeCreate(EmployeeCreate, models.BaseUserCreate): class DeveloperCreate(UserCreate, models.BaseUserCreate): + is_superuser = True date_reg: datetime = datetime.utcnow()