Merge pull request 'feature/permissions' (#7) from feature/permissions into dev
Reviewed-on: #7
This commit was merged in pull request #7.
This commit is contained in:
+6
-11
@@ -1,13 +1,13 @@
|
|||||||
from logging.config import fileConfig
|
from logging.config import fileConfig
|
||||||
|
|
||||||
|
from alembic import context
|
||||||
|
from sqlalchemy import create_engine, pool
|
||||||
|
|
||||||
from src.models.database_models import Model
|
from src.models.database_models import Model
|
||||||
from src.models.database_models.model import engine
|
from src.models.database_models.model import engine
|
||||||
|
|
||||||
from sqlalchemy import engine_from_config
|
sync_url = engine.url.render_as_string(hide_password=False).replace("+aiosqlite", "")
|
||||||
from sqlalchemy import pool
|
sync_engine = create_engine(sync_url, poolclass=pool.NullPool)
|
||||||
|
|
||||||
from alembic import context
|
|
||||||
|
|
||||||
# this is the Alembic Config object, which provides
|
# this is the Alembic Config object, which provides
|
||||||
# access to the values within the .ini file in use.
|
# access to the values within the .ini file in use.
|
||||||
@@ -23,7 +23,7 @@ if config.config_file_name is not None:
|
|||||||
# from myapp import mymodel
|
# from myapp import mymodel
|
||||||
# target_metadata = mymodel.Base.metadata
|
# target_metadata = mymodel.Base.metadata
|
||||||
target_metadata = Model.metadata
|
target_metadata = Model.metadata
|
||||||
config.set_main_option("sqlalchemy.url", engine.url.render_as_string(hide_password=False))
|
config.set_main_option("sqlalchemy.url", sync_url)
|
||||||
|
|
||||||
# other values from the config, defined by the needs of env.py,
|
# other values from the config, defined by the needs of env.py,
|
||||||
# can be acquired:
|
# can be acquired:
|
||||||
@@ -62,13 +62,8 @@ def run_migrations_online() -> None:
|
|||||||
and associate a connection with the context.
|
and associate a connection with the context.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
connectable = engine_from_config(
|
|
||||||
config.get_section(config.config_ini_section, {}),
|
|
||||||
prefix="sqlalchemy.",
|
|
||||||
poolclass=pool.NullPool,
|
|
||||||
)
|
|
||||||
|
|
||||||
with connectable.connect() as connection:
|
with sync_engine.connect() as connection:
|
||||||
context.configure(
|
context.configure(
|
||||||
connection=connection, target_metadata=target_metadata, render_as_batch=True
|
connection=connection, target_metadata=target_metadata, render_as_batch=True
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
"""empty message
|
||||||
|
|
||||||
|
Revision ID: ebe80cd28822
|
||||||
|
Revises: 74814eb1b7f8
|
||||||
|
Create Date: 2026-08-21 13:52:49.788041
|
||||||
|
|
||||||
|
"""
|
||||||
|
from typing import Sequence, Union
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision: str = 'ebe80cd28822'
|
||||||
|
down_revision: Union[str, Sequence[str], None] = '74814eb1b7f8'
|
||||||
|
branch_labels: Union[str, Sequence[str], None] = None
|
||||||
|
depends_on: Union[str, Sequence[str], None] = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade() -> None:
|
||||||
|
"""Upgrade schema."""
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
with op.batch_alter_table('user_direct_permissions', schema=None) as batch_op:
|
||||||
|
batch_op.drop_constraint(batch_op.f('fk_user_direct_permissions_user_id_users'), type_='foreignkey')
|
||||||
|
batch_op.create_foreign_key(batch_op.f('fk_user_direct_permissions_user_id_users'), 'users', ['user_id'], ['id'], ondelete='CASCADE')
|
||||||
|
|
||||||
|
with op.batch_alter_table('user_group', schema=None) as batch_op:
|
||||||
|
batch_op.drop_constraint(batch_op.f('fk_user_group_user_id_users'), type_='foreignkey')
|
||||||
|
batch_op.create_foreign_key(batch_op.f('fk_user_group_user_id_users'), 'users', ['user_id'], ['id'], ondelete='CASCADE')
|
||||||
|
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade() -> None:
|
||||||
|
"""Downgrade schema."""
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
with op.batch_alter_table('user_group', schema=None) as batch_op:
|
||||||
|
batch_op.drop_constraint(batch_op.f('fk_user_group_user_id_users'), type_='foreignkey')
|
||||||
|
batch_op.create_foreign_key(batch_op.f('fk_user_group_user_id_users'), 'users', ['user_id'], ['id'])
|
||||||
|
|
||||||
|
with op.batch_alter_table('user_direct_permissions', schema=None) as batch_op:
|
||||||
|
batch_op.drop_constraint(batch_op.f('fk_user_direct_permissions_user_id_users'), type_='foreignkey')
|
||||||
|
batch_op.create_foreign_key(batch_op.f('fk_user_direct_permissions_user_id_users'), 'users', ['user_id'], ['id'])
|
||||||
|
|
||||||
|
# ### end Alembic commands ###
|
||||||
@@ -75,14 +75,14 @@ class Permissions(Model):
|
|||||||
user_group_of_permissions=Table(
|
user_group_of_permissions=Table(
|
||||||
"user_group",
|
"user_group",
|
||||||
Model.metadata,
|
Model.metadata,
|
||||||
Column("user_id", ForeignKey("users.id"), primary_key=True),
|
Column("user_id", ForeignKey("users.id", ondelete="CASCADE"), primary_key=True),
|
||||||
Column("permission_group_id", ForeignKey("groups_of_permissions.id"), primary_key=True)
|
Column("permission_group_id", ForeignKey("groups_of_permissions.id"), primary_key=True)
|
||||||
)
|
)
|
||||||
|
|
||||||
user_permission=Table(
|
user_permission=Table(
|
||||||
"user_direct_permissions",
|
"user_direct_permissions",
|
||||||
Model.metadata,
|
Model.metadata,
|
||||||
Column("user_id",ForeignKey("users.id"), primary_key=True),
|
Column("user_id",ForeignKey("users.id", ondelete="CASCADE"), primary_key=True),
|
||||||
Column("permission_id", ForeignKey("permissions.id"), primary_key=True)
|
Column("permission_id", ForeignKey("permissions.id"), primary_key=True)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ class PermissionsGroupsOut(Base):
|
|||||||
|
|
||||||
id:Annotated[int, Field(..., description="id of the permission group")]
|
id:Annotated[int, Field(..., description="id of the permission group")]
|
||||||
group:Annotated[str, Field(..., max_length=255, description="group name for the permissions")]
|
group:Annotated[str, Field(..., max_length=255, description="group name for the permissions")]
|
||||||
|
permissions: Annotated[list[PermissionsOut], Field(..., description="permissions granted by this group")]
|
||||||
|
|
||||||
class UserCreate(Base):
|
class UserCreate(Base):
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ class CurrentUserService:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
async def get_current_user(self, token:str)->UserOut:
|
async def get_current_user(self, token:str, *permissions: str)->UserOut:
|
||||||
|
|
||||||
payload= await self.jwt_service.jwt_decode(token)
|
payload= await self.jwt_service.jwt_decode(token)
|
||||||
sub=payload.get("sub")
|
sub=payload.get("sub")
|
||||||
@@ -69,6 +69,12 @@ class CurrentUserService:
|
|||||||
if user.status is False:
|
if user.status is False:
|
||||||
raise self.error.credentials_error(detail="This user is deactivated")
|
raise self.error.credentials_error(detail="This user is deactivated")
|
||||||
|
|
||||||
|
effective = {p.permission for p in user.direct_permissions} | {p.permission for group in user.group for p in group.permissions}
|
||||||
|
missing = set(permissions) - effective
|
||||||
|
|
||||||
|
if missing:
|
||||||
|
raise self.error.forbidden_error(detail=f"Missing: {missing}")
|
||||||
|
|
||||||
return UserOut.model_validate(user)
|
return UserOut.model_validate(user)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,16 @@ from src.service.auth.auth import CurrentUserService, auth_service
|
|||||||
router=APIRouter(prefix="/protected")
|
router=APIRouter(prefix="/protected")
|
||||||
oauth2_schema=OAuth2PasswordBearer(tokenUrl="/protected/token", refreshUrl="/protected/refresh")
|
oauth2_schema=OAuth2PasswordBearer(tokenUrl="/protected/token", refreshUrl="/protected/refresh")
|
||||||
|
|
||||||
|
|
||||||
|
def require_permissions(*permissions: str): #permissions check dependency
|
||||||
|
async def checker(
|
||||||
|
token: str = Depends(oauth2_schema),
|
||||||
|
auth: CurrentUserService = Depends(auth_service), #noqa: B008
|
||||||
|
) -> UserOut:
|
||||||
|
return UserOut.model_validate(await auth.get_current_user(token, *permissions))
|
||||||
|
return checker
|
||||||
|
|
||||||
|
|
||||||
@router.post("/token")
|
@router.post("/token")
|
||||||
async def get_access_token(request: Request,response:Response,auth:CurrentUserService=Depends(auth_service), form_data:OAuth2PasswordRequestForm=Depends())->dict: # noqa: B008
|
async def get_access_token(request: Request,response:Response,auth:CurrentUserService=Depends(auth_service), form_data:OAuth2PasswordRequestForm=Depends())->dict: # noqa: B008
|
||||||
|
|
||||||
@@ -40,16 +50,11 @@ async def get_refresh_token(request:Request,response:Response, refresh_token: st
|
|||||||
|
|
||||||
return {"access_token":access_token, "token_type": "bearer"}
|
return {"access_token":access_token, "token_type": "bearer"}
|
||||||
|
|
||||||
|
|
||||||
async def get_current_user(token:str = Depends(oauth2_schema), auth:CurrentUserService=Depends(auth_service)) -> UserOut: # noqa: B008
|
|
||||||
return UserOut.model_validate(await auth.get_current_user(token))
|
|
||||||
|
|
||||||
|
|
||||||
@router.get("/logout")
|
@router.get("/logout")
|
||||||
async def logout(response:Response,refresh_token: str = Cookie(),auth:CurrentUserService=Depends(auth_service),current_user:UserOut=Depends(get_current_user))->bool: # noqa: B008
|
async def logout(response:Response,refresh_token: str = Cookie(),auth:CurrentUserService=Depends(auth_service),current_user:UserOut=Depends(require_permissions()))->bool: # noqa: B008
|
||||||
response.delete_cookie("refresh_token")
|
response.delete_cookie("refresh_token")
|
||||||
return await auth.logout(refresh_token)
|
return await auth.logout(refresh_token)
|
||||||
|
|
||||||
@router.get("")
|
@router.get("")
|
||||||
async def protected(current_user:UserOut=Depends(get_current_user))->dict: # noqa: B008
|
async def protected(current_user:UserOut=Depends(require_permissions()))->dict: # noqa: B008
|
||||||
return {"protected router": "Hello, this is a protected router"}
|
return {"protected router": "Hello, this is a protected router"}
|
||||||
|
|||||||
@@ -2,27 +2,27 @@ from fastapi import APIRouter, Depends
|
|||||||
|
|
||||||
from src.models.pydantic_models.model import UserCreate, UserOut, UserUpdate
|
from src.models.pydantic_models.model import UserCreate, UserOut, UserUpdate
|
||||||
from src.service.users_crud.users_crud import CrudService, crud_service
|
from src.service.users_crud.users_crud import CrudService, crud_service
|
||||||
from src.web.protected_routes.auth_routes import get_current_user
|
from src.web.protected_routes.auth_routes import require_permissions
|
||||||
|
|
||||||
router=APIRouter(prefix="/user")
|
router=APIRouter(prefix="/user")
|
||||||
|
|
||||||
@router.get("/get_by_email")
|
@router.get("/get_by_email")
|
||||||
async def get_current_user_by_email(email:str, crud:CrudService=Depends(crud_service), current_user=Depends(get_current_user))->UserOut: # noqa: B008
|
async def get_current_user_by_email(email:str, crud:CrudService=Depends(crud_service), current_user=Depends(require_permissions("admin")))->UserOut: # noqa: B008
|
||||||
return await crud.get_user_by_email(email)
|
return await crud.get_user_by_email(email)
|
||||||
|
|
||||||
@router.post("/create_user")
|
@router.post("/create_user")
|
||||||
async def create_user(data:UserCreate, crud:CrudService=Depends(crud_service), current_user=Depends(get_current_user))->UserOut: #noqa: B008
|
async def create_user(data:UserCreate, crud:CrudService=Depends(crud_service), current_user=Depends(require_permissions("admin")))->UserOut: #noqa: B008
|
||||||
return await crud.create_user(data)
|
return await crud.create_user(data)
|
||||||
|
|
||||||
@router.post("/delete_user_soft")
|
@router.post("/delete_user_soft")
|
||||||
async def delete_user_soft(email:str, crud:CrudService=Depends(crud_service), current_user=Depends(get_current_user))->bool: #noqa: B008
|
async def delete_user_soft(email:str, crud:CrudService=Depends(crud_service), current_user=Depends(require_permissions("admin")))->bool: #noqa: B008
|
||||||
return await crud.delete_user_soft(email)
|
return await crud.delete_user_soft(email)
|
||||||
|
|
||||||
@router.post("/delete_user_hard")
|
@router.post("/delete_user_hard")
|
||||||
async def delete_user_hard(email:str, crud:CrudService=Depends(crud_service), current_user=Depends(get_current_user))->bool: #noqa: B008
|
async def delete_user_hard(email:str, crud:CrudService=Depends(crud_service), current_user=Depends(require_permissions("admin")))->bool: #noqa: B008
|
||||||
return await crud.delete_user_hard(email, current_user)
|
return await crud.delete_user_hard(email, current_user)
|
||||||
|
|
||||||
@router.patch("/patch_user")
|
@router.patch("/patch_user")
|
||||||
async def patch_user(email:str, data:UserUpdate, crud:CrudService=Depends(crud_service), current_user=Depends(get_current_user))->UserOut: #noqa: B008
|
async def patch_user(email:str, data:UserUpdate, crud:CrudService=Depends(crud_service), current_user=Depends(require_permissions("admin")))->UserOut: #noqa: B008
|
||||||
return await crud.update_user(email, data)
|
return await crud.update_user(email, data)
|
||||||
|
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
import allure
|
||||||
|
import pytest
|
||||||
|
import requests_async
|
||||||
|
from httpx import HTTPStatusError
|
||||||
|
|
||||||
|
|
||||||
|
class TestAuth:
|
||||||
|
|
||||||
|
async def test_get_access_token_positive(self, target_url:str)->None:
|
||||||
|
|
||||||
|
with allure.step("get_access_token"), pytest.raises(HTTPStatusError) as exc_info:
|
||||||
|
|
||||||
|
response = await requests_async.post(f"{target_url}/protected/token")
|
||||||
|
response.raise_for_status()
|
||||||
|
assert exc_info.value.response.status_code != 403
|
||||||
|
assert exc_info.value.response.status_code != 401
|
||||||
|
|
||||||
|
async def test_get_refresh_token_positive(self, target_url:str)->None:
|
||||||
|
|
||||||
|
with allure.step("get_refresh_token"), pytest.raises(HTTPStatusError) as exc_info:
|
||||||
|
|
||||||
|
response = await requests_async.post(f"{target_url}/protected/refresh")
|
||||||
|
response.raise_for_status()
|
||||||
|
assert exc_info.value.response.status_code != 403
|
||||||
|
assert exc_info.value.response.status_code != 401
|
||||||
|
|
||||||
|
async def test_get_root_positive(self, target_url:str)->None:
|
||||||
|
|
||||||
|
with allure.step("get_root"), pytest.raises(HTTPStatusError) as exc_info:
|
||||||
|
|
||||||
|
response = await requests_async.get(f"{target_url}/protected")
|
||||||
|
response.raise_for_status()
|
||||||
|
assert exc_info.value.response.status_code != 403
|
||||||
|
assert exc_info.value.response.status_code == 401
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("test_user_fixture", [([], [])], indirect=True)
|
||||||
|
async def test_get_logout_positive(self,test_user_fixture, target_url:str)->None:
|
||||||
|
|
||||||
|
session=test_user_fixture[0]
|
||||||
|
with allure.step("get_root"), pytest.raises(HTTPStatusError) as exc_info:
|
||||||
|
|
||||||
|
response = await session.get(f"{target_url}/protected/logout")
|
||||||
|
response.raise_for_status()
|
||||||
|
assert exc_info.value.response.status_code != 403
|
||||||
|
assert exc_info.value.response.status_code != 401
|
||||||
|
|
||||||
@@ -241,7 +241,7 @@ class TestCrud:
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("test_user_fixture", [
|
@pytest.mark.parametrize("test_user_fixture", [
|
||||||
([], [])
|
(["admin"], ["admin_group"])
|
||||||
], indirect=True)
|
], indirect=True)
|
||||||
@pytest.mark.parametrize("user_record_to_update, expected_exception, expected_status",[
|
@pytest.mark.parametrize("user_record_to_update, expected_exception, expected_status",[
|
||||||
pytest.param({"plain_password": "Wrong_pass"},HTTPStatusError,422,id="Wrong_password"),
|
pytest.param({"plain_password": "Wrong_pass"},HTTPStatusError,422,id="Wrong_password"),
|
||||||
@@ -258,3 +258,126 @@ class TestCrud:
|
|||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
|
|
||||||
assert exc_info.value.response.status_code == expected_status
|
assert exc_info.value.response.status_code == expected_status
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("test_user_fixture", [(["admin"], ["admin_group"])], indirect=True)
|
||||||
|
async def test_get_user_by_email_permissions_positive(self,test_user_fixture, target_url:str)->None:
|
||||||
|
|
||||||
|
session=test_user_fixture[0]
|
||||||
|
|
||||||
|
with allure.step("Get user by email"), pytest.raises(HTTPStatusError) as exc_info:
|
||||||
|
response = await session.get(f"{target_url}/user/get_by_email")
|
||||||
|
response.raise_for_status()
|
||||||
|
|
||||||
|
assert exc_info.value.response.status_code != 403
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("test_user_fixture", [([], [])], indirect=True)
|
||||||
|
async def test_get_user_by_email_permissions_negative(self,test_user_fixture, target_url:str)->None:
|
||||||
|
|
||||||
|
session=test_user_fixture[0]
|
||||||
|
|
||||||
|
with allure.step("Get user by email"), pytest.raises(HTTPStatusError) as exc_info:
|
||||||
|
response = await session.get(f"{target_url}/user/get_by_email")
|
||||||
|
response.raise_for_status()
|
||||||
|
|
||||||
|
assert exc_info.value.response.status_code == 403
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("test_user_fixture", [(["admin"], ["admin_group"])], indirect=True)
|
||||||
|
async def test_create_user_permissions_positive(self,test_user_fixture, target_url:str)->None:
|
||||||
|
|
||||||
|
session=test_user_fixture[0]
|
||||||
|
|
||||||
|
with allure.step("Get user by email"), pytest.raises(HTTPStatusError) as exc_info:
|
||||||
|
response = await session.post(f"{target_url}/user/create_user")
|
||||||
|
response.raise_for_status()
|
||||||
|
|
||||||
|
assert exc_info.value.response.status_code != 403
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("test_user_fixture", [([], [])], indirect=True)
|
||||||
|
async def test_create_user_permissions_negative(self,test_user_fixture, target_url:str)->None:
|
||||||
|
|
||||||
|
session=test_user_fixture[0]
|
||||||
|
|
||||||
|
with allure.step("Get user by email"), pytest.raises(HTTPStatusError) as exc_info:
|
||||||
|
response = await session.post(f"{target_url}/user/create_user")
|
||||||
|
response.raise_for_status()
|
||||||
|
|
||||||
|
assert exc_info.value.response.status_code == 403
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("test_user_fixture", [(["admin"], ["admin_group"])], indirect=True)
|
||||||
|
async def test_patch_user_permissions_positive(self,test_user_fixture, target_url:str)->None:
|
||||||
|
|
||||||
|
session=test_user_fixture[0]
|
||||||
|
|
||||||
|
with allure.step("Get user by email"), pytest.raises(HTTPStatusError) as exc_info:
|
||||||
|
response = await session.patch(f"{target_url}/user/patch_user")
|
||||||
|
response.raise_for_status()
|
||||||
|
|
||||||
|
assert exc_info.value.response.status_code != 403
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("test_user_fixture", [([], [])], indirect=True)
|
||||||
|
async def test_patch_user_permissions_negative(self,test_user_fixture, target_url:str)->None:
|
||||||
|
|
||||||
|
session=test_user_fixture[0]
|
||||||
|
|
||||||
|
with allure.step("Get user by email"), pytest.raises(HTTPStatusError) as exc_info:
|
||||||
|
response = await session.patch(f"{target_url}/user/patch_user")
|
||||||
|
response.raise_for_status()
|
||||||
|
|
||||||
|
assert exc_info.value.response.status_code == 403
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("test_user_fixture", [(["admin"], ["admin_group"])], indirect=True)
|
||||||
|
async def test_delete_user_soft_permissions_positive(self,test_user_fixture, target_url:str)->None:
|
||||||
|
|
||||||
|
session=test_user_fixture[0]
|
||||||
|
|
||||||
|
with allure.step("Get user by email"), pytest.raises(HTTPStatusError) as exc_info:
|
||||||
|
response = await session.post(f"{target_url}/user/delete_user_soft")
|
||||||
|
response.raise_for_status()
|
||||||
|
|
||||||
|
assert exc_info.value.response.status_code != 403
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("test_user_fixture", [([], [])], indirect=True)
|
||||||
|
async def test_delete_user_soft_permissions_negative(self,test_user_fixture, target_url:str)->None:
|
||||||
|
|
||||||
|
session=test_user_fixture[0]
|
||||||
|
|
||||||
|
with allure.step("Get user by email"), pytest.raises(HTTPStatusError) as exc_info:
|
||||||
|
response = await session.post(f"{target_url}/user/delete_user_soft")
|
||||||
|
response.raise_for_status()
|
||||||
|
|
||||||
|
assert exc_info.value.response.status_code == 403
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("test_user_fixture", [(["admin"], ["admin_group"])], indirect=True)
|
||||||
|
async def test_delete_user_hard_permissions_positive(self,test_user_fixture, target_url:str)->None:
|
||||||
|
|
||||||
|
session=test_user_fixture[0]
|
||||||
|
|
||||||
|
with allure.step("Get user by email"), pytest.raises(HTTPStatusError) as exc_info:
|
||||||
|
response = await session.post(f"{target_url}/user/delete_user_hard")
|
||||||
|
response.raise_for_status()
|
||||||
|
|
||||||
|
assert exc_info.value.response.status_code != 403
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("test_user_fixture", [([], [])], indirect=True)
|
||||||
|
async def test_delete_user_hard_permissions_negative(self,test_user_fixture, target_url:str)->None:
|
||||||
|
|
||||||
|
session=test_user_fixture[0]
|
||||||
|
|
||||||
|
with allure.step("Get user by email"), pytest.raises(HTTPStatusError) as exc_info:
|
||||||
|
response = await session.post(f"{target_url}/user/delete_user_hard")
|
||||||
|
response.raise_for_status()
|
||||||
|
|
||||||
|
assert exc_info.value.response.status_code == 403
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@ class TestAuth:
|
|||||||
@pytest.mark.parametrize("user_data, uuid, expected_exception,expected_status",[
|
@pytest.mark.parametrize("user_data, uuid, expected_exception,expected_status",[
|
||||||
pytest.param(SimpleNamespace(first_name="test",last_name="test",middle_name="test",email="d@d.d",direct_permissions=[],group=[],status=False), uuid4(), HTTPException,401, id="false_status"),
|
pytest.param(SimpleNamespace(first_name="test",last_name="test",middle_name="test",email="d@d.d",direct_permissions=[],group=[],status=False), uuid4(), HTTPException,401, id="false_status"),
|
||||||
pytest.param(SimpleNamespace(first_name="test",last_name="test",middle_name="test",email="d@d.d",direct_permissions=[],group=[],status=True),1234, HTTPException,401, id="wrong_id"),
|
pytest.param(SimpleNamespace(first_name="test",last_name="test",middle_name="test",email="d@d.d",direct_permissions=[],group=[],status=True),1234, HTTPException,401, id="wrong_id"),
|
||||||
pytest.param(SimpleNamespace(status=True),uuid4(), ValidationError,None,id="empty_model_data")
|
pytest.param(SimpleNamespace(status=True,direct_permissions=[],group=[]),uuid4(), ValidationError,None,id="empty_model_data")
|
||||||
])
|
])
|
||||||
async def test_get_current_user_negative(self,current_user_service:CurrentUserService, jwt_service:JwtService, monkeypatch, user_data:SimpleNamespace,expected_exception, expected_status:int, uuid)->None:
|
async def test_get_current_user_negative(self,current_user_service:CurrentUserService, jwt_service:JwtService, monkeypatch, user_data:SimpleNamespace,expected_exception, expected_status:int, uuid)->None:
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user