diff --git a/achievement_api/base.py b/achievement_api/base.py new file mode 100644 index 0000000..fdb58a7 --- /dev/null +++ b/achievement_api/base.py @@ -0,0 +1,17 @@ +from pydantic import BaseModel, ConfigDict + + +class Base(BaseModel): + def __repr__(self) -> str: + attrs = [] + for k, v in self.__class__.model_json_schema().items(): + attrs.append(f"{k}={v}") + return "{}({})".format(self.__class__.__name__, ', '.join(attrs)) + + model_config = ConfigDict(from_attributes=True) + + +class StatusResponseModel(Base): + status: str + message: str + ru: str diff --git a/achievement_api/routes/achievement.py b/achievement_api/routes/achievement.py index ecef2b8..84f91b0 100644 --- a/achievement_api/routes/achievement.py +++ b/achievement_api/routes/achievement.py @@ -6,6 +6,7 @@ from fastapi_sqlalchemy import db from pydantic import BaseModel, ConfigDict +from achievement_api.base import StatusResponseModel from achievement_api.models import Achievement from achievement_api.settings import get_settings from achievement_api.utils.image import get_image_dimensions @@ -92,3 +93,15 @@ async def upload_picture( achievement.picture = f'static/{id}.png' db.session.commit() return achievement + + +@router.delete("/{id}", response_model=StatusResponseModel) +def delete_achievement(id: int, user=Depends(UnionAuth(['achievements.achievement.delete']))) -> StatusResponseModel: + """Нужны права на: `achievements.achievement.delete`""" + achievement: Achievement | None = db.session.get(Achievement, id) + if achievement is None: + raise HTTPException(404, f"Achievement {id=} not found") + logger.info(f"User id={user['id']} has deleted achievement {achievement.name}") + db.session.delete(achievement) + db.session.commit() + return StatusResponseModel(status="Success", message=f"Achievement {id=} has been deleted", ru="Ачивка удалена") diff --git a/tests/conftest.py b/tests/conftest.py index 38b1b30..61ee4a7 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,9 +1,26 @@ import pytest from fastapi.testclient import TestClient +from sqlalchemy import create_engine +from sqlalchemy.orm import sessionmaker from achievement_api.routes.base import app +from achievement_api.settings import get_settings @pytest.fixture def client(): yield TestClient(app) + + +@pytest.fixture(scope='session') +def dbsession(): + settings = get_settings() + engine = create_engine(str(settings.DB_DSN)) + TestingSessionLocal = sessionmaker(bind=engine) + yield TestingSessionLocal() + + +@pytest.fixture +def achievement_id(client): + post_response = client.post("/achievement", json={"name": "test name", "description": "test description"}) + yield post_response.json()["id"] diff --git a/tests/test_routes/test_achievement.py b/tests/test_routes/test_achievement.py new file mode 100644 index 0000000..dbbdfb7 --- /dev/null +++ b/tests/test_routes/test_achievement.py @@ -0,0 +1,18 @@ +import pytest + +from achievement_api.models.achievement import Achievement + + +@pytest.mark.authenticated("achievements.achievement.create", "achievements.achievement.delete") +def test_delete_existed(client, dbsession, achievement_id): + delete_response = client.delete(f"/achievement/{achievement_id}") + assert delete_response.status_code == 200 + query = dbsession.get(Achievement, achievement_id) + assert query is None + + +@pytest.mark.authenticated("achievements.achievement.delete") +def test_delete_unexisted(client): + unexisted_id = -1 + response = client.delete(f"/achievement/{unexisted_id}") + assert response.status_code == 404