Skip to content

Commit

Permalink
доработал пользователей в соответствие с прототипом
Browse files Browse the repository at this point in the history
  • Loading branch information
Puzanovim committed May 30, 2021
1 parent 3585892 commit 65c1cc2
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 20 deletions.
20 changes: 19 additions & 1 deletion src/errors.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,24 @@
class Errors:
NO_VACANCIES_UNDER_LICENCES = "NO_VACANCIES_UNDER_LICENCES"
CLIENT_HAS_NOT_FREE_VACANCIES = "CLIENT_HAS_NOT_FREE_VACANCIES"
USER_NOT_FOUND = "USER_NOT_FOUND"
IMPOSSIBLE_DELETE_OWNER = "IMPOSSIBLE_DELETE_OWNER"
USER_CAN_NOT_CHANGE_STATUS = "USER_CAN_NOT_CHANGE_STATUS_ON_THE_NEXT"
APPEAL_IS_CLOSED = "APPEAL_IS_CLOSED"
COMPANY_IS_EXIST = "COMPANY_IS_EXIST"

USER_HAS_ANOTHER_LICENCE = "USER_HAS_ANOTHER_LICENCE"
LICENCE_IS_FULL = "LICENCE_IS_FULL"
CLIENT_HAS_THIS_LICENCE = "CLIENT_HAS_THIS_LICENCE"

MODULE_IS_EXIST = "MODULE_IS_EXIST"
SOFTWARE_IS_EXIST = "SOFTWARE_IS_EXIST"
LICENCE_IS_EXIST = "LICENCE_IS_EXIST"

MODULE_IS_NOT_EXIST = "MODULE_IS_NOT_EXIST"
SOFTWARE_IS_NOT_EXIST = "SOFTWARE_IS_NOT_EXIST"
LICENCE_IS_NOT_EXIST = "LICENCE_IS_NOT_EXIST"

MODULE_FOR_THIS_SOFTWARE_IS_EXIST = "MODULE_FOR_THIS_SOFTWARE_IS_EXIST"
MODULE_FOR_THIS_SOFTWARE_IS_NOT_EXIST = "MODULE_FOR_THIS_SOFTWARE_IS_NOT_EXIST"

CLIENT_NOT_FOUND = "CLIENT_NOT_FOUND"
70 changes: 61 additions & 9 deletions src/users/logic.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,17 @@
from fastapi_users.password import get_password_hash

from ..config import SECRET
from .schemas import User, UserCreate, UserUpdate, UserDB
from .schemas import User, UserCreate, UserUpdate, UserDB, DeveloperList, generate_pwd, EmployeeUpdate
from .models import user_db, UserTable, users
from src.db.db import database
from src.errors import Errors

from typing import Dict, Any
from typing import Dict, Any, List, Optional
from pydantic.types import UUID4
# from requests import Request

from pydantic import EmailStr
from ..desk.models import appeals
from ..reference_book.services import update_employee_licence
from ..service import send_mail

auth_backends = []

Expand Down Expand Up @@ -74,12 +76,21 @@ async def after_verification(user: UserDB, request: Request):
print(f"{user.id} is now verified.")


async def get_developers():
async def get_count_dev_appeals(developer_id: UUID4):
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)
result = await database.fetch_all(query=query)
if result:
return [dict(developer) for developer in result]
return []
developers = []
for developer in result:
developer = dict(developer)
count_appeals = await get_count_dev_appeals(developer["id"])
developers.append(DeveloperList(**dict({**developer, "count_appeals": count_appeals})))
return developers


async def get_or_404(id: UUID4) -> UserDB:
Expand All @@ -91,7 +102,21 @@ async def get_or_404(id: UUID4) -> UserDB:
return user


async def update_user(id: UUID4, update_dict: Dict[str, Any]):
async def get_user(id: UUID4) -> Optional[UserDB]:
user = await database.fetch_one(query=users.select().where(users.c.id == id))
return user


async def pre_update_user(id: UUID4, item: EmployeeUpdate) -> UserDB:
if item.licence_id:
licence = await update_employee_licence(id, item.licence_id)
update_employee = UserUpdate(**dict(item))
update_dict = update_employee.dict(exclude_unset=True)
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}
for field in update_dict:
Expand All @@ -110,3 +135,30 @@ async def delete_user(id: UUID4):
user = await get_or_404(id)
await user_db.delete(user)
return None


async def get_user_by_email(email: EmailStr) -> UserDB:
user = await database.fetch_one(query=users.select().where(users.c.email == email))
if user is None:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=Errors.USER_NOT_FOUND)
return user


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)


async def get_new_password(email: EmailStr) -> UserDB:
user = await get_user_by_email(email)
pwd = await generate_pwd()

message = f"Добрый день!\nВаш новый пароль: {pwd}\n" \
f"Если Вы не меняли пароль обратитесь к администратору или смените его самостоятельно"
await send_mail(user.email, "Вы зарегистрированы в системе", message)

return await change_pwd(user.id, pwd)
2 changes: 1 addition & 1 deletion src/users/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class UserTable(Base, SQLAlchemyBaseUserTable):
name = Column(String, nullable=False)
surname = Column(String, nullable=False)
patronymic = Column(String, nullable=True)
# avatar
avatar = Column(String, nullable=True)
is_owner = Column(Boolean, default=False, nullable=True)
client_id = Column(Integer, ForeignKey('client.id')) # TODO сделать проверку на существующего владельца клиента
date_reg = Column(DateTime(timezone=True), server_default=sql.func.now())
Expand Down
11 changes: 9 additions & 2 deletions src/users/routes.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
from fastapi import Depends, Response
from fastapi import APIRouter
from fastapi import APIRouter, status
from pydantic import EmailStr

from .schemas import UserDB
from ..config import SECRET

from src.users.logic import jwt_authentication, all_users, \
on_after_forgot_password, on_after_reset_password, after_verification, after_verification_request, any_user
on_after_forgot_password, on_after_reset_password, after_verification, after_verification_request, any_user, \
get_new_password

router = APIRouter()

Expand All @@ -22,6 +24,11 @@ async def me(
return user


@router.post("/forgot_password", response_model=UserDB, status_code=status.HTTP_201_CREATED)
async def forgot_password(email: EmailStr):
return get_new_password(email)


router.include_router(
all_users.get_auth_router(jwt_authentication),
prefix="/auth/jwt",
Expand Down
36 changes: 29 additions & 7 deletions src/users/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
import random

from fastapi_users import models
from pydantic import validator
from pydantic import validator, EmailStr
from typing import Optional

from src.reference_book.schemas import LicenceDB


def generate_pwd():
symbols_list = "+-/*!&$#?=@<>abcdefghijklnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
Expand All @@ -19,6 +21,7 @@ class User(models.BaseUser):
name: str
surname: str
patronymic: Optional[str]
avatar: Optional[str]
# is_owner: bool
# client_id: int
# date_block: Optional[datetime]
Expand All @@ -28,9 +31,10 @@ class UserCreate(models.BaseUserCreate):
name: str
surname: str
patronymic: Optional[str]
avatar: Optional[str]
password: str = generate_pwd()
is_owner: Optional[bool] = False
client_id: Optional[int]
client_id: Optional[int] = 0
date_reg: datetime = datetime.utcnow()
date_block: Optional[datetime]

Expand All @@ -42,19 +46,20 @@ def valid_password(cls, v: str):


class EmployeeCreate(UserCreate, models.BaseUserCreate):
# avatar
is_owner: bool = False
client_id: int
date_reg: datetime = datetime.utcnow()


class PreEmployeeCreate(EmployeeCreate, models.BaseUserCreate):
licence_id: int


class DeveloperCreate(UserCreate, models.BaseUserCreate):
# avatar
date_reg: datetime = datetime.utcnow()


class OwnerCreate(UserCreate, models.BaseUserCreate):
# avatar
is_owner: bool = True
client_id: int
date_reg: datetime = datetime.utcnow()
Expand All @@ -66,11 +71,28 @@ class UserUpdate(User, models.BaseUserUpdate):
is_owner: Optional[bool]
is_active: Optional[bool]
date_block: Optional[datetime]
email: Optional[EmailStr]


class UserDB(User, models.BaseUserDB):
is_active: bool = True
is_active: bool # TODO проверить зачем здесь был " = True"
is_owner: Optional[bool]
client_id: Optional[int]
date_reg: datetime = datetime.utcnow()
date_reg: datetime # TODO проверить можно ли убрать " = datetime.utcnow()"
date_block: Optional[datetime]


class Employee(UserDB):
licence: Optional[LicenceDB]


class EmployeeUpdate(UserUpdate):
licence_id: Optional[int]


class EmployeeList(Employee):
count_appeals: int


class DeveloperList(User):
count_appeals: int

0 comments on commit 65c1cc2

Please sign in to comment.