diff --git a/client/html/banned_post_entry.tpl b/client/html/banned_post_entry.tpl
index defc6a92..87ec0f2a 100644
--- a/client/html/banned_post_entry.tpl
+++ b/client/html/banned_post_entry.tpl
@@ -1,9 +1,9 @@
-
<%- ctx.postBan.checksum %>
|
- <%- ctx.makeRelativeTime(ctx.postBan.time) %>
+ <%= ctx.makeRelativeTime(ctx.postBan.time) %>
|
<% if (ctx.canDelete) { %>
diff --git a/client/js/controllers/top_navigation_controller.js b/client/js/controllers/top_navigation_controller.js
index fbc5399d..da90959a 100644
--- a/client/js/controllers/top_navigation_controller.js
+++ b/client/js/controllers/top_navigation_controller.js
@@ -53,6 +53,9 @@ class TopNavigationController {
if (!api.hasPrivilege("pools:list")) {
topNavigation.hide("pools");
}
+ if (!api.hasPrivilege("posts:ban:list")) {
+ topNavigation.hide("banned-posts");
+ }
if (api.isLoggedIn()) {
if (!api.hasPrivilege("users:create:any")) {
topNavigation.hide("register");
diff --git a/client/js/models/banned_post_list.js b/client/js/models/banned_post_list.js
index 2665b4c1..61ac3a27 100644
--- a/client/js/models/banned_post_list.js
+++ b/client/js/models/banned_post_list.js
@@ -26,8 +26,8 @@ class BannedPostList extends AbstractList {
save() {
let promises = [];
- for (let BannedPost of this._deletedBans) {
- promises.push(BannedPost.delete());
+ for (let bannedPost of this._deletedBans) {
+ promises.push(bannedPost.delete());
}
return Promise.all(promises).then((response) => {
@@ -37,7 +37,7 @@ class BannedPostList extends AbstractList {
}
_evtBannedPostDeleted(e) {
- this._deletedBans.push(e.detail.BannedPost);
+ this._deletedBans.push(e.detail.bannedPost);
}
}
diff --git a/client/js/models/post.js b/client/js/models/post.js
index 15fb61ea..58374173 100644
--- a/client/js/models/post.js
+++ b/client/js/models/post.js
@@ -336,7 +336,8 @@ class Post extends events.EventTarget {
ban() {
return api
- .post(uri.formatApiLink("post-ban", this.id), {
+ .post(uri.formatApiLink("post-ban"), {
+ post_id: this.id,
version: this._version
})
.then((response) => {
diff --git a/client/js/models/top_navigation.js b/client/js/models/top_navigation.js
index a469a034..3a680010 100644
--- a/client/js/models/top_navigation.js
+++ b/client/js/models/top_navigation.js
@@ -90,6 +90,7 @@ function _makeTopNavigation() {
ret.add("login", new TopNavigationItem("L", "Log in", "login"));
ret.add("logout", new TopNavigationItem("O", "Logout", "logout"));
ret.add("help", new TopNavigationItem("E", "Help", "help"));
+ ret.add("banned-posts", new TopNavigationItem("B", "Banned posts", "banned-posts"));
ret.add(
"settings",
new TopNavigationItem(null, "", "settings")
diff --git a/client/js/views/banned_posts_view.js b/client/js/views/banned_posts_view.js
index 89fe3b4b..0a29d955 100644
--- a/client/js/views/banned_posts_view.js
+++ b/client/js/views/banned_posts_view.js
@@ -83,7 +83,7 @@ class BannedPostsView extends events.EventTarget {
}
_evtBannedPostDeleted(e) {
- this._removeBannedPostRowNode(e.detail.poolCategory);
+ this._removeBannedPostRowNode(e.detail.bannedPost);
}
_evtDeleteButtonClick(e, rowNode, link) {
diff --git a/doc/API.md b/doc/API.md
index 6287f61d..e388cb7a 100644
--- a/doc/API.md
+++ b/doc/API.md
@@ -912,7 +912,7 @@ data.
- **Output**
- A [post resource](#post).
+ A [post resource](#banned-post).
- **Errors**
@@ -1006,15 +1006,35 @@ data.
Deletes existing post. Related posts and tags are kept.
+
+## Listing banned posts
+- **Request**
+
+ `GET /post-ban`
+
+- **Output**
+
+ An [unpaged search result](#unpaged-search-result) of [banned posts](#postban).
+
+- **Errors**
+
+ - the post does not exist
+ - privileges are too low
+
+- **Description**
+
+ Retrieves information about an existing post.
+
## Banning post
- **Request**
- `POST /post-ban/`
+ `POST /post-ban`
- **Input**
```json5
{
+ "post_id":
"version":
}
```
@@ -1039,6 +1059,27 @@ data.
Related posts and tags are kept.
+## Undoing post ban
+- **Request**
+
+ `DELETE /post-ban/`
+
+- **Output**
+
+ ```json5
+ {}
+ ```
+
+- **Errors**
+
+ - there is no banned image with that hash
+ - privileges are too low
+
+- **Description**
+
+ Removes a banned image from the ban list. Takes a SHA-1 hash of the image as input.
+
+
## Merging posts
- **Request**
@@ -2617,6 +2658,26 @@ An ordered list of posts, with a description and category.
A [pool resource](#pool) stripped down to `id`, `names`, `category`,
`description` and `postCount` fields.
+
+## Banned post
+**Description**
+
+A record of a post that has been banned.
+
+**Structure**
+
+```json5
+{
+ "checksum": ,
+ "time":
+}
+```
+
+**Field meaning**
+- ``: SHA-1 hash of an image that has been banned
+- ``: time the post was banned
+
+
## Comment
**Description**
diff --git a/server/szurubooru/api/ban_api.py b/server/szurubooru/api/ban_api.py
index b6238815..10b0f956 100644
--- a/server/szurubooru/api/ban_api.py
+++ b/server/szurubooru/api/ban_api.py
@@ -1,8 +1,8 @@
from datetime import datetime
from typing import Dict, List, Optional
-from server.szurubooru.api import post_api
-from server.szurubooru.func import posts
-from server.szurubooru.model.bans import PostBan
+from szurubooru.api import post_api
+from szurubooru.func import posts
+from szurubooru.model.bans import PostBan
from szurubooru import db, errors, model, rest, search
from szurubooru.func import (
@@ -29,18 +29,6 @@ def _serialize(ctx: rest.Context, ban: model.PostBan) -> rest.Response:
)
-@rest.routes.post("/post-ban/(?P[^/]+)/?")
-def ban_post(ctx: rest.Context, params: Dict[str, str]) -> rest.Response:
- auth.verify_privilege(ctx.user, "posts:ban:create")
- post = post_api._get_post(params)
- versions.verify_version(post, ctx)
- posts.ban(bans.create_ban(post))
- snapshots.delete(post, ctx.user)
- posts.delete(post)
- ctx.session.commit()
- return {}
-
-
@rest.routes.delete("/post-ban/(?P[^/]+)/?")
def unban_post(ctx: rest.Context, params: Dict[str, str]) -> rest.Response:
auth.verify_privilege(ctx.user, "posts:ban:delete")
@@ -50,9 +38,21 @@ def unban_post(ctx: rest.Context, params: Dict[str, str]) -> rest.Response:
return {}
+@rest.routes.post("/post-ban/?")
+def ban_post(ctx: rest.Context, params: Dict[str, str]) -> rest.Response:
+ auth.verify_privilege(ctx.user, "posts:ban:create")
+ # post = post_api._get_post(params)
+ post = posts.get_post_by_id(ctx.get_param_as_int("post_id"))
+ versions.verify_version(post, ctx)
+ posts.ban(bans.create_ban(post))
+ snapshots.delete(post, ctx.user)
+ posts.delete(post)
+ ctx.session.commit()
+ return {}
+
@rest.routes.get("/post-ban/?")
def get_bans(ctx: rest.Context, _params: Dict[str, str] = {}) -> rest.Response:
auth.verify_privilege(ctx.user, "posts:ban:list")
return _search_executor.execute_and_serialize(
- ctx, lambda tag: _serialize(ctx, tag)
+ ctx, lambda ban: _serialize(ctx, ban)
)
diff --git a/server/szurubooru/func/bans.py b/server/szurubooru/func/bans.py
index 35946cc4..694dda62 100644
--- a/server/szurubooru/func/bans.py
+++ b/server/szurubooru/func/bans.py
@@ -15,7 +15,7 @@ class HashNotBannedError(errors.ValidationError):
pass
-class TagSerializer(serialization.BaseSerializer):
+class BanSerializer(serialization.BaseSerializer):
def __init__(self, ban: model.PostBan) -> None:
self.ban = ban
@@ -65,4 +65,4 @@ def serialize_ban(
) -> Optional[rest.Response]:
if not ban:
return None
- return serialization.BaseSerializer(ban).serialize(options)
+ return BanSerializer(ban).serialize(options)
diff --git a/server/szurubooru/func/posts.py b/server/szurubooru/func/posts.py
index 7ec779f7..0348532b 100644
--- a/server/szurubooru/func/posts.py
+++ b/server/szurubooru/func/posts.py
@@ -4,7 +4,7 @@ from datetime import datetime
from typing import Any, Callable, Dict, List, Optional, Tuple
import sqlalchemy as sa
-from server.szurubooru.func.bans import PostBannedError
+from szurubooru.func.bans import PostBannedError
from szurubooru import config, db, errors, model, rest
from szurubooru.func import (
diff --git a/server/szurubooru/search/configs/ban_search_config.py b/server/szurubooru/search/configs/ban_search_config.py
index 8977f4a9..ce8bba7d 100644
--- a/server/szurubooru/search/configs/ban_search_config.py
+++ b/server/szurubooru/search/configs/ban_search_config.py
@@ -14,17 +14,7 @@ from szurubooru.search.typing import SaColumn, SaQuery
class BanSearchConfig(BaseSearchConfig):
def create_filter_query(self, _disable_eager_loads: bool) -> SaQuery:
- strategy = (
- sa.orm.lazyload if _disable_eager_loads else sa.orm.subqueryload
- )
- return (
- db.session.query(model.PostBan)
- .options(
- sa.orm.defer(model.PostBan.checksum),
- sa.orm.defer(model.PostBan.time),
- sa.orm.defer(model.PostBan.ban_id)
- )
- )
+ return db.session.query(model.PostBan)
def create_count_query(self, _disable_eager_loads: bool) -> SaQuery:
return db.session.query(model.PostBan)
|