Fix some bugs, document new API

This commit is contained in:
rebel 2023-05-17 03:30:49 +02:00
parent bd8cdc8509
commit 002f49d7db
11 changed files with 95 additions and 39 deletions

View file

@ -1,9 +1,9 @@
<tr data-category='<%- ctx.postBan.checksum %>'><% <tr data-category='<%- ctx.postBan.checksum %>'>
<td class='name'> <td class='name'>
<%- ctx.postBan.checksum %> <%- ctx.postBan.checksum %>
</td> </td>
<td class='time'> <td class='time'>
<%- ctx.makeRelativeTime(ctx.postBan.time) %> <%= ctx.makeRelativeTime(ctx.postBan.time) %>
</td> </td>
<% if (ctx.canDelete) { %> <% if (ctx.canDelete) { %>
<td class='remove'> <td class='remove'>

View file

@ -53,6 +53,9 @@ class TopNavigationController {
if (!api.hasPrivilege("pools:list")) { if (!api.hasPrivilege("pools:list")) {
topNavigation.hide("pools"); topNavigation.hide("pools");
} }
if (!api.hasPrivilege("posts:ban:list")) {
topNavigation.hide("banned-posts");
}
if (api.isLoggedIn()) { if (api.isLoggedIn()) {
if (!api.hasPrivilege("users:create:any")) { if (!api.hasPrivilege("users:create:any")) {
topNavigation.hide("register"); topNavigation.hide("register");

View file

@ -26,8 +26,8 @@ class BannedPostList extends AbstractList {
save() { save() {
let promises = []; let promises = [];
for (let BannedPost of this._deletedBans) { for (let bannedPost of this._deletedBans) {
promises.push(BannedPost.delete()); promises.push(bannedPost.delete());
} }
return Promise.all(promises).then((response) => { return Promise.all(promises).then((response) => {
@ -37,7 +37,7 @@ class BannedPostList extends AbstractList {
} }
_evtBannedPostDeleted(e) { _evtBannedPostDeleted(e) {
this._deletedBans.push(e.detail.BannedPost); this._deletedBans.push(e.detail.bannedPost);
} }
} }

View file

@ -336,7 +336,8 @@ class Post extends events.EventTarget {
ban() { ban() {
return api return api
.post(uri.formatApiLink("post-ban", this.id), { .post(uri.formatApiLink("post-ban"), {
post_id: this.id,
version: this._version version: this._version
}) })
.then((response) => { .then((response) => {

View file

@ -90,6 +90,7 @@ function _makeTopNavigation() {
ret.add("login", new TopNavigationItem("L", "Log in", "login")); ret.add("login", new TopNavigationItem("L", "Log in", "login"));
ret.add("logout", new TopNavigationItem("O", "Logout", "logout")); ret.add("logout", new TopNavigationItem("O", "Logout", "logout"));
ret.add("help", new TopNavigationItem("E", "Help", "help")); ret.add("help", new TopNavigationItem("E", "Help", "help"));
ret.add("banned-posts", new TopNavigationItem("B", "Banned posts", "banned-posts"));
ret.add( ret.add(
"settings", "settings",
new TopNavigationItem(null, "<i class='fa fa-cog'></i>", "settings") new TopNavigationItem(null, "<i class='fa fa-cog'></i>", "settings")

View file

@ -83,7 +83,7 @@ class BannedPostsView extends events.EventTarget {
} }
_evtBannedPostDeleted(e) { _evtBannedPostDeleted(e) {
this._removeBannedPostRowNode(e.detail.poolCategory); this._removeBannedPostRowNode(e.detail.bannedPost);
} }
_evtDeleteButtonClick(e, rowNode, link) { _evtDeleteButtonClick(e, rowNode, link) {

View file

@ -912,7 +912,7 @@ data.
- **Output** - **Output**
A [post resource](#post). A [post resource](#banned-post).
- **Errors** - **Errors**
@ -1006,15 +1006,35 @@ data.
Deletes existing post. Related posts and tags are kept. 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 ## Banning post
- **Request** - **Request**
`POST /post-ban/<id>` `POST /post-ban`
- **Input** - **Input**
```json5 ```json5
{ {
"post_id": <post id>
"version": <version> "version": <version>
} }
``` ```
@ -1039,6 +1059,27 @@ data.
Related posts and tags are kept. Related posts and tags are kept.
## Undoing post ban
- **Request**
`DELETE /post-ban/<image_hash>`
- **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 ## Merging posts
- **Request** - **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`, A [pool resource](#pool) stripped down to `id`, `names`, `category`,
`description` and `postCount` fields. `description` and `postCount` fields.
## Banned post
**Description**
A record of a post that has been banned.
**Structure**
```json5
{
"checksum": <sha-hash>,
"time": <time-of-ban>
}
```
**Field meaning**
- `<sha-hash>`: SHA-1 hash of an image that has been banned
- `<time-of-ban>`: time the post was banned
## Comment ## Comment
**Description** **Description**

View file

@ -1,8 +1,8 @@
from datetime import datetime from datetime import datetime
from typing import Dict, List, Optional from typing import Dict, List, Optional
from server.szurubooru.api import post_api from szurubooru.api import post_api
from server.szurubooru.func import posts from szurubooru.func import posts
from server.szurubooru.model.bans import PostBan from szurubooru.model.bans import PostBan
from szurubooru import db, errors, model, rest, search from szurubooru import db, errors, model, rest, search
from szurubooru.func import ( from szurubooru.func import (
@ -29,18 +29,6 @@ def _serialize(ctx: rest.Context, ban: model.PostBan) -> rest.Response:
) )
@rest.routes.post("/post-ban/(?P<post_id>[^/]+)/?")
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<image_hash>[^/]+)/?") @rest.routes.delete("/post-ban/(?P<image_hash>[^/]+)/?")
def unban_post(ctx: rest.Context, params: Dict[str, str]) -> rest.Response: def unban_post(ctx: rest.Context, params: Dict[str, str]) -> rest.Response:
auth.verify_privilege(ctx.user, "posts:ban:delete") 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 {} 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/?") @rest.routes.get("/post-ban/?")
def get_bans(ctx: rest.Context, _params: Dict[str, str] = {}) -> rest.Response: def get_bans(ctx: rest.Context, _params: Dict[str, str] = {}) -> rest.Response:
auth.verify_privilege(ctx.user, "posts:ban:list") auth.verify_privilege(ctx.user, "posts:ban:list")
return _search_executor.execute_and_serialize( return _search_executor.execute_and_serialize(
ctx, lambda tag: _serialize(ctx, tag) ctx, lambda ban: _serialize(ctx, ban)
) )

View file

@ -15,7 +15,7 @@ class HashNotBannedError(errors.ValidationError):
pass pass
class TagSerializer(serialization.BaseSerializer): class BanSerializer(serialization.BaseSerializer):
def __init__(self, ban: model.PostBan) -> None: def __init__(self, ban: model.PostBan) -> None:
self.ban = ban self.ban = ban
@ -65,4 +65,4 @@ def serialize_ban(
) -> Optional[rest.Response]: ) -> Optional[rest.Response]:
if not ban: if not ban:
return None return None
return serialization.BaseSerializer(ban).serialize(options) return BanSerializer(ban).serialize(options)

View file

@ -4,7 +4,7 @@ from datetime import datetime
from typing import Any, Callable, Dict, List, Optional, Tuple from typing import Any, Callable, Dict, List, Optional, Tuple
import sqlalchemy as sa 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 import config, db, errors, model, rest
from szurubooru.func import ( from szurubooru.func import (

View file

@ -14,17 +14,7 @@ from szurubooru.search.typing import SaColumn, SaQuery
class BanSearchConfig(BaseSearchConfig): class BanSearchConfig(BaseSearchConfig):
def create_filter_query(self, _disable_eager_loads: bool) -> SaQuery: def create_filter_query(self, _disable_eager_loads: bool) -> SaQuery:
strategy = ( return db.session.query(model.PostBan)
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)
)
)
def create_count_query(self, _disable_eager_loads: bool) -> SaQuery: def create_count_query(self, _disable_eager_loads: bool) -> SaQuery:
return db.session.query(model.PostBan) return db.session.query(model.PostBan)