From a45d9f0743356add41051396fb1a33f0a01ce50d Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Wed, 18 Oct 2023 22:56:27 +0200 Subject: [PATCH 01/21] response cookie --- app/routers/token.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/routers/token.py b/app/routers/token.py index 7ef5419..4c362fb 100644 --- a/app/routers/token.py +++ b/app/routers/token.py @@ -2,6 +2,7 @@ from datetime import datetime, timedelta from typing import Annotated from fastapi import Depends, FastAPI, HTTPException, status, APIRouter +from fastapi.responses import JSONResponse from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm from ..dependencies import users_token from ..models import token @@ -9,7 +10,7 @@ from ..models import token router = APIRouter() ACCESS_TOKEN_EXPIRE_MINUTES = 30 -@router.post("/token", response_model=token.Token, tags=["token"]) +@router.post("/token", tags=["token"]) async def login_for_access_token( form_data: Annotated[OAuth2PasswordRequestForm, Depends()] ): @@ -24,4 +25,7 @@ async def login_for_access_token( access_token = users_token.create_access_token( data={"sub": user.username}, expires_delta=access_token_expires ) - return {"access_token": access_token, "token_type": "bearer"} \ No newline at end of file + content = {"message": "Access token generated"} + response = JSONResponse(content=content) + response.set_cookie(key="jwt", value=access_token) + return response \ No newline at end of file From 878fbbf5df5b23101b992f99a034dea098085f76 Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Wed, 18 Oct 2023 23:59:18 +0200 Subject: [PATCH 02/21] cors added and jwt --- app/main.py | 14 ++++++++++++++ app/routers/token.py | 12 +++++++++--- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/app/main.py b/app/main.py index 55aaf51..8e8d558 100644 --- a/app/main.py +++ b/app/main.py @@ -1,4 +1,5 @@ from fastapi import FastAPI +from fastapi.middleware.cors import CORSMiddleware from .routers import users, token, mail from .dependencies import user_add @@ -7,6 +8,19 @@ import os app = FastAPI() +origins = [ + "http://localhost:8084", +] + +app.add_middleware( + CORSMiddleware, + allow_origins=origins, + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], +) + + app.include_router(users.router) app.include_router(token.router) app.include_router(mail.router) diff --git a/app/routers/token.py b/app/routers/token.py index 4c362fb..d8eae4c 100644 --- a/app/routers/token.py +++ b/app/routers/token.py @@ -4,8 +4,8 @@ from typing import Annotated from fastapi import Depends, FastAPI, HTTPException, status, APIRouter from fastapi.responses import JSONResponse from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm -from ..dependencies import users_token -from ..models import token +from ..dependencies import users_token, permissions_checker +from ..models import token, users router = APIRouter() ACCESS_TOKEN_EXPIRE_MINUTES = 30 @@ -28,4 +28,10 @@ async def login_for_access_token( content = {"message": "Access token generated"} response = JSONResponse(content=content) response.set_cookie(key="jwt", value=access_token) - return response \ No newline at end of file + return response + +@router.get("/token",tags=["token"]) +async def check_token(current_user: Annotated[users.User, Depends(users_token.get_current_active_user)], authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin", "User"]))]): + content = {"message": "Check token"} + response = JSONResponse(content=content) + return response \ No newline at end of file From 0d00df81944fb197ca027bf644f29ed0a26e9d96 Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Fri, 20 Oct 2023 22:26:48 +0200 Subject: [PATCH 03/21] auth with cookie --- app/dependencies/cookie.py | 38 +++++++++++++++++++++++++++++++++ app/dependencies/users_token.py | 4 ++-- app/routers/token.py | 2 +- 3 files changed, 41 insertions(+), 3 deletions(-) create mode 100644 app/dependencies/cookie.py diff --git a/app/dependencies/cookie.py b/app/dependencies/cookie.py new file mode 100644 index 0000000..ed78336 --- /dev/null +++ b/app/dependencies/cookie.py @@ -0,0 +1,38 @@ +from fastapi.security import OAuth2 +from fastapi.openapi.models import OAuthFlows as OAuthFlowsModel +from fastapi import Request +from fastapi.security.utils import get_authorization_scheme_param +from fastapi import HTTPException +from fastapi import status +from typing import Optional +from typing import Dict + + +class OAuth2PasswordBearerWithCookie(OAuth2): + def __init__( + self, + tokenUrl: str, + scheme_name: Optional[str] = None, + scopes: Optional[Dict[str, str]] = None, + auto_error: bool = True, + ): + if not scopes: + scopes = {} + flows = OAuthFlowsModel(password={"tokenUrl": tokenUrl, "scopes": scopes}) + super().__init__(flows=flows, scheme_name=scheme_name, auto_error=auto_error) + + async def __call__(self, request: Request) -> Optional[str]: + authorization: str = request.cookies.get("access_token") #changed to accept access token from httpOnly Cookie + print("access_token is",authorization) + + scheme, param = get_authorization_scheme_param(authorization) + if not authorization or scheme.lower() != "bearer": + if self.auto_error: + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail="Not authenticated", + headers={"WWW-Authenticate": "Bearer"}, + ) + else: + return None + return param \ No newline at end of file diff --git a/app/dependencies/users_token.py b/app/dependencies/users_token.py index 341075e..8ef3032 100644 --- a/app/dependencies/users_token.py +++ b/app/dependencies/users_token.py @@ -8,14 +8,14 @@ from jose import JWTError, jwt from passlib.context import CryptContext from ..models import users, token -from ..dependencies import database +from ..dependencies import database, cookie SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7" ALGORITHM = "HS256" pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") -oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") +oauth2_scheme = cookie.OAuth2PasswordBearerWithCookie(tokenUrl="token") def verify_password(plain_password, hashed_password): return pwd_context.verify(plain_password, hashed_password) diff --git a/app/routers/token.py b/app/routers/token.py index d8eae4c..02defe6 100644 --- a/app/routers/token.py +++ b/app/routers/token.py @@ -27,7 +27,7 @@ async def login_for_access_token( ) content = {"message": "Access token generated"} response = JSONResponse(content=content) - response.set_cookie(key="jwt", value=access_token) + response.set_cookie(key="access_token", value="Bearer {0}".format(access_token), httponly=True) return response @router.get("/token",tags=["token"]) From 6e7970d5e3a982bebfeb519008ea389203284adc Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Fri, 20 Oct 2023 22:43:59 +0200 Subject: [PATCH 04/21] add method delete --- app/routers/token.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/routers/token.py b/app/routers/token.py index 02defe6..8b13860 100644 --- a/app/routers/token.py +++ b/app/routers/token.py @@ -34,4 +34,11 @@ async def login_for_access_token( async def check_token(current_user: Annotated[users.User, Depends(users_token.get_current_active_user)], authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin", "User"]))]): content = {"message": "Check token"} response = JSONResponse(content=content) + return response + +@router.delete("/token",tags=["token"]) +async def check_token(current_user: Annotated[users.User, Depends(users_token.get_current_active_user)], authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin", "User"]))]): + content = {"message": "Token deleted"} + response = JSONResponse(content=content) + response.set_cookie(key="access_token", value="", httponly=True) return response \ No newline at end of file From 68c578c449c7aea601c410adb8e1b2aad82a4909 Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Fri, 20 Oct 2023 23:38:12 +0200 Subject: [PATCH 05/21] check roles user --- app/dependencies/cookie.py | 1 - app/routers/token.py | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/app/dependencies/cookie.py b/app/dependencies/cookie.py index ed78336..2078dac 100644 --- a/app/dependencies/cookie.py +++ b/app/dependencies/cookie.py @@ -23,7 +23,6 @@ class OAuth2PasswordBearerWithCookie(OAuth2): async def __call__(self, request: Request) -> Optional[str]: authorization: str = request.cookies.get("access_token") #changed to accept access token from httpOnly Cookie - print("access_token is",authorization) scheme, param = get_authorization_scheme_param(authorization) if not authorization or scheme.lower() != "bearer": diff --git a/app/routers/token.py b/app/routers/token.py index 8b13860..037f6e6 100644 --- a/app/routers/token.py +++ b/app/routers/token.py @@ -7,13 +7,13 @@ from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm from ..dependencies import users_token, permissions_checker from ..models import token, users + router = APIRouter() ACCESS_TOKEN_EXPIRE_MINUTES = 30 @router.post("/token", tags=["token"]) async def login_for_access_token( - form_data: Annotated[OAuth2PasswordRequestForm, Depends()] -): + form_data: Annotated[OAuth2PasswordRequestForm, Depends()]): user = users_token.authenticate_user(form_data.username, form_data.password) if not user: raise HTTPException( @@ -25,7 +25,7 @@ async def login_for_access_token( access_token = users_token.create_access_token( data={"sub": user.username}, expires_delta=access_token_expires ) - content = {"message": "Access token generated"} + content = {"roles":user.roles,"message": "Access token generated"} response = JSONResponse(content=content) response.set_cookie(key="access_token", value="Bearer {0}".format(access_token), httponly=True) return response From 76a46806221a9aa7f883813725636f9ee3da3fc8 Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Sat, 21 Oct 2023 10:10:02 +0200 Subject: [PATCH 06/21] add count get --- app/routers/users.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/app/routers/users.py b/app/routers/users.py index 6b79929..30f44be 100644 --- a/app/routers/users.py +++ b/app/routers/users.py @@ -1,4 +1,5 @@ from fastapi import APIRouter, Depends, HTTPException, status +from fastapi.responses import JSONResponse from ..dependencies import users_token, permissions_checker, database from ..models import users from typing import Annotated @@ -47,6 +48,14 @@ async def read_users_id(authorize: Annotated[bool, Depends(permissions_checker.P async def read_users_me(current_user: Annotated[users.User, Depends(users_token.get_current_active_user)], authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin", "User"]))]): return current_user +@router.get("/users/count", tags=["users"]) +async def read_users_count(authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin"]))]): + count = database.database.get_collection("users").estimated_document_count() + content = {"count":count} + response = JSONResponse(content=content) + return response + + @router.get("/users/{item_id}", tags=["users"], response_model=users.User) async def read_users_id(item_id : str, authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin"]))]): user_repository = users.UserRepository(database=database.database) @@ -54,7 +63,6 @@ async def read_users_id(item_id : str, authorize: Annotated[bool, Depends(permis return user - @router.delete("/users/me",tags=["users"], response_model=users.User, response_model_exclude=["id", "password", "roles", "disabled"]) async def read_users_me(current_user: Annotated[users.User, Depends(users_token.get_current_active_user)], authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin", "User"]))], remove: bool = False): user_repository = users.UserRepository(database=database.database) From e12c1c91b3f5411cb3d38f7b4aa835012e77fac4 Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Sun, 22 Oct 2023 18:58:35 +0200 Subject: [PATCH 07/21] change status --- app/dependencies/user_add.py | 7 +++---- app/dependencies/users_token.py | 2 +- app/models/users.py | 8 ++------ app/routers/users.py | 18 +++++++++--------- 4 files changed, 15 insertions(+), 20 deletions(-) diff --git a/app/dependencies/user_add.py b/app/dependencies/user_add.py index fae97c5..a9f5a70 100644 --- a/app/dependencies/user_add.py +++ b/app/dependencies/user_add.py @@ -4,18 +4,17 @@ from passlib.context import CryptContext from pydantic import EmailStr -def add(username="", password="", roles="User", disabled=False, confirmed=True, email="test@toto.com"): +def add(username="", password="", roles="User", status=1, email="test@toto.com"): user_repository = users.UserRepository(database=database.database) pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") result = user_repository.find_one_by({'username': username}) change = "added" - user = users.User(username=username, password=pwd_context.hash(password), roles=roles, disabled=disabled, confirmed=confirmed, email=email) + user = users.User(username=username, password=pwd_context.hash(password), status=status, email=email) if result is not None: result.password=pwd_context.hash(password) result.roles=roles - result.disabled=disabled - result.confirmed=confirmed + result.status=status result.email=email user = result change = "updated" diff --git a/app/dependencies/users_token.py b/app/dependencies/users_token.py index 8ef3032..b34ea00 100644 --- a/app/dependencies/users_token.py +++ b/app/dependencies/users_token.py @@ -70,6 +70,6 @@ async def get_current_user(token_str: Annotated[str, Depends(oauth2_scheme)]): async def get_current_active_user( current_user: Annotated[users.User, Depends(get_current_user)] ): - if current_user.disabled: + if current_user.status == 0: raise HTTPException(status_code=400, detail="Inactive user") return current_user \ No newline at end of file diff --git a/app/models/users.py b/app/models/users.py index 4912304..5e7f358 100644 --- a/app/models/users.py +++ b/app/models/users.py @@ -6,18 +6,14 @@ class User(BaseModel): username: str password: str roles: str = "User" - disabled: bool = False - removed: bool = False - confirmed: bool = False + status: int = 0 email: EmailStr class UserOut(BaseModel): id: ObjectIdField = None username: str roles: str - disabled: bool - removed: bool - confirmed: bool + status: int = 0 email: EmailStr diff --git a/app/routers/users.py b/app/routers/users.py index 30f44be..ae27d57 100644 --- a/app/routers/users.py +++ b/app/routers/users.py @@ -19,7 +19,7 @@ async def read_users(authorize: Annotated[bool, Depends(permissions_checker.Perm listUsers = [] user_repository = users.UserRepository(database=database.database) for user_index in user_repository.find_by({}, limit=limit, skip=skip): - user = users.UserOut(id=user_index.id, username=user_index.username, email=user_index.email, disabled=user_index.disabled, roles=user_index.roles, removed=user_index.removed, confirmed=user_index.confirmed) + user = users.UserOut(id=user_index.id, username=user_index.username, email=user_index.email, status=user_index.status, roles=user_index.roles) listUsers.append(user) return listUsers @@ -39,12 +39,12 @@ async def read_users_id(authorize: Annotated[bool, Depends(permissions_checker.P listUsers = [] user_repository = users.UserRepository(database=database.database) for user_index in user_repository.find_by({key: {'$regex': value}}, limit=limit, skip=skip): - user = users.UserOut(id=user_index.id, username=user_index.username, disabled=user_index.disabled, roles=user_index.roles, email=user_index.email, removed=user_index.removed, confirmed=user_index.confirmed) + user = users.UserOut(id=user_index.id, username=user_index.username, status=user_index.status, roles=user_index.roles, email=user_index.email) listUsers.append(user) return listUsers -@router.get("/users/me",tags=["users"], response_model=users.User, response_model_exclude=["id", "password", "roles", "disabled"]) +@router.get("/users/me",tags=["users"], response_model=users.User, response_model_exclude=["id", "password", "roles", "status"]) async def read_users_me(current_user: Annotated[users.User, Depends(users_token.get_current_active_user)], authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin", "User"]))]): return current_user @@ -63,12 +63,12 @@ async def read_users_id(item_id : str, authorize: Annotated[bool, Depends(permis return user -@router.delete("/users/me",tags=["users"], response_model=users.User, response_model_exclude=["id", "password", "roles", "disabled"]) +@router.delete("/users/me",tags=["users"], response_model=users.User, response_model_exclude=["id", "password", "roles", "status"]) async def read_users_me(current_user: Annotated[users.User, Depends(users_token.get_current_active_user)], authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin", "User"]))], remove: bool = False): user_repository = users.UserRepository(database=database.database) - current_user.disabled = True + current_user.status = 0 if remove is True: - current_user.removed = True + current_user.status = -1 user_repository.save(current_user) return current_user @@ -76,13 +76,13 @@ async def read_users_me(current_user: Annotated[users.User, Depends(users_token. async def read_users_id(item_id : str, authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin"]))], remove : bool = False): user_repository = users.UserRepository(database=database.database) user = user_repository.find_one_by_id(ObjectId(item_id)) - user.disabled = True + user.status = 0 if remove is True: - user.removed = True + user.status = -1 user_repository.save(user) return user -@router.put("/users/me",tags=["users"], response_model=users.User, response_model_exclude=["id", "password", "roles", "disabled"]) +@router.put("/users/me",tags=["users"], response_model=users.User, response_model_exclude=["id", "password", "roles", "status"]) async def read_users_me(current_user: Annotated[users.User, Depends(users_token.get_current_active_user)], authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin", "User"]))], userSingle: users.UserIn | None = None): user_repository = users.UserRepository(database=database.database) current_user.username = userSingle.username From c120e609115c0d18f5f59effc7be0382fe3a7496 Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Mon, 23 Oct 2023 23:45:13 +0200 Subject: [PATCH 08/21] add datetime --- app/models/users.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/models/users.py b/app/models/users.py index 5e7f358..225a0ed 100644 --- a/app/models/users.py +++ b/app/models/users.py @@ -1,5 +1,6 @@ from pydantic import BaseModel, EmailStr from pydantic_mongo import AbstractRepository, ObjectIdField +from datetime import datetime class User(BaseModel): id: ObjectIdField = None @@ -8,6 +9,11 @@ class User(BaseModel): roles: str = "User" status: int = 0 email: EmailStr + birth: datetime = None + created_at: datetime = datetime.today() + connected_at: datetime = None + updated_at: datetime = datetime.today() + deleted_at: datetime = None class UserOut(BaseModel): id: ObjectIdField = None From 94bdf0e27af63b1f03e535f171281144c6593d96 Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Wed, 25 Oct 2023 23:42:34 +0200 Subject: [PATCH 09/21] update user --- app/dependencies/user_add.py | 2 +- app/dependencies/users_token.py | 3 +++ app/models/users.py | 15 +++++++++++---- app/routers/users.py | 11 ++++++++--- 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/app/dependencies/user_add.py b/app/dependencies/user_add.py index a9f5a70..9c8e85d 100644 --- a/app/dependencies/user_add.py +++ b/app/dependencies/user_add.py @@ -10,7 +10,7 @@ def add(username="", password="", roles="User", status=1, email="test@toto.com") pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") result = user_repository.find_one_by({'username': username}) change = "added" - user = users.User(username=username, password=pwd_context.hash(password), status=status, email=email) + user = users.User(username=username, password=pwd_context.hash(password), roles=roles, status=status, email=email) if result is not None: result.password=pwd_context.hash(password) result.roles=roles diff --git a/app/dependencies/users_token.py b/app/dependencies/users_token.py index b34ea00..b494a37 100644 --- a/app/dependencies/users_token.py +++ b/app/dependencies/users_token.py @@ -35,6 +35,9 @@ def authenticate_user(username: str, password: str): return False if not verify_password(password, user.password): return False + user.connected_at = datetime.today() + user_repository = users.UserRepository(database=database.database) + user_repository.save(user) return user def create_access_token(data: dict, expires_delta: timedelta | None = None): diff --git a/app/models/users.py b/app/models/users.py index 225a0ed..bacfa46 100644 --- a/app/models/users.py +++ b/app/models/users.py @@ -1,32 +1,39 @@ from pydantic import BaseModel, EmailStr from pydantic_mongo import AbstractRepository, ObjectIdField -from datetime import datetime +from datetime import datetime, date class User(BaseModel): id: ObjectIdField = None username: str password: str + firstName: str = "" + name: str = "" roles: str = "User" status: int = 0 email: EmailStr - birth: datetime = None + birth: str | None = None created_at: datetime = datetime.today() - connected_at: datetime = None + connected_at: datetime | None = None updated_at: datetime = datetime.today() - deleted_at: datetime = None + deleted_at: datetime | None = None class UserOut(BaseModel): id: ObjectIdField = None username: str roles: str + firstName: str + name: str status: int = 0 email: EmailStr class UserIn(BaseModel): username: str + name: str + firstName: str roles: str password: str + birth: str email: EmailStr diff --git a/app/routers/users.py b/app/routers/users.py index ae27d57..fa431aa 100644 --- a/app/routers/users.py +++ b/app/routers/users.py @@ -1,5 +1,6 @@ from fastapi import APIRouter, Depends, HTTPException, status from fastapi.responses import JSONResponse +from datetime import datetime from ..dependencies import users_token, permissions_checker, database from ..models import users from typing import Annotated @@ -19,7 +20,7 @@ async def read_users(authorize: Annotated[bool, Depends(permissions_checker.Perm listUsers = [] user_repository = users.UserRepository(database=database.database) for user_index in user_repository.find_by({}, limit=limit, skip=skip): - user = users.UserOut(id=user_index.id, username=user_index.username, email=user_index.email, status=user_index.status, roles=user_index.roles) + user = users.UserOut(id=user_index.id, username=user_index.username, email=user_index.email, status=user_index.status, roles=user_index.roles, firstName=user_index.firstName, name=user_index.name) listUsers.append(user) return listUsers @@ -39,7 +40,7 @@ async def read_users_id(authorize: Annotated[bool, Depends(permissions_checker.P listUsers = [] user_repository = users.UserRepository(database=database.database) for user_index in user_repository.find_by({key: {'$regex': value}}, limit=limit, skip=skip): - user = users.UserOut(id=user_index.id, username=user_index.username, status=user_index.status, roles=user_index.roles, email=user_index.email) + user = users.UserOut(id=user_index.id, username=user_index.username, status=user_index.status, roles=user_index.roles, email=user_index.email, firstName=user_index.firstName, name=user_index.name) listUsers.append(user) return listUsers @@ -106,8 +107,12 @@ async def read_users_id(authorize: Annotated[bool, Depends(permissions_checker.P response.status_code = status.HTTP_201_CREATED user = users.User() user.username = userSingle.username - user.password = user_token.get_password_hash(userSingle.password) + user.password = users_token.get_password_hash(userSingle.password) user.roles = userSingle.roles user.email = userSingle.email + user.firstName = userSingle.firstName + user.name = userSingle.name + user.birth = userSingle.birth + user.updated_at = datetime.today() user_repository.save(user) return user \ No newline at end of file From 4e2cf12c3b4731ab1888c435b96d0d80db4fa72b Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Thu, 26 Oct 2023 00:08:14 +0200 Subject: [PATCH 10/21] add enable user --- app/routers/users.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/app/routers/users.py b/app/routers/users.py index fa431aa..efdb31e 100644 --- a/app/routers/users.py +++ b/app/routers/users.py @@ -25,7 +25,7 @@ async def read_users(authorize: Annotated[bool, Depends(permissions_checker.Perm return listUsers @router.get("/users/search", tags=["users"], response_model=list[users.UserOut]) -async def read_users_id(authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin", "User"]))], skip: int = 0, limit: int = 20, key: str | None = None, value: str | None= None): +async def read_users_search(authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin", "User"]))], skip: int = 0, limit: int = 20, key: str | None = None, value: str | None= None): if limit < 1 or skip < 0 or limit < skip: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, @@ -65,7 +65,7 @@ async def read_users_id(item_id : str, authorize: Annotated[bool, Depends(permis @router.delete("/users/me",tags=["users"], response_model=users.User, response_model_exclude=["id", "password", "roles", "status"]) -async def read_users_me(current_user: Annotated[users.User, Depends(users_token.get_current_active_user)], authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin", "User"]))], remove: bool = False): +async def delete_users_me(current_user: Annotated[users.User, Depends(users_token.get_current_active_user)], authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin", "User"]))], remove: bool = False): user_repository = users.UserRepository(database=database.database) current_user.status = 0 if remove is True: @@ -74,7 +74,7 @@ async def read_users_me(current_user: Annotated[users.User, Depends(users_token. return current_user @router.delete("/users/{item_id}", tags=["users"], response_model=users.User) -async def read_users_id(item_id : str, authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin"]))], remove : bool = False): +async def delete_users_id(item_id : str, authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin"]))], remove : bool = False): user_repository = users.UserRepository(database=database.database) user = user_repository.find_one_by_id(ObjectId(item_id)) user.status = 0 @@ -84,7 +84,7 @@ async def read_users_id(item_id : str, authorize: Annotated[bool, Depends(permis return user @router.put("/users/me",tags=["users"], response_model=users.User, response_model_exclude=["id", "password", "roles", "status"]) -async def read_users_me(current_user: Annotated[users.User, Depends(users_token.get_current_active_user)], authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin", "User"]))], userSingle: users.UserIn | None = None): +async def update_users_me(current_user: Annotated[users.User, Depends(users_token.get_current_active_user)], authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin", "User"]))], userSingle: users.UserIn | None = None): user_repository = users.UserRepository(database=database.database) current_user.username = userSingle.username current_user.password = user_token.get_password_hash(userSingle.password) @@ -94,7 +94,7 @@ async def read_users_me(current_user: Annotated[users.User, Depends(users_token. return current_user @router.put("/users", tags=["users"], response_model=users.User, status_code=status.HTTP_200_OK) -async def read_users_id(authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin"]))], userSingle: users.UserIn | None = None): +async def update_users_id(authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin"]))], userSingle: users.UserIn | None = None): if userSingle is None: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, @@ -115,4 +115,12 @@ async def read_users_id(authorize: Annotated[bool, Depends(permissions_checker.P user.birth = userSingle.birth user.updated_at = datetime.today() user_repository.save(user) + return user + +@router.patch("/users/enable/{item_id}", tags=["users"], response_model=users.User) +async def patch_users_id(item_id : str, authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin"]))]): + user_repository = users.UserRepository(database=database.database) + user = user_repository.find_one_by_id(ObjectId(item_id)) + user.status = 1 + user_repository.save(user) return user \ No newline at end of file From 4059411828ca0e82bb4a74d0180d40bdb6aac09d Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Fri, 27 Oct 2023 23:50:35 +0200 Subject: [PATCH 11/21] =?UTF-8?q?add=20routers=20users=C3=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/routers/users.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/routers/users.py b/app/routers/users.py index efdb31e..ef5850d 100644 --- a/app/routers/users.py +++ b/app/routers/users.py @@ -1,4 +1,4 @@ -from fastapi import APIRouter, Depends, HTTPException, status +from fastapi import APIRouter, Depends, HTTPException, status, Response from fastapi.responses import JSONResponse from datetime import datetime from ..dependencies import users_token, permissions_checker, database @@ -104,8 +104,8 @@ async def update_users_id(authorize: Annotated[bool, Depends(permissions_checker user = user_repository.find_one_by({"username": {'$eq': userSingle.username}}) if user is None: - response.status_code = status.HTTP_201_CREATED - user = users.User() + Response.status_code = status.HTTP_201_CREATED + user = users.User(username=userSingle.username, password=users_token.get_password_hash(userSingle.password), email=userSingle.email) user.username = userSingle.username user.password = users_token.get_password_hash(userSingle.password) user.roles = userSingle.roles From af4af31e26fe9df25eca484738cfea31a29ecc2d Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Mon, 30 Oct 2023 23:37:16 +0100 Subject: [PATCH 12/21] search user done --- app/routers/users.py | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/app/routers/users.py b/app/routers/users.py index ef5850d..496085a 100644 --- a/app/routers/users.py +++ b/app/routers/users.py @@ -3,6 +3,7 @@ from fastapi.responses import JSONResponse from datetime import datetime from ..dependencies import users_token, permissions_checker, database from ..models import users +from pydantic import EmailStr from typing import Annotated from bson import ObjectId router = APIRouter() @@ -10,7 +11,7 @@ router = APIRouter() @router.get("/users", tags=["users"], response_model=list[users.UserOut]) -async def read_users(authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin"]))], skip: int = 0, limit: int = 20): +async def read_users(authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin"]))], skip: int = 0, limit: int = 20, id_user: str | None = None, roles: str | None = None, status: int | None = None, email: EmailStr | None = None): if limit < 1 or skip < 0 or limit < skip: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, @@ -19,13 +20,42 @@ async def read_users(authorize: Annotated[bool, Depends(permissions_checker.Perm limit = limit + skip listUsers = [] user_repository = users.UserRepository(database=database.database) - for user_index in user_repository.find_by({}, limit=limit, skip=skip): + object_search = {} + if status is not None and roles is not None: + object_search = {"$and":[{"roles":{"$eq": roles}}, {"status":{"$eq":status}}]} + else: + if status is not None: + object_search = {"status":{"$eq": status}} + if roles is not None: + object_search = {"roles":{"$eq":roles}} + if id_user is not None: + userid = ObjectId(id_user) + object_search = {"id": {"$regex": userid}} + if status is not None and roles is not None: + object_search = {"$and":[{"id":{"$regex": userid}}, {"roles":{"$eq": roles}}, {"status":{"$eq":status}}]} + else: + if status is not None: + object_search = {"$and":[{"id":{"$regex": userid}}, {"status":{"$eq":status}}]} + if roles is not None: + object_search = {"$and":[{"id":{"$regex": userid}}, {"roles":{"$eq":roles}}]} + if email is not None: + object_search = {"email": {"$eq": email}} + if status is not None and roles is not None: + object_search = {"$and":[{"email":{"$eq": email}}, {"roles":{"$eq": roles}}, {"status":{"$eq":status}}]} + else: + if status is not None: + object_search = {"$and":[{"email":{"$eq": email}}, {"status":{"$eq":status}}]} + if roles is not None: + object_search = {"$and":[{"email":{"$eq": email}}, {"roles":{"$eq":roles}}]} + + + for user_index in user_repository.find_by(object_search, limit=limit, skip=skip): user = users.UserOut(id=user_index.id, username=user_index.username, email=user_index.email, status=user_index.status, roles=user_index.roles, firstName=user_index.firstName, name=user_index.name) listUsers.append(user) return listUsers @router.get("/users/search", tags=["users"], response_model=list[users.UserOut]) -async def read_users_search(authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin", "User"]))], skip: int = 0, limit: int = 20, key: str | None = None, value: str | None= None): +async def read_users_search(authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin", "User"]))], skip: int = 0, limit: int = 20): if limit < 1 or skip < 0 or limit < skip: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, From 6cc12e0535d8ab703ee852bc9ba931d233b2ae2d Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Tue, 31 Oct 2023 17:44:24 +0100 Subject: [PATCH 13/21] add method group method --- app/routers/users.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/app/routers/users.py b/app/routers/users.py index 496085a..edc8b08 100644 --- a/app/routers/users.py +++ b/app/routers/users.py @@ -103,6 +103,26 @@ async def delete_users_me(current_user: Annotated[users.User, Depends(users_toke user_repository.save(current_user) return current_user +@router.delete("/users/groups",tags=["users"]) +async def delete_users_groups(current_user: Annotated[users.User, Depends(users_token.get_current_active_user)], authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin", "User"]))], remove: bool = False, userids: list[str] = []): + if len(userids) == 0: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail="userids should be greater than 0" + ) + + user_repository = users.UserRepository(database=database.database) + for i in userids: + user = user_repository.find_one_by_id(ObjectId(i)) + user.status = 0 + if remove is True: + user.status = -1 + user_repository.save(current_user) + + content = {"roles":user.roles,"message": "Access token generated"} + response = JSONResponse(content=content) + return response + @router.delete("/users/{item_id}", tags=["users"], response_model=users.User) async def delete_users_id(item_id : str, authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin"]))], remove : bool = False): user_repository = users.UserRepository(database=database.database) From 475c8e0ffca0b0df0a4be0733bf7018d23279e87 Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Tue, 31 Oct 2023 17:47:44 +0100 Subject: [PATCH 14/21] disable message --- app/routers/users.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/routers/users.py b/app/routers/users.py index edc8b08..770f045 100644 --- a/app/routers/users.py +++ b/app/routers/users.py @@ -112,14 +112,16 @@ async def delete_users_groups(current_user: Annotated[users.User, Depends(users_ ) user_repository = users.UserRepository(database=database.database) + content = {"roles":user.roles,"message": "users are disabled"} for i in userids: user = user_repository.find_one_by_id(ObjectId(i)) user.status = 0 if remove is True: user.status = -1 + content = {"roles":user.roles,"message": "users are deleted "} user_repository.save(current_user) - content = {"roles":user.roles,"message": "Access token generated"} + response = JSONResponse(content=content) return response From 1286f0a3f2967c1b39bb2cd283b6ce33b5655706 Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Tue, 31 Oct 2023 17:49:57 +0100 Subject: [PATCH 15/21] remove current user for groups --- app/routers/users.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/routers/users.py b/app/routers/users.py index 770f045..325db86 100644 --- a/app/routers/users.py +++ b/app/routers/users.py @@ -104,7 +104,7 @@ async def delete_users_me(current_user: Annotated[users.User, Depends(users_toke return current_user @router.delete("/users/groups",tags=["users"]) -async def delete_users_groups(current_user: Annotated[users.User, Depends(users_token.get_current_active_user)], authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin", "User"]))], remove: bool = False, userids: list[str] = []): +async def delete_users_groups(authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin"]))], remove: bool = False, userids: list[str] = []): if len(userids) == 0: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, From 2546763b03aa68ce2e1dde0240cb3db88b08d64a Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Tue, 31 Oct 2023 18:02:24 +0100 Subject: [PATCH 16/21] add method patch enable --- app/routers/users.py | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/app/routers/users.py b/app/routers/users.py index 325db86..e6e0fab 100644 --- a/app/routers/users.py +++ b/app/routers/users.py @@ -175,4 +175,23 @@ async def patch_users_id(item_id : str, authorize: Annotated[bool, Depends(permi user = user_repository.find_one_by_id(ObjectId(item_id)) user.status = 1 user_repository.save(user) - return user \ No newline at end of file + return user + +@router.patch("/users/groups",tags=["users"]) +async def patch_users_groups(authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin"]))], userids: list[str] = []): + if len(userids) == 0: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail="userids should be greater than 0" + ) + + user_repository = users.UserRepository(database=database.database) + content = {"roles":user.roles,"message": "users are enabled"} + for i in userids: + user = user_repository.find_one_by_id(ObjectId(i)) + user.status = 1 + user_repository.save(current_user) + + + response = JSONResponse(content=content) + return response \ No newline at end of file From a279439e72a55c1bf514e11a5ddbd29ca3247213 Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Thu, 2 Nov 2023 17:30:15 +0100 Subject: [PATCH 17/21] move method --- app/routers/users.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/app/routers/users.py b/app/routers/users.py index e6e0fab..afd8d89 100644 --- a/app/routers/users.py +++ b/app/routers/users.py @@ -169,13 +169,7 @@ async def update_users_id(authorize: Annotated[bool, Depends(permissions_checker user_repository.save(user) return user -@router.patch("/users/enable/{item_id}", tags=["users"], response_model=users.User) -async def patch_users_id(item_id : str, authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin"]))]): - user_repository = users.UserRepository(database=database.database) - user = user_repository.find_one_by_id(ObjectId(item_id)) - user.status = 1 - user_repository.save(user) - return user + @router.patch("/users/groups",tags=["users"]) async def patch_users_groups(authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin"]))], userids: list[str] = []): @@ -194,4 +188,12 @@ async def patch_users_groups(authorize: Annotated[bool, Depends(permissions_chec response = JSONResponse(content=content) - return response \ No newline at end of file + return response + +@router.patch("/users/{item_id}", tags=["users"], response_model=users.User) +async def patch_users_id(item_id : str, authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin"]))]): + user_repository = users.UserRepository(database=database.database) + user = user_repository.find_one_by_id(ObjectId(item_id)) + user.status = 1 + user_repository.save(user) + return user \ No newline at end of file From 753f4ee0877d23d02fece75603421498dc6c5759 Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Thu, 2 Nov 2023 23:54:40 +0100 Subject: [PATCH 18/21] add enable and remove groups --- app/models/users.py | 3 +++ app/routers/users.py | 22 +++++++++++----------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/app/models/users.py b/app/models/users.py index bacfa46..9d71f9d 100644 --- a/app/models/users.py +++ b/app/models/users.py @@ -46,6 +46,9 @@ class UserCreate(BaseModel): class UserInDB(User): password: str +class UserIDS(BaseModel): + ids: list[str] + class UserRepository(AbstractRepository[User]): class Meta: collection_name = "users" \ No newline at end of file diff --git a/app/routers/users.py b/app/routers/users.py index afd8d89..515c710 100644 --- a/app/routers/users.py +++ b/app/routers/users.py @@ -104,22 +104,22 @@ async def delete_users_me(current_user: Annotated[users.User, Depends(users_toke return current_user @router.delete("/users/groups",tags=["users"]) -async def delete_users_groups(authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin"]))], remove: bool = False, userids: list[str] = []): - if len(userids) == 0: +async def delete_users_groups(authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin"]))], remove: bool = False, userids: users.UserIDS | None = None): + if len(userids.ids) == 0: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="userids should be greater than 0" ) user_repository = users.UserRepository(database=database.database) - content = {"roles":user.roles,"message": "users are disabled"} - for i in userids: + content = {"message": "users are disabled"} + for i in userids.ids: user = user_repository.find_one_by_id(ObjectId(i)) user.status = 0 if remove is True: user.status = -1 - content = {"roles":user.roles,"message": "users are deleted "} - user_repository.save(current_user) + content = {"message": "users are deleted "} + user_repository.save(user) response = JSONResponse(content=content) @@ -172,19 +172,19 @@ async def update_users_id(authorize: Annotated[bool, Depends(permissions_checker @router.patch("/users/groups",tags=["users"]) -async def patch_users_groups(authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin"]))], userids: list[str] = []): - if len(userids) == 0: +async def patch_users_groups(authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin"]))], userids: users.UserIDS | None = None): + if len(userids.ids) == 0: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="userids should be greater than 0" ) user_repository = users.UserRepository(database=database.database) - content = {"roles":user.roles,"message": "users are enabled"} - for i in userids: + content = {"message": "users are enabled"} + for i in userids.ids: user = user_repository.find_one_by_id(ObjectId(i)) user.status = 1 - user_repository.save(current_user) + user_repository.save(user) response = JSONResponse(content=content) From ce0ba3e55b9966df55c49ffa3696ff1e533c7262 Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Fri, 3 Nov 2023 15:22:59 +0100 Subject: [PATCH 19/21] status code --- app/routers/users.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/routers/users.py b/app/routers/users.py index 515c710..23f6ffb 100644 --- a/app/routers/users.py +++ b/app/routers/users.py @@ -146,7 +146,7 @@ async def update_users_me(current_user: Annotated[users.User, Depends(users_toke return current_user @router.put("/users", tags=["users"], response_model=users.User, status_code=status.HTTP_200_OK) -async def update_users_id(authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin"]))], userSingle: users.UserIn | None = None): +async def update_users_id(authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin"]))], userSingle: users.UserIn | None = None, response: Response = Response): if userSingle is None: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, @@ -156,7 +156,7 @@ async def update_users_id(authorize: Annotated[bool, Depends(permissions_checker user = user_repository.find_one_by({"username": {'$eq': userSingle.username}}) if user is None: - Response.status_code = status.HTTP_201_CREATED + response.status_code = status.HTTP_201_CREATED user = users.User(username=userSingle.username, password=users_token.get_password_hash(userSingle.password), email=userSingle.email) user.username = userSingle.username user.password = users_token.get_password_hash(userSingle.password) From 4f6a057ecae7cfd810636d3cee5e95791cc230ee Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Fri, 3 Nov 2023 21:00:47 +0100 Subject: [PATCH 20/21] add or --- app/routers/users.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/routers/users.py b/app/routers/users.py index 23f6ffb..1f33b0e 100644 --- a/app/routers/users.py +++ b/app/routers/users.py @@ -154,7 +154,7 @@ async def update_users_id(authorize: Annotated[bool, Depends(permissions_checker ) user_repository = users.UserRepository(database=database.database) - user = user_repository.find_one_by({"username": {'$eq': userSingle.username}}) + user = user_repository.find_one_by({"$or":[{"username": {'$eq': userSingle.username}}, {"email": {"$eq": userSingle.email}}]}) if user is None: response.status_code = status.HTTP_201_CREATED user = users.User(username=userSingle.username, password=users_token.get_password_hash(userSingle.password), email=userSingle.email) From 632f61a376c7dfecc2335ce4b656ca15b4d9f2a1 Mon Sep 17 00:00:00 2001 From: Valentin CZERYBA Date: Fri, 3 Nov 2023 21:36:08 +0100 Subject: [PATCH 21/21] add route users --- app/routers/users.py | 44 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/app/routers/users.py b/app/routers/users.py index 1f33b0e..309ce13 100644 --- a/app/routers/users.py +++ b/app/routers/users.py @@ -145,8 +145,8 @@ async def update_users_me(current_user: Annotated[users.User, Depends(users_toke user_repository.save(current_user) return current_user -@router.put("/users", tags=["users"], response_model=users.User, status_code=status.HTTP_200_OK) -async def update_users_id(authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin"]))], userSingle: users.UserIn | None = None, response: Response = Response): +@router.put("/users", tags=["users"], response_model=users.User, status_code=status.HTTP_201_CREATED) +async def update_users(authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin"]))], userSingle: users.UserIn | None = None, response: Response = Response): if userSingle is None: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, @@ -155,9 +155,18 @@ async def update_users_id(authorize: Annotated[bool, Depends(permissions_checker user_repository = users.UserRepository(database=database.database) user = user_repository.find_one_by({"$or":[{"username": {'$eq': userSingle.username}}, {"email": {"$eq": userSingle.email}}]}) - if user is None: + if user is not None: response.status_code = status.HTTP_201_CREATED - user = users.User(username=userSingle.username, password=users_token.get_password_hash(userSingle.password), email=userSingle.email) + if user.username == userSingle.username: + raise HTTPException( + status_code=status.HTTP_204_NO_CONTENT, + detail="username" + ) + if user.email == userSingle.email: + raise HTTPException( + status_code=status.HTTP_204_NO_CONTENT, + detail="email" + ) user.username = userSingle.username user.password = users_token.get_password_hash(userSingle.password) user.roles = userSingle.roles @@ -170,6 +179,33 @@ async def update_users_id(authorize: Annotated[bool, Depends(permissions_checker return user +@router.put("/users/{item_id}", tags=["users"], response_model=users.User, status_code=status.HTTP_200_OK) +async def update_users_id(item_id: str, authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin"]))], userSingle: users.UserIn | None = None, response: Response = Response): + if userSingle is None: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail="Body request is empty" + ) + user_repository = users.UserRepository(database=database.database) + + user = user_repository.find_one_by({"id": {'$eq': ObjectId(item_id)}}) + if user is None: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail="User not found" + ) + + user.username = userSingle.username + user.password = users_token.get_password_hash(userSingle.password) + user.roles = userSingle.roles + user.email = userSingle.email + user.firstName = userSingle.firstName + user.name = userSingle.name + user.birth = userSingle.birth + user.updated_at = datetime.today() + user_repository.save(user) + return user + @router.patch("/users/groups",tags=["users"]) async def patch_users_groups(authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin"]))], userids: users.UserIDS | None = None):