diff --git a/API.md b/API.md index 6904d6d..83f0fc9 100644 --- a/API.md +++ b/API.md @@ -32,7 +32,7 @@ - ~~Creating post~~ - ~~Updating post~~ - [Getting post](#getting-post) - - ~~Deleting post~~ + - [Deleting post](#deleting-post) - [Rating post](#rating-post) - ~~Adding post to favorites~~ - ~~Removing post from favorites~~ @@ -647,6 +647,27 @@ data. Retrieves information about an existing post. +## Deleting post +- **Request** + + `DELETE /post/` + +- **Output** + + ```json5 + {} + ``` + +- **Errors** + + - the post does not exist + - privileges are too low + +- **Description** + + Deletes existing post. Related posts and tags are kept. + + ## Rating post - **Request** diff --git a/server/szurubooru/api/post_api.py b/server/szurubooru/api/post_api.py index 1613133..81992bd 100644 --- a/server/szurubooru/api/post_api.py +++ b/server/szurubooru/api/post_api.py @@ -1,5 +1,5 @@ from szurubooru.api.base_api import BaseApi -from szurubooru.func import auth, posts, snapshots, scores +from szurubooru.func import auth, tags, posts, snapshots, scores class PostDetailApi(BaseApi): def get(self, ctx, post_id): @@ -7,6 +7,15 @@ class PostDetailApi(BaseApi): post = posts.get_post_by_id(post_id) return posts.serialize_post_with_details(post, ctx.user) + def delete(self, ctx, post_id): + auth.verify_privilege(ctx.user, 'posts:delete') + post = posts.get_post_by_id(post_id) + snapshots.delete(post, ctx.user) + ctx.session.delete(post) + ctx.session.commit() + tags.export_to_json() + return {} + class PostFeatureApi(BaseApi): def post(self, ctx): auth.verify_privilege(ctx.user, 'posts:feature') diff --git a/server/szurubooru/tests/api/test_post_deleting.py b/server/szurubooru/tests/api/test_post_deleting.py new file mode 100644 index 0000000..6a49c7c --- /dev/null +++ b/server/szurubooru/tests/api/test_post_deleting.py @@ -0,0 +1,49 @@ +import pytest +import os +from datetime import datetime +from szurubooru import api, config, db, errors +from szurubooru.func import util, posts + +@pytest.fixture +def test_ctx( + tmpdir, config_injector, context_factory, post_factory, user_factory): + config_injector({ + 'data_dir': str(tmpdir), + 'privileges': { + 'posts:delete': 'regular_user', + }, + 'ranks': ['anonymous', 'regular_user'], + }) + ret = util.dotdict() + ret.context_factory = context_factory + ret.user_factory = user_factory + ret.post_factory = post_factory + ret.api = api.PostDetailApi() + return ret + +def test_deleting(test_ctx): + db.session.add(test_ctx.post_factory(id=1)) + db.session.commit() + result = test_ctx.api.delete( + test_ctx.context_factory( + user=test_ctx.user_factory(rank='regular_user')), + 1) + assert result == {} + assert db.session.query(db.Post).count() == 0 + assert os.path.exists(os.path.join(config.config['data_dir'], 'tags.json')) + +def test_trying_to_delete_non_existing(test_ctx): + with pytest.raises(posts.PostNotFoundError): + test_ctx.api.delete( + test_ctx.context_factory( + user=test_ctx.user_factory(rank='regular_user')), 'bad') + +def test_trying_to_delete_without_privileges(test_ctx): + db.session.add(test_ctx.post_factory(id=1)) + db.session.commit() + with pytest.raises(errors.AuthError): + test_ctx.api.delete( + test_ctx.context_factory( + user=test_ctx.user_factory(rank='anonymous')), + 1) + assert db.session.query(db.Post).count() == 1