Merge branch 'feature/reports-groups-and-multiple-state-update' into 'develop'
Admin API: Grouped reports, update multiple reports in one query Closes admin-fe#43 See merge request pleroma/pleroma!1815
This commit is contained in:
commit
1afeaf82fa
|
@ -25,6 +25,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
|
|
||||||
- **Breaking** Admin API: `PATCH /api/pleroma/admin/users/:nickname/force_password_reset` is now `PATCH /api/pleroma/admin/users/force_password_reset` (accepts `nicknames` array in the request body)
|
- **Breaking** Admin API: `PATCH /api/pleroma/admin/users/:nickname/force_password_reset` is now `PATCH /api/pleroma/admin/users/force_password_reset` (accepts `nicknames` array in the request body)
|
||||||
- **Breaking:** Admin API: Return link alongside with token on password reset
|
- **Breaking:** Admin API: Return link alongside with token on password reset
|
||||||
|
- **Breaking:** Admin API: `PUT /api/pleroma/admin/reports/:id` is now `PATCH /api/pleroma/admin/reports`, see admin_api.md for details
|
||||||
- **Breaking:** `/api/pleroma/admin/users/invite_token` now uses `POST`, changed accepted params and returns full invite in json instead of only token string.
|
- **Breaking:** `/api/pleroma/admin/users/invite_token` now uses `POST`, changed accepted params and returns full invite in json instead of only token string.
|
||||||
- Admin API: Return `total` when querying for reports
|
- Admin API: Return `total` when querying for reports
|
||||||
- Mastodon API: Return `pleroma.direct_conversation_id` when creating a direct message (`POST /api/v1/statuses`)
|
- Mastodon API: Return `pleroma.direct_conversation_id` when creating a direct message (`POST /api/v1/statuses`)
|
||||||
|
@ -45,6 +46,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
<summary>API Changes</summary>
|
<summary>API Changes</summary>
|
||||||
|
|
||||||
- Job queue stats to the healthcheck page
|
- Job queue stats to the healthcheck page
|
||||||
|
- Admin API: Add ability to fetch reports, grouped by status `GET /api/pleroma/admin/grouped_reports`
|
||||||
- Admin API: Add ability to require password reset
|
- Admin API: Add ability to require password reset
|
||||||
- Mastodon API: Account entities now include `follow_requests_count` (planned Mastodon 3.x addition)
|
- Mastodon API: Account entities now include `follow_requests_count` (planned Mastodon 3.x addition)
|
||||||
- Pleroma API: `GET /api/v1/pleroma/accounts/:id/scrobbles` to get a list of recently scrobbled items
|
- Pleroma API: `GET /api/v1/pleroma/accounts/:id/scrobbles` to get a list of recently scrobbled items
|
||||||
|
@ -56,7 +58,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- Mix task to re-count statuses for all users (`mix pleroma.count_statuses`)
|
- Mix task to re-count statuses for all users (`mix pleroma.count_statuses`)
|
||||||
- Mastodon API: Add `exclude_visibilities` parameter to the timeline and notification endpoints
|
- Mastodon API: Add `exclude_visibilities` parameter to the timeline and notification endpoints
|
||||||
- Admin API: `/users/:nickname/toggle_activation` endpoint is now deprecated in favor of: `/users/activate`, `/users/deactivate`, both accept `nicknames` array
|
- Admin API: `/users/:nickname/toggle_activation` endpoint is now deprecated in favor of: `/users/activate`, `/users/deactivate`, both accept `nicknames` array
|
||||||
- Admin API: `POST/DELETE /api/pleroma/admin/users/:nickname/permission_group/:permission_group` are deprecated in favor of: `POST/DELETE /api/pleroma/admin/users/permission_group/:permission_group` (both accept `nicknames` array), `DELETE /api/pleroma/admin/users` (`nickname` query param or `nickname` sent in JSON body) is deprecated in favor of: `DELETE /api/pleroma/admin/users` (`nicknames` query array param or `nicknames` sent in JSON body).
|
- Admin API: Multiple endpoints now require `nicknames` array, instead of singe `nickname`:
|
||||||
|
- `POST/DELETE /api/pleroma/admin/users/:nickname/permission_group/:permission_group` are deprecated in favor of: `POST/DELETE /api/pleroma/admin/users/permission_group/:permission_group`
|
||||||
|
- `DELETE /api/pleroma/admin/users` (`nickname` query param or `nickname` sent in JSON body) is deprecated in favor of: `DELETE /api/pleroma/admin/users` (`nicknames` query array param or `nicknames` sent in JSON body)
|
||||||
- Admin API: Add `GET /api/pleroma/admin/relay` endpoint - lists all followed relays
|
- Admin API: Add `GET /api/pleroma/admin/relay` endpoint - lists all followed relays
|
||||||
- Pleroma API: `POST /api/v1/pleroma/conversations/read` to mark all conversations as read
|
- Pleroma API: `POST /api/v1/pleroma/conversations/read` to mark all conversations as read
|
||||||
- Mastodon API: Add `/api/v1/markers` for managing timeline read markers
|
- Mastodon API: Add `/api/v1/markers` for managing timeline read markers
|
||||||
|
|
|
@ -2,11 +2,10 @@
|
||||||
|
|
||||||
Authentication is required and the user must be an admin.
|
Authentication is required and the user must be an admin.
|
||||||
|
|
||||||
## `/api/pleroma/admin/users`
|
## `GET /api/pleroma/admin/users`
|
||||||
|
|
||||||
### List users
|
### List users
|
||||||
|
|
||||||
- Method `GET`
|
|
||||||
- Query Params:
|
- Query Params:
|
||||||
- *optional* `query`: **string** search term (e.g. nickname, domain, nickname@domain)
|
- *optional* `query`: **string** search term (e.g. nickname, domain, nickname@domain)
|
||||||
- *optional* `filters`: **string** comma-separated string of filters:
|
- *optional* `filters`: **string** comma-separated string of filters:
|
||||||
|
@ -51,7 +50,6 @@ Authentication is required and the user must be an admin.
|
||||||
|
|
||||||
### Remove a user
|
### Remove a user
|
||||||
|
|
||||||
- Method `DELETE`
|
|
||||||
- Params:
|
- Params:
|
||||||
- `nickname`
|
- `nickname`
|
||||||
- Response: User’s nickname
|
- Response: User’s nickname
|
||||||
|
@ -60,7 +58,6 @@ Authentication is required and the user must be an admin.
|
||||||
|
|
||||||
### Remove a user
|
### Remove a user
|
||||||
|
|
||||||
- Method `DELETE`
|
|
||||||
- Params:
|
- Params:
|
||||||
- `nicknames`
|
- `nicknames`
|
||||||
- Response: Array of user nicknames
|
- Response: Array of user nicknames
|
||||||
|
@ -78,31 +75,30 @@ Authentication is required and the user must be an admin.
|
||||||
]
|
]
|
||||||
- Response: User’s nickname
|
- Response: User’s nickname
|
||||||
|
|
||||||
## `/api/pleroma/admin/users/follow`
|
## `POST /api/pleroma/admin/users/follow`
|
||||||
|
|
||||||
### Make a user follow another user
|
### Make a user follow another user
|
||||||
|
|
||||||
- Methods: `POST`
|
|
||||||
- Params:
|
- Params:
|
||||||
- `follower`: The nickname of the follower
|
- `follower`: The nickname of the follower
|
||||||
- `followed`: The nickname of the followed
|
- `followed`: The nickname of the followed
|
||||||
- Response:
|
- Response:
|
||||||
- "ok"
|
- "ok"
|
||||||
|
|
||||||
## `/api/pleroma/admin/users/unfollow`
|
## `POST /api/pleroma/admin/users/unfollow`
|
||||||
|
|
||||||
### Make a user unfollow another user
|
### Make a user unfollow another user
|
||||||
|
|
||||||
- Methods: `POST`
|
|
||||||
- Params:
|
- Params:
|
||||||
- `follower`: The nickname of the follower
|
- `follower`: The nickname of the follower
|
||||||
- `followed`: The nickname of the followed
|
- `followed`: The nickname of the followed
|
||||||
- Response:
|
- Response:
|
||||||
- "ok"
|
- "ok"
|
||||||
|
|
||||||
## `/api/pleroma/admin/users/:nickname/toggle_activation`
|
## `PATCH /api/pleroma/admin/users/:nickname/toggle_activation`
|
||||||
|
|
||||||
### Toggle user activation
|
### Toggle user activation
|
||||||
|
|
||||||
- Method: `PATCH`
|
|
||||||
- Params:
|
- Params:
|
||||||
- `nickname`
|
- `nickname`
|
||||||
- Response: User’s object
|
- Response: User’s object
|
||||||
|
@ -115,27 +111,26 @@ Authentication is required and the user must be an admin.
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## `/api/pleroma/admin/users/tag`
|
## `PUT /api/pleroma/admin/users/tag`
|
||||||
|
|
||||||
### Tag a list of users
|
### Tag a list of users
|
||||||
|
|
||||||
- Method: `PUT`
|
|
||||||
- Params:
|
- Params:
|
||||||
- `nicknames` (array)
|
- `nicknames` (array)
|
||||||
- `tags` (array)
|
- `tags` (array)
|
||||||
|
|
||||||
|
## `DELETE /api/pleroma/admin/users/tag`
|
||||||
|
|
||||||
### Untag a list of users
|
### Untag a list of users
|
||||||
|
|
||||||
- Method: `DELETE`
|
|
||||||
- Params:
|
- Params:
|
||||||
- `nicknames` (array)
|
- `nicknames` (array)
|
||||||
- `tags` (array)
|
- `tags` (array)
|
||||||
|
|
||||||
## `/api/pleroma/admin/users/:nickname/permission_group`
|
## `GET /api/pleroma/admin/users/:nickname/permission_group`
|
||||||
|
|
||||||
### Get user user permission groups membership
|
### Get user user permission groups membership
|
||||||
|
|
||||||
- Method: `GET`
|
|
||||||
- Params: none
|
- Params: none
|
||||||
- Response:
|
- Response:
|
||||||
|
|
||||||
|
@ -146,13 +141,12 @@ Authentication is required and the user must be an admin.
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## `/api/pleroma/admin/users/:nickname/permission_group/:permission_group`
|
## `GET /api/pleroma/admin/users/:nickname/permission_group/:permission_group`
|
||||||
|
|
||||||
Note: Available `:permission_group` is currently moderator and admin. 404 is returned when the permission group doesn’t exist.
|
Note: Available `:permission_group` is currently moderator and admin. 404 is returned when the permission group doesn’t exist.
|
||||||
|
|
||||||
### Get user user permission groups membership per permission group
|
### Get user user permission groups membership per permission group
|
||||||
|
|
||||||
- Method: `GET`
|
|
||||||
- Params: none
|
- Params: none
|
||||||
- Response:
|
- Response:
|
||||||
|
|
||||||
|
@ -184,6 +178,8 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret
|
||||||
|
|
||||||
## DEPRECATED `DELETE /api/pleroma/admin/users/:nickname/permission_group/:permission_group`
|
## DEPRECATED `DELETE /api/pleroma/admin/users/:nickname/permission_group/:permission_group`
|
||||||
|
|
||||||
|
## `DELETE /api/pleroma/admin/users/:nickname/permission_group/:permission_group`
|
||||||
|
|
||||||
### Remove user from permission group
|
### Remove user from permission group
|
||||||
|
|
||||||
- Params: none
|
- Params: none
|
||||||
|
@ -247,22 +243,20 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret
|
||||||
- `nickname`
|
- `nickname`
|
||||||
- `status` BOOLEAN field, false value means deactivation.
|
- `status` BOOLEAN field, false value means deactivation.
|
||||||
|
|
||||||
## `/api/pleroma/admin/users/:nickname_or_id`
|
## `GET /api/pleroma/admin/users/:nickname_or_id`
|
||||||
|
|
||||||
### Retrive the details of a user
|
### Retrive the details of a user
|
||||||
|
|
||||||
- Method: `GET`
|
|
||||||
- Params:
|
- Params:
|
||||||
- `nickname` or `id`
|
- `nickname` or `id`
|
||||||
- Response:
|
- Response:
|
||||||
- On failure: `Not found`
|
- On failure: `Not found`
|
||||||
- On success: JSON of the user
|
- On success: JSON of the user
|
||||||
|
|
||||||
## `/api/pleroma/admin/users/:nickname_or_id/statuses`
|
## `GET /api/pleroma/admin/users/:nickname_or_id/statuses`
|
||||||
|
|
||||||
### Retrive user's latest statuses
|
### Retrive user's latest statuses
|
||||||
|
|
||||||
- Method: `GET`
|
|
||||||
- Params:
|
- Params:
|
||||||
- `nickname` or `id`
|
- `nickname` or `id`
|
||||||
- *optional* `page_size`: number of statuses to return (default is `20`)
|
- *optional* `page_size`: number of statuses to return (default is `20`)
|
||||||
|
@ -271,19 +265,19 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret
|
||||||
- On failure: `Not found`
|
- On failure: `Not found`
|
||||||
- On success: JSON array of user's latest statuses
|
- On success: JSON array of user's latest statuses
|
||||||
|
|
||||||
## `/api/pleroma/admin/relay`
|
## `POST /api/pleroma/admin/relay`
|
||||||
|
|
||||||
### Follow a Relay
|
### Follow a Relay
|
||||||
|
|
||||||
- Methods: `POST`
|
|
||||||
- Params:
|
- Params:
|
||||||
- `relay_url`
|
- `relay_url`
|
||||||
- Response:
|
- Response:
|
||||||
- On success: URL of the followed relay
|
- On success: URL of the followed relay
|
||||||
|
|
||||||
|
## `DELETE /api/pleroma/admin/relay`
|
||||||
|
|
||||||
### Unfollow a Relay
|
### Unfollow a Relay
|
||||||
|
|
||||||
- Methods: `DELETE`
|
|
||||||
- Params:
|
- Params:
|
||||||
- `relay_url`
|
- `relay_url`
|
||||||
- Response:
|
- Response:
|
||||||
|
@ -297,11 +291,10 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret
|
||||||
- Response:
|
- Response:
|
||||||
- On success: JSON array of relays
|
- On success: JSON array of relays
|
||||||
|
|
||||||
## `/api/pleroma/admin/users/invite_token`
|
## `POST /api/pleroma/admin/users/invite_token`
|
||||||
|
|
||||||
### Create an account registration invite token
|
### Create an account registration invite token
|
||||||
|
|
||||||
- Methods: `POST`
|
|
||||||
- Params:
|
- Params:
|
||||||
- *optional* `max_use` (integer)
|
- *optional* `max_use` (integer)
|
||||||
- *optional* `expires_at` (date string e.g. "2019-04-07")
|
- *optional* `expires_at` (date string e.g. "2019-04-07")
|
||||||
|
@ -319,11 +312,10 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## `/api/pleroma/admin/users/invites`
|
## `GET /api/pleroma/admin/users/invites`
|
||||||
|
|
||||||
### Get a list of generated invites
|
### Get a list of generated invites
|
||||||
|
|
||||||
- Methods: `GET`
|
|
||||||
- Params: none
|
- Params: none
|
||||||
- Response:
|
- Response:
|
||||||
|
|
||||||
|
@ -345,11 +337,10 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## `/api/pleroma/admin/users/revoke_invite`
|
## `POST /api/pleroma/admin/users/revoke_invite`
|
||||||
|
|
||||||
### Revoke invite by token
|
### Revoke invite by token
|
||||||
|
|
||||||
- Methods: `POST`
|
|
||||||
- Params:
|
- Params:
|
||||||
- `token`
|
- `token`
|
||||||
- Response:
|
- Response:
|
||||||
|
@ -367,21 +358,18 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## `POST /api/pleroma/admin/users/email_invite`
|
||||||
## `/api/pleroma/admin/users/email_invite`
|
|
||||||
|
|
||||||
### Sends registration invite via email
|
### Sends registration invite via email
|
||||||
|
|
||||||
- Methods: `POST`
|
|
||||||
- Params:
|
- Params:
|
||||||
- `email`
|
- `email`
|
||||||
- `name`, optional
|
- `name`, optional
|
||||||
|
|
||||||
## `/api/pleroma/admin/users/:nickname/password_reset`
|
## `GET /api/pleroma/admin/users/:nickname/password_reset`
|
||||||
|
|
||||||
### Get a password reset token for a given nickname
|
### Get a password reset token for a given nickname
|
||||||
|
|
||||||
- Methods: `GET`
|
|
||||||
- Params: none
|
- Params: none
|
||||||
- Response:
|
- Response:
|
||||||
|
|
||||||
|
@ -392,18 +380,18 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## `/api/pleroma/admin/users/force_password_reset`
|
## `PATCH /api/pleroma/admin/users/force_password_reset`
|
||||||
|
|
||||||
### Force passord reset for a user with a given nickname
|
### Force passord reset for a user with a given nickname
|
||||||
|
|
||||||
- Methods: `PATCH`
|
|
||||||
- Params:
|
- Params:
|
||||||
- `nicknames`
|
- `nicknames`
|
||||||
- Response: none (code `204`)
|
- Response: none (code `204`)
|
||||||
|
|
||||||
## `/api/pleroma/admin/reports`
|
## `GET /api/pleroma/admin/reports`
|
||||||
|
|
||||||
### Get a list of reports
|
### Get a list of reports
|
||||||
- Method `GET`
|
|
||||||
- Params:
|
- Params:
|
||||||
- *optional* `state`: **string** the state of reports. Valid values are `open`, `closed` and `resolved`
|
- *optional* `state`: **string** the state of reports. Valid values are `open`, `closed` and `resolved`
|
||||||
- *optional* `limit`: **integer** the number of records to retrieve
|
- *optional* `limit`: **integer** the number of records to retrieve
|
||||||
|
@ -418,7 +406,7 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"total" : 1,
|
"totalReports" : 1,
|
||||||
"reports": [
|
"reports": [
|
||||||
{
|
{
|
||||||
"account": {
|
"account": {
|
||||||
|
@ -560,9 +548,34 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## `/api/pleroma/admin/reports/:id`
|
## `GET /api/pleroma/admin/grouped_reports`
|
||||||
|
|
||||||
|
### Get a list of reports, grouped by status
|
||||||
|
|
||||||
|
- Params: none
|
||||||
|
- On success: JSON, returns a list of reports, where:
|
||||||
|
- `date`: date of the latest report
|
||||||
|
- `account`: the user who has been reported (see `/api/pleroma/admin/reports` for reference)
|
||||||
|
- `status`: reported status (see `/api/pleroma/admin/reports` for reference)
|
||||||
|
- `actors`: users who had reported this status (see `/api/pleroma/admin/reports` for reference)
|
||||||
|
- `reports`: reports (see `/api/pleroma/admin/reports` for reference)
|
||||||
|
|
||||||
|
```json
|
||||||
|
"reports": [
|
||||||
|
{
|
||||||
|
"date": "2019-10-07T12:31:39.615149Z",
|
||||||
|
"account": { ... },
|
||||||
|
"status": { ... },
|
||||||
|
"actors": [{ ... }, { ... }],
|
||||||
|
"reports": [{ ... }]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
## `GET /api/pleroma/admin/reports/:id`
|
||||||
|
|
||||||
### Get an individual report
|
### Get an individual report
|
||||||
- Method `GET`
|
|
||||||
- Params:
|
- Params:
|
||||||
- `id`
|
- `id`
|
||||||
- Response:
|
- Response:
|
||||||
|
@ -571,22 +584,41 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret
|
||||||
- 404 Not Found `"Not found"`
|
- 404 Not Found `"Not found"`
|
||||||
- On success: JSON, Report object (see above)
|
- On success: JSON, Report object (see above)
|
||||||
|
|
||||||
## `/api/pleroma/admin/reports/:id`
|
## `PATCH /api/pleroma/admin/reports`
|
||||||
### Change the state of the report
|
|
||||||
- Method `PUT`
|
### Change the state of one or multiple reports
|
||||||
|
|
||||||
- Params:
|
- Params:
|
||||||
- `id`
|
|
||||||
- `state`: required, the new state. Valid values are `open`, `closed` and `resolved`
|
```json
|
||||||
|
`reports`: [
|
||||||
|
{
|
||||||
|
`id`, // required, report id
|
||||||
|
`state` // required, the new state. Valid values are `open`, `closed` and `resolved`
|
||||||
|
},
|
||||||
|
...
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
- Response:
|
- Response:
|
||||||
- On failure:
|
- On failure:
|
||||||
- 400 Bad Request `"Unsupported state"`
|
- 400 Bad Request, JSON:
|
||||||
- 403 Forbidden `{"error": "error_msg"}`
|
|
||||||
- 404 Not Found `"Not found"`
|
```json
|
||||||
- On success: JSON, Report object (see above)
|
[
|
||||||
|
{
|
||||||
|
`id`, // report id
|
||||||
|
`error` // error message
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
- On success: `204`, empty response
|
||||||
|
|
||||||
|
## `POST /api/pleroma/admin/reports/:id/respond`
|
||||||
|
|
||||||
## `/api/pleroma/admin/reports/:id/respond`
|
|
||||||
### Respond to a report
|
### Respond to a report
|
||||||
- Method `POST`
|
|
||||||
- Params:
|
- Params:
|
||||||
- `id`
|
- `id`
|
||||||
- `status`: required, the message
|
- `status`: required, the message
|
||||||
|
@ -656,9 +688,10 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## `/api/pleroma/admin/statuses/:id`
|
## `PUT /api/pleroma/admin/statuses/:id`
|
||||||
|
|
||||||
### Change the scope of an individual reported status
|
### Change the scope of an individual reported status
|
||||||
- Method `PUT`
|
|
||||||
- Params:
|
- Params:
|
||||||
- `id`
|
- `id`
|
||||||
- `sensitive`: optional, valid values are `true` or `false`
|
- `sensitive`: optional, valid values are `true` or `false`
|
||||||
|
@ -670,9 +703,10 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret
|
||||||
- 404 Not Found `"Not found"`
|
- 404 Not Found `"Not found"`
|
||||||
- On success: JSON, Mastodon Status entity
|
- On success: JSON, Mastodon Status entity
|
||||||
|
|
||||||
## `/api/pleroma/admin/statuses/:id`
|
## `DELETE /api/pleroma/admin/statuses/:id`
|
||||||
|
|
||||||
### Delete an individual reported status
|
### Delete an individual reported status
|
||||||
- Method `DELETE`
|
|
||||||
- Params:
|
- Params:
|
||||||
- `id`
|
- `id`
|
||||||
- Response:
|
- Response:
|
||||||
|
@ -681,11 +715,12 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret
|
||||||
- 404 Not Found `"Not found"`
|
- 404 Not Found `"Not found"`
|
||||||
- On success: 200 OK `{}`
|
- On success: 200 OK `{}`
|
||||||
|
|
||||||
|
## `GET /api/pleroma/admin/config/migrate_to_db`
|
||||||
|
|
||||||
## `/api/pleroma/admin/config/migrate_to_db`
|
|
||||||
### Run mix task pleroma.config migrate_to_db
|
### Run mix task pleroma.config migrate_to_db
|
||||||
|
|
||||||
Copy settings on key `:pleroma` to DB.
|
Copy settings on key `:pleroma` to DB.
|
||||||
- Method `GET`
|
|
||||||
- Params: none
|
- Params: none
|
||||||
- Response:
|
- Response:
|
||||||
|
|
||||||
|
@ -693,10 +728,12 @@ Copy settings on key `:pleroma` to DB.
|
||||||
{}
|
{}
|
||||||
```
|
```
|
||||||
|
|
||||||
## `/api/pleroma/admin/config/migrate_from_db`
|
## `GET /api/pleroma/admin/config/migrate_from_db`
|
||||||
|
|
||||||
### Run mix task pleroma.config migrate_from_db
|
### Run mix task pleroma.config migrate_from_db
|
||||||
|
|
||||||
Copy all settings from DB to `config/prod.exported_from_db.secret.exs` with deletion from DB.
|
Copy all settings from DB to `config/prod.exported_from_db.secret.exs` with deletion from DB.
|
||||||
- Method `GET`
|
|
||||||
- Params: none
|
- Params: none
|
||||||
- Response:
|
- Response:
|
||||||
|
|
||||||
|
@ -704,10 +741,12 @@ Copy all settings from DB to `config/prod.exported_from_db.secret.exs` with dele
|
||||||
{}
|
{}
|
||||||
```
|
```
|
||||||
|
|
||||||
## `/api/pleroma/admin/config`
|
## `GET /api/pleroma/admin/config`
|
||||||
|
|
||||||
### List config settings
|
### List config settings
|
||||||
|
|
||||||
List config settings only works with `:pleroma => :instance => :dynamic_configuration` setting to `true`.
|
List config settings only works with `:pleroma => :instance => :dynamic_configuration` setting to `true`.
|
||||||
- Method `GET`
|
|
||||||
- Params: none
|
- Params: none
|
||||||
- Response:
|
- Response:
|
||||||
|
|
||||||
|
@ -723,8 +762,10 @@ List config settings only works with `:pleroma => :instance => :dynamic_configur
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## `/api/pleroma/admin/config`
|
## `POST /api/pleroma/admin/config`
|
||||||
|
|
||||||
### Update config settings
|
### Update config settings
|
||||||
|
|
||||||
Updating config settings only works with `:pleroma => :instance => :dynamic_configuration` setting to `true`.
|
Updating config settings only works with `:pleroma => :instance => :dynamic_configuration` setting to `true`.
|
||||||
Module name can be passed as string, which starts with `Pleroma`, e.g. `"Pleroma.Upload"`.
|
Module name can be passed as string, which starts with `Pleroma`, e.g. `"Pleroma.Upload"`.
|
||||||
Atom keys and values can be passed with `:` in the beginning, e.g. `":upload"`.
|
Atom keys and values can be passed with `:` in the beginning, e.g. `":upload"`.
|
||||||
|
@ -747,7 +788,6 @@ Compile time settings (need instance reboot):
|
||||||
- `Pleroma.Upload` -> `:proxy_remote`
|
- `Pleroma.Upload` -> `:proxy_remote`
|
||||||
- `:instance` -> `:upload_limit`
|
- `:instance` -> `:upload_limit`
|
||||||
|
|
||||||
- Method `POST`
|
|
||||||
- Params:
|
- Params:
|
||||||
- `configs` => [
|
- `configs` => [
|
||||||
- `group` (string)
|
- `group` (string)
|
||||||
|
@ -802,9 +842,10 @@ Compile time settings (need instance reboot):
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## `/api/pleroma/admin/moderation_log`
|
## `GET /api/pleroma/admin/moderation_log`
|
||||||
|
|
||||||
### Get moderation log
|
### Get moderation log
|
||||||
- Method `GET`
|
|
||||||
- Params:
|
- Params:
|
||||||
- *optional* `page`: **integer** page number
|
- *optional* `page`: **integer** page number
|
||||||
- *optional* `page_size`: **integer** number of log entries per page (default is `50`)
|
- *optional* `page_size`: **integer** number of log entries per page (default is `50`)
|
||||||
|
@ -831,8 +872,9 @@ Compile time settings (need instance reboot):
|
||||||
```
|
```
|
||||||
|
|
||||||
## `POST /api/pleroma/admin/reload_emoji`
|
## `POST /api/pleroma/admin/reload_emoji`
|
||||||
|
|
||||||
### Reload the instance's custom emoji
|
### Reload the instance's custom emoji
|
||||||
* Method `POST`
|
|
||||||
* Authentication: required
|
- Authentication: required
|
||||||
* Params: None
|
- Params: None
|
||||||
* Response: JSON, "ok" and 200 status
|
- Response: JSON, "ok" and 200 status
|
||||||
|
|
|
@ -41,6 +41,10 @@ defmodule Pleroma.Activity do
|
||||||
field(:actor, :string)
|
field(:actor, :string)
|
||||||
field(:recipients, {:array, :string}, default: [])
|
field(:recipients, {:array, :string}, default: [])
|
||||||
field(:thread_muted?, :boolean, virtual: true)
|
field(:thread_muted?, :boolean, virtual: true)
|
||||||
|
|
||||||
|
# This is a fake relation,
|
||||||
|
# do not use outside of with_preloaded_user_actor/with_joined_user_actor
|
||||||
|
has_one(:user_actor, User, on_delete: :nothing, foreign_key: :id)
|
||||||
# This is a fake relation, do not use outside of with_preloaded_bookmark/get_bookmark
|
# This is a fake relation, do not use outside of with_preloaded_bookmark/get_bookmark
|
||||||
has_one(:bookmark, Bookmark)
|
has_one(:bookmark, Bookmark)
|
||||||
has_many(:notifications, Notification, on_delete: :delete_all)
|
has_many(:notifications, Notification, on_delete: :delete_all)
|
||||||
|
@ -86,6 +90,19 @@ def with_preloaded_object(query, join_type \\ :inner) do
|
||||||
|> preload([activity, object: object], object: object)
|
|> preload([activity, object: object], object: object)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def with_joined_user_actor(query, join_type \\ :inner) do
|
||||||
|
join(query, join_type, [activity], u in User,
|
||||||
|
on: u.ap_id == activity.actor,
|
||||||
|
as: :user_actor
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def with_preloaded_user_actor(query, join_type \\ :inner) do
|
||||||
|
query
|
||||||
|
|> with_joined_user_actor(join_type)
|
||||||
|
|> preload([activity, user_actor: user_actor], user_actor: user_actor)
|
||||||
|
end
|
||||||
|
|
||||||
def with_preloaded_bookmark(query, %User{} = user) do
|
def with_preloaded_bookmark(query, %User{} = user) do
|
||||||
from([a] in query,
|
from([a] in query,
|
||||||
left_join: b in Bookmark,
|
left_join: b in Bookmark,
|
||||||
|
|
|
@ -11,6 +11,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
|
||||||
alias Pleroma.Repo
|
alias Pleroma.Repo
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web
|
alias Pleroma.Web
|
||||||
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
alias Pleroma.Web.ActivityPub.Visibility
|
alias Pleroma.Web.ActivityPub.Visibility
|
||||||
alias Pleroma.Web.AdminAPI.AccountView
|
alias Pleroma.Web.AdminAPI.AccountView
|
||||||
alias Pleroma.Web.Endpoint
|
alias Pleroma.Web.Endpoint
|
||||||
|
@ -706,8 +707,14 @@ def make_flag_data(%{actor: actor, context: context, content: content} = params,
|
||||||
def make_flag_data(_, _), do: %{}
|
def make_flag_data(_, _), do: %{}
|
||||||
|
|
||||||
defp build_flag_object(%{account: account, statuses: statuses} = _) do
|
defp build_flag_object(%{account: account, statuses: statuses} = _) do
|
||||||
[account.ap_id] ++
|
[account.ap_id] ++ build_flag_object(%{statuses: statuses})
|
||||||
Enum.map(statuses || [], fn act ->
|
end
|
||||||
|
|
||||||
|
defp build_flag_object(%{statuses: statuses}) do
|
||||||
|
Enum.map(statuses || [], &build_flag_object/1)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp build_flag_object(act) when is_map(act) or is_binary(act) do
|
||||||
id =
|
id =
|
||||||
case act do
|
case act do
|
||||||
%Activity{} = act -> act.data["id"]
|
%Activity{} = act -> act.data["id"]
|
||||||
|
@ -725,7 +732,6 @@ defp build_flag_object(%{account: account, statuses: statuses} = _) do
|
||||||
"published" => activity.object.data["published"],
|
"published" => activity.object.data["published"],
|
||||||
"actor" => AccountView.render("show.json", %{user: actor})
|
"actor" => AccountView.render("show.json", %{user: actor})
|
||||||
}
|
}
|
||||||
end)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
defp build_flag_object(_), do: []
|
defp build_flag_object(_), do: []
|
||||||
|
@ -770,6 +776,94 @@ def fetch_ordered_collection(from, pages_left, acc \\ []) do
|
||||||
end
|
end
|
||||||
|
|
||||||
#### Report-related helpers
|
#### Report-related helpers
|
||||||
|
def get_reports(params, page, page_size) do
|
||||||
|
params =
|
||||||
|
params
|
||||||
|
|> Map.put("type", "Flag")
|
||||||
|
|> Map.put("skip_preload", true)
|
||||||
|
|> Map.put("total", true)
|
||||||
|
|> Map.put("limit", page_size)
|
||||||
|
|> Map.put("offset", (page - 1) * page_size)
|
||||||
|
|
||||||
|
ActivityPub.fetch_activities([], params, :offset)
|
||||||
|
end
|
||||||
|
|
||||||
|
@spec get_reports_grouped_by_status(%{required(:activity) => String.t()}) :: %{
|
||||||
|
required(:groups) => [
|
||||||
|
%{
|
||||||
|
required(:date) => String.t(),
|
||||||
|
required(:account) => %{},
|
||||||
|
required(:status) => %{},
|
||||||
|
required(:actors) => [%User{}],
|
||||||
|
required(:reports) => [%Activity{}]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
required(:total) => integer
|
||||||
|
}
|
||||||
|
def get_reports_grouped_by_status(groups) do
|
||||||
|
parsed_groups =
|
||||||
|
groups
|
||||||
|
|> Enum.map(fn entry ->
|
||||||
|
activity =
|
||||||
|
case Jason.decode(entry.activity) do
|
||||||
|
{:ok, activity} -> activity
|
||||||
|
_ -> build_flag_object(entry.activity)
|
||||||
|
end
|
||||||
|
|
||||||
|
parse_report_group(activity)
|
||||||
|
end)
|
||||||
|
|
||||||
|
%{
|
||||||
|
groups: parsed_groups
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def parse_report_group(activity) do
|
||||||
|
reports = get_reports_by_status_id(activity["id"])
|
||||||
|
max_date = Enum.max_by(reports, &NaiveDateTime.from_iso8601!(&1.data["published"]))
|
||||||
|
actors = Enum.map(reports, & &1.user_actor)
|
||||||
|
|
||||||
|
%{
|
||||||
|
date: max_date.data["published"],
|
||||||
|
account: activity["actor"],
|
||||||
|
status: %{
|
||||||
|
id: activity["id"],
|
||||||
|
content: activity["content"],
|
||||||
|
published: activity["published"]
|
||||||
|
},
|
||||||
|
actors: Enum.uniq(actors),
|
||||||
|
reports: reports
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_reports_by_status_id(ap_id) do
|
||||||
|
from(a in Activity,
|
||||||
|
where: fragment("(?)->>'type' = 'Flag'", a.data),
|
||||||
|
where: fragment("(?)->'object' @> ?", a.data, ^[%{id: ap_id}])
|
||||||
|
)
|
||||||
|
|> Activity.with_preloaded_user_actor()
|
||||||
|
|> Repo.all()
|
||||||
|
end
|
||||||
|
|
||||||
|
@spec get_reported_activities() :: [
|
||||||
|
%{
|
||||||
|
required(:activity) => String.t(),
|
||||||
|
required(:date) => String.t()
|
||||||
|
}
|
||||||
|
]
|
||||||
|
def get_reported_activities do
|
||||||
|
from(a in Activity,
|
||||||
|
where: fragment("(?)->>'type' = 'Flag'", a.data),
|
||||||
|
select: %{
|
||||||
|
date: fragment("max(?->>'published') date", a.data),
|
||||||
|
activity:
|
||||||
|
fragment("jsonb_array_elements_text((? #- '{object,0}')->'object') activity", a.data)
|
||||||
|
},
|
||||||
|
group_by: fragment("activity"),
|
||||||
|
order_by: fragment("date DESC")
|
||||||
|
)
|
||||||
|
|> Repo.all()
|
||||||
|
end
|
||||||
|
|
||||||
def update_report_state(%Activity{} = activity, state)
|
def update_report_state(%Activity{} = activity, state)
|
||||||
when state in @strip_status_report_states do
|
when state in @strip_status_report_states do
|
||||||
|
@ -793,6 +887,18 @@ def update_report_state(%Activity{} = activity, state) when state in @supported_
|
||||||
|> Repo.update()
|
|> Repo.update()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def update_report_state(activity_ids, state) when state in @supported_report_states do
|
||||||
|
activities_num = length(activity_ids)
|
||||||
|
|
||||||
|
from(a in Activity, where: a.id in ^activity_ids)
|
||||||
|
|> update(set: [data: fragment("jsonb_set(data, '{state}', ?)", ^state)])
|
||||||
|
|> Repo.update_all([])
|
||||||
|
|> case do
|
||||||
|
{^activities_num, _} -> :ok
|
||||||
|
_ -> {:error, activity_ids}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def update_report_state(_, _), do: {:error, "Unsupported state"}
|
def update_report_state(_, _), do: {:error, "Unsupported state"}
|
||||||
|
|
||||||
def strip_report_status_data(activity) do
|
def strip_report_status_data(activity) do
|
||||||
|
|
|
@ -11,6 +11,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
|
||||||
alias Pleroma.UserInviteToken
|
alias Pleroma.UserInviteToken
|
||||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
alias Pleroma.Web.ActivityPub.Relay
|
alias Pleroma.Web.ActivityPub.Relay
|
||||||
|
alias Pleroma.Web.ActivityPub.Utils
|
||||||
alias Pleroma.Web.AdminAPI.AccountView
|
alias Pleroma.Web.AdminAPI.AccountView
|
||||||
alias Pleroma.Web.AdminAPI.Config
|
alias Pleroma.Web.AdminAPI.Config
|
||||||
alias Pleroma.Web.AdminAPI.ConfigView
|
alias Pleroma.Web.AdminAPI.ConfigView
|
||||||
|
@ -624,19 +625,17 @@ def force_password_reset(%{assigns: %{user: admin}} = conn, %{"nicknames" => nic
|
||||||
def list_reports(conn, params) do
|
def list_reports(conn, params) do
|
||||||
{page, page_size} = page_params(params)
|
{page, page_size} = page_params(params)
|
||||||
|
|
||||||
params =
|
conn
|
||||||
params
|
|> put_view(ReportView)
|
||||||
|> Map.put("type", "Flag")
|
|> render("index.json", %{reports: Utils.get_reports(params, page, page_size)})
|
||||||
|> Map.put("skip_preload", true)
|
end
|
||||||
|> Map.put("total", true)
|
|
||||||
|> Map.put("limit", page_size)
|
|
||||||
|> Map.put("offset", (page - 1) * page_size)
|
|
||||||
|
|
||||||
reports = ActivityPub.fetch_activities([], params, :offset)
|
def list_grouped_reports(conn, _params) do
|
||||||
|
reports = Utils.get_reported_activities()
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> put_view(ReportView)
|
|> put_view(ReportView)
|
||||||
|> render("index.json", %{reports: reports})
|
|> render("index_grouped.json", Utils.get_reports_grouped_by_status(reports))
|
||||||
end
|
end
|
||||||
|
|
||||||
def report_show(conn, %{"id" => id}) do
|
def report_show(conn, %{"id" => id}) do
|
||||||
|
@ -649,17 +648,26 @@ def report_show(conn, %{"id" => id}) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def report_update_state(%{assigns: %{user: admin}} = conn, %{"id" => id, "state" => state}) do
|
def reports_update(%{assigns: %{user: admin}} = conn, %{"reports" => reports}) do
|
||||||
with {:ok, report} <- CommonAPI.update_report_state(id, state) do
|
result =
|
||||||
|
reports
|
||||||
|
|> Enum.map(fn report ->
|
||||||
|
with {:ok, activity} <- CommonAPI.update_report_state(report["id"], report["state"]) do
|
||||||
ModerationLog.insert_log(%{
|
ModerationLog.insert_log(%{
|
||||||
action: "report_update",
|
action: "report_update",
|
||||||
actor: admin,
|
actor: admin,
|
||||||
subject: report
|
subject: activity
|
||||||
})
|
})
|
||||||
|
|
||||||
conn
|
activity
|
||||||
|> put_view(ReportView)
|
else
|
||||||
|> render("show.json", Report.extract_report_info(report))
|
{:error, message} -> %{id: report["id"], error: message}
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
case Enum.any?(result, &Map.has_key?(&1, :error)) do
|
||||||
|
true -> json_response(conn, :bad_request, result)
|
||||||
|
false -> json_response(conn, :no_content, "")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,26 @@ def render("show.json", %{report: report, user: user, account: account, statuses
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def render("index_grouped.json", %{groups: groups}) do
|
||||||
|
reports =
|
||||||
|
Enum.map(groups, fn group ->
|
||||||
|
%{
|
||||||
|
date: group[:date],
|
||||||
|
account: group[:account],
|
||||||
|
status: group[:status],
|
||||||
|
actors: Enum.map(group[:actors], &merge_account_views/1),
|
||||||
|
reports:
|
||||||
|
group[:reports]
|
||||||
|
|> Enum.map(&Report.extract_report_info(&1))
|
||||||
|
|> Enum.map(&render(__MODULE__, "show.json", &1))
|
||||||
|
}
|
||||||
|
end)
|
||||||
|
|
||||||
|
%{
|
||||||
|
reports: reports
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
defp merge_account_views(%User{} = user) do
|
defp merge_account_views(%User{} = user) do
|
||||||
Pleroma.Web.MastodonAPI.AccountView.render("show.json", %{user: user})
|
Pleroma.Web.MastodonAPI.AccountView.render("show.json", %{user: user})
|
||||||
|> Map.merge(Pleroma.Web.AdminAPI.AccountView.render("show.json", %{user: user}))
|
|> Map.merge(Pleroma.Web.AdminAPI.AccountView.render("show.json", %{user: user}))
|
||||||
|
|
|
@ -370,6 +370,13 @@ defp get_reported_account(account_id) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def update_report_state(activity_ids, state) when is_list(activity_ids) do
|
||||||
|
case Utils.update_report_state(activity_ids, state) do
|
||||||
|
:ok -> {:ok, activity_ids}
|
||||||
|
_ -> {:error, dgettext("errors", "Could not update state")}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def update_report_state(activity_id, state) do
|
def update_report_state(activity_id, state) do
|
||||||
with %Activity{} = activity <- Activity.get_by_id(activity_id) do
|
with %Activity{} = activity <- Activity.get_by_id(activity_id) do
|
||||||
Utils.update_report_state(activity, state)
|
Utils.update_report_state(activity, state)
|
||||||
|
|
|
@ -178,8 +178,9 @@ defmodule Pleroma.Web.Router do
|
||||||
get("/users/:nickname/statuses", AdminAPIController, :list_user_statuses)
|
get("/users/:nickname/statuses", AdminAPIController, :list_user_statuses)
|
||||||
|
|
||||||
get("/reports", AdminAPIController, :list_reports)
|
get("/reports", AdminAPIController, :list_reports)
|
||||||
|
get("/grouped_reports", AdminAPIController, :list_grouped_reports)
|
||||||
get("/reports/:id", AdminAPIController, :report_show)
|
get("/reports/:id", AdminAPIController, :report_show)
|
||||||
put("/reports/:id", AdminAPIController, :report_update_state)
|
patch("/reports", AdminAPIController, :reports_update)
|
||||||
post("/reports/:id/respond", AdminAPIController, :report_respond)
|
post("/reports/:id/respond", AdminAPIController, :report_respond)
|
||||||
|
|
||||||
put("/statuses/:id", AdminAPIController, :status_update)
|
put("/statuses/:id", AdminAPIController, :status_update)
|
||||||
|
|
|
@ -636,4 +636,47 @@ test "removes actor from announcements" do
|
||||||
assert updated_object.data["announcement_count"] == 1
|
assert updated_object.data["announcement_count"] == 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "get_reports_grouped_by_status/1" do
|
||||||
|
setup do
|
||||||
|
[reporter, target_user] = insert_pair(:user)
|
||||||
|
first_status = insert(:note_activity, user: target_user)
|
||||||
|
second_status = insert(:note_activity, user: target_user)
|
||||||
|
|
||||||
|
CommonAPI.report(reporter, %{
|
||||||
|
"account_id" => target_user.id,
|
||||||
|
"comment" => "I feel offended",
|
||||||
|
"status_ids" => [first_status.id]
|
||||||
|
})
|
||||||
|
|
||||||
|
CommonAPI.report(reporter, %{
|
||||||
|
"account_id" => target_user.id,
|
||||||
|
"comment" => "I feel offended2",
|
||||||
|
"status_ids" => [second_status.id]
|
||||||
|
})
|
||||||
|
|
||||||
|
data = [%{activity: first_status.data["id"]}, %{activity: second_status.data["id"]}]
|
||||||
|
|
||||||
|
{:ok,
|
||||||
|
%{
|
||||||
|
first_status: first_status,
|
||||||
|
second_status: second_status,
|
||||||
|
data: data
|
||||||
|
}}
|
||||||
|
end
|
||||||
|
|
||||||
|
test "works for deprecated reports format", %{
|
||||||
|
first_status: first_status,
|
||||||
|
second_status: second_status,
|
||||||
|
data: data
|
||||||
|
} do
|
||||||
|
groups = Utils.get_reports_grouped_by_status(data).groups
|
||||||
|
|
||||||
|
first_group = Enum.find(groups, &(&1.status.id == first_status.data["id"]))
|
||||||
|
second_group = Enum.find(groups, &(&1.status.id == second_status.data["id"]))
|
||||||
|
|
||||||
|
assert first_group.status.id == first_status.data["id"]
|
||||||
|
assert second_group.status.id == second_status.data["id"]
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1312,7 +1312,7 @@ test "returns 404 when report id is invalid", %{conn: conn} do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "PUT /api/pleroma/admin/reports/:id" do
|
describe "PATCH /api/pleroma/admin/reports" do
|
||||||
setup %{conn: conn} do
|
setup %{conn: conn} do
|
||||||
admin = insert(:user, is_admin: true)
|
admin = insert(:user, is_admin: true)
|
||||||
[reporter, target_user] = insert_pair(:user)
|
[reporter, target_user] = insert_pair(:user)
|
||||||
|
@ -1325,16 +1325,32 @@ test "returns 404 when report id is invalid", %{conn: conn} do
|
||||||
"status_ids" => [activity.id]
|
"status_ids" => [activity.id]
|
||||||
})
|
})
|
||||||
|
|
||||||
%{conn: assign(conn, :user, admin), id: report_id, admin: admin}
|
{:ok, %{id: second_report_id}} =
|
||||||
|
CommonAPI.report(reporter, %{
|
||||||
|
"account_id" => target_user.id,
|
||||||
|
"comment" => "I feel very offended",
|
||||||
|
"status_ids" => [activity.id]
|
||||||
|
})
|
||||||
|
|
||||||
|
%{
|
||||||
|
conn: assign(conn, :user, admin),
|
||||||
|
id: report_id,
|
||||||
|
admin: admin,
|
||||||
|
second_report_id: second_report_id
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
test "mark report as resolved", %{conn: conn, id: id, admin: admin} do
|
test "mark report as resolved", %{conn: conn, id: id, admin: admin} do
|
||||||
response =
|
|
||||||
conn
|
conn
|
||||||
|> put("/api/pleroma/admin/reports/#{id}", %{"state" => "resolved"})
|
|> patch("/api/pleroma/admin/reports", %{
|
||||||
|> json_response(:ok)
|
"reports" => [
|
||||||
|
%{"state" => "resolved", "id" => id}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|> json_response(:no_content)
|
||||||
|
|
||||||
assert response["state"] == "resolved"
|
activity = Activity.get_by_id(id)
|
||||||
|
assert activity.data["state"] == "resolved"
|
||||||
|
|
||||||
log_entry = Repo.one(ModerationLog)
|
log_entry = Repo.one(ModerationLog)
|
||||||
|
|
||||||
|
@ -1343,12 +1359,16 @@ test "mark report as resolved", %{conn: conn, id: id, admin: admin} do
|
||||||
end
|
end
|
||||||
|
|
||||||
test "closes report", %{conn: conn, id: id, admin: admin} do
|
test "closes report", %{conn: conn, id: id, admin: admin} do
|
||||||
response =
|
|
||||||
conn
|
conn
|
||||||
|> put("/api/pleroma/admin/reports/#{id}", %{"state" => "closed"})
|
|> patch("/api/pleroma/admin/reports", %{
|
||||||
|> json_response(:ok)
|
"reports" => [
|
||||||
|
%{"state" => "closed", "id" => id}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|> json_response(:no_content)
|
||||||
|
|
||||||
assert response["state"] == "closed"
|
activity = Activity.get_by_id(id)
|
||||||
|
assert activity.data["state"] == "closed"
|
||||||
|
|
||||||
log_entry = Repo.one(ModerationLog)
|
log_entry = Repo.one(ModerationLog)
|
||||||
|
|
||||||
|
@ -1359,17 +1379,54 @@ test "closes report", %{conn: conn, id: id, admin: admin} do
|
||||||
test "returns 400 when state is unknown", %{conn: conn, id: id} do
|
test "returns 400 when state is unknown", %{conn: conn, id: id} do
|
||||||
conn =
|
conn =
|
||||||
conn
|
conn
|
||||||
|> put("/api/pleroma/admin/reports/#{id}", %{"state" => "test"})
|
|> patch("/api/pleroma/admin/reports", %{
|
||||||
|
"reports" => [
|
||||||
|
%{"state" => "test", "id" => id}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
assert json_response(conn, :bad_request) == "Unsupported state"
|
assert hd(json_response(conn, :bad_request))["error"] == "Unsupported state"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "returns 404 when report is not exist", %{conn: conn} do
|
test "returns 404 when report is not exist", %{conn: conn} do
|
||||||
conn =
|
conn =
|
||||||
conn
|
conn
|
||||||
|> put("/api/pleroma/admin/reports/test", %{"state" => "closed"})
|
|> patch("/api/pleroma/admin/reports", %{
|
||||||
|
"reports" => [
|
||||||
|
%{"state" => "closed", "id" => "test"}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
assert json_response(conn, :not_found) == "Not found"
|
assert hd(json_response(conn, :bad_request))["error"] == "not_found"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "updates state of multiple reports", %{
|
||||||
|
conn: conn,
|
||||||
|
id: id,
|
||||||
|
admin: admin,
|
||||||
|
second_report_id: second_report_id
|
||||||
|
} do
|
||||||
|
conn
|
||||||
|
|> patch("/api/pleroma/admin/reports", %{
|
||||||
|
"reports" => [
|
||||||
|
%{"state" => "resolved", "id" => id},
|
||||||
|
%{"state" => "closed", "id" => second_report_id}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|> json_response(:no_content)
|
||||||
|
|
||||||
|
activity = Activity.get_by_id(id)
|
||||||
|
second_activity = Activity.get_by_id(second_report_id)
|
||||||
|
assert activity.data["state"] == "resolved"
|
||||||
|
assert second_activity.data["state"] == "closed"
|
||||||
|
|
||||||
|
[first_log_entry, second_log_entry] = Repo.all(ModerationLog)
|
||||||
|
|
||||||
|
assert ModerationLog.get_log_entry_message(first_log_entry) ==
|
||||||
|
"@#{admin.nickname} updated report ##{id} with 'resolved' state"
|
||||||
|
|
||||||
|
assert ModerationLog.get_log_entry_message(second_log_entry) ==
|
||||||
|
"@#{admin.nickname} updated report ##{second_report_id} with 'closed' state"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1492,7 +1549,145 @@ test "returns 403 when requested by anonymous" do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
#
|
describe "GET /api/pleroma/admin/grouped_reports" do
|
||||||
|
setup %{conn: conn} do
|
||||||
|
admin = insert(:user, is_admin: true)
|
||||||
|
[reporter, target_user] = insert_pair(:user)
|
||||||
|
|
||||||
|
date1 = (DateTime.to_unix(DateTime.utc_now()) + 1000) |> DateTime.from_unix!()
|
||||||
|
date2 = (DateTime.to_unix(DateTime.utc_now()) + 2000) |> DateTime.from_unix!()
|
||||||
|
date3 = (DateTime.to_unix(DateTime.utc_now()) + 3000) |> DateTime.from_unix!()
|
||||||
|
|
||||||
|
first_status =
|
||||||
|
insert(:note_activity, user: target_user, data_attrs: %{"published" => date1})
|
||||||
|
|
||||||
|
second_status =
|
||||||
|
insert(:note_activity, user: target_user, data_attrs: %{"published" => date2})
|
||||||
|
|
||||||
|
third_status =
|
||||||
|
insert(:note_activity, user: target_user, data_attrs: %{"published" => date3})
|
||||||
|
|
||||||
|
{:ok, first_report} =
|
||||||
|
CommonAPI.report(reporter, %{
|
||||||
|
"account_id" => target_user.id,
|
||||||
|
"status_ids" => [first_status.id, second_status.id, third_status.id]
|
||||||
|
})
|
||||||
|
|
||||||
|
{:ok, second_report} =
|
||||||
|
CommonAPI.report(reporter, %{
|
||||||
|
"account_id" => target_user.id,
|
||||||
|
"status_ids" => [first_status.id, second_status.id]
|
||||||
|
})
|
||||||
|
|
||||||
|
{:ok, third_report} =
|
||||||
|
CommonAPI.report(reporter, %{
|
||||||
|
"account_id" => target_user.id,
|
||||||
|
"status_ids" => [first_status.id]
|
||||||
|
})
|
||||||
|
|
||||||
|
%{
|
||||||
|
conn: assign(conn, :user, admin),
|
||||||
|
first_status: Activity.get_by_ap_id_with_object(first_status.data["id"]),
|
||||||
|
second_status: Activity.get_by_ap_id_with_object(second_status.data["id"]),
|
||||||
|
third_status: Activity.get_by_ap_id_with_object(third_status.data["id"]),
|
||||||
|
first_status_reports: [first_report, second_report, third_report],
|
||||||
|
second_status_reports: [first_report, second_report],
|
||||||
|
third_status_reports: [first_report],
|
||||||
|
target_user: target_user,
|
||||||
|
reporter: reporter
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
test "returns reports grouped by status", %{
|
||||||
|
conn: conn,
|
||||||
|
first_status: first_status,
|
||||||
|
second_status: second_status,
|
||||||
|
third_status: third_status,
|
||||||
|
first_status_reports: first_status_reports,
|
||||||
|
second_status_reports: second_status_reports,
|
||||||
|
third_status_reports: third_status_reports,
|
||||||
|
target_user: target_user,
|
||||||
|
reporter: reporter
|
||||||
|
} do
|
||||||
|
response =
|
||||||
|
conn
|
||||||
|
|> get("/api/pleroma/admin/grouped_reports")
|
||||||
|
|> json_response(:ok)
|
||||||
|
|
||||||
|
assert length(response["reports"]) == 3
|
||||||
|
|
||||||
|
first_group =
|
||||||
|
Enum.find(response["reports"], &(&1["status"]["id"] == first_status.data["id"]))
|
||||||
|
|
||||||
|
second_group =
|
||||||
|
Enum.find(response["reports"], &(&1["status"]["id"] == second_status.data["id"]))
|
||||||
|
|
||||||
|
third_group =
|
||||||
|
Enum.find(response["reports"], &(&1["status"]["id"] == third_status.data["id"]))
|
||||||
|
|
||||||
|
assert length(first_group["reports"]) == 3
|
||||||
|
assert length(second_group["reports"]) == 2
|
||||||
|
assert length(third_group["reports"]) == 1
|
||||||
|
|
||||||
|
assert first_group["date"] ==
|
||||||
|
Enum.max_by(first_status_reports, fn act ->
|
||||||
|
NaiveDateTime.from_iso8601!(act.data["published"])
|
||||||
|
end).data["published"]
|
||||||
|
|
||||||
|
assert first_group["status"] == %{
|
||||||
|
"id" => first_status.data["id"],
|
||||||
|
"content" => first_status.object.data["content"],
|
||||||
|
"published" => first_status.object.data["published"]
|
||||||
|
}
|
||||||
|
|
||||||
|
assert first_group["account"]["id"] == target_user.id
|
||||||
|
|
||||||
|
assert length(first_group["actors"]) == 1
|
||||||
|
assert hd(first_group["actors"])["id"] == reporter.id
|
||||||
|
|
||||||
|
assert Enum.map(first_group["reports"], & &1["id"]) --
|
||||||
|
Enum.map(first_status_reports, & &1.id) == []
|
||||||
|
|
||||||
|
assert second_group["date"] ==
|
||||||
|
Enum.max_by(second_status_reports, fn act ->
|
||||||
|
NaiveDateTime.from_iso8601!(act.data["published"])
|
||||||
|
end).data["published"]
|
||||||
|
|
||||||
|
assert second_group["status"] == %{
|
||||||
|
"id" => second_status.data["id"],
|
||||||
|
"content" => second_status.object.data["content"],
|
||||||
|
"published" => second_status.object.data["published"]
|
||||||
|
}
|
||||||
|
|
||||||
|
assert second_group["account"]["id"] == target_user.id
|
||||||
|
|
||||||
|
assert length(second_group["actors"]) == 1
|
||||||
|
assert hd(second_group["actors"])["id"] == reporter.id
|
||||||
|
|
||||||
|
assert Enum.map(second_group["reports"], & &1["id"]) --
|
||||||
|
Enum.map(second_status_reports, & &1.id) == []
|
||||||
|
|
||||||
|
assert third_group["date"] ==
|
||||||
|
Enum.max_by(third_status_reports, fn act ->
|
||||||
|
NaiveDateTime.from_iso8601!(act.data["published"])
|
||||||
|
end).data["published"]
|
||||||
|
|
||||||
|
assert third_group["status"] == %{
|
||||||
|
"id" => third_status.data["id"],
|
||||||
|
"content" => third_status.object.data["content"],
|
||||||
|
"published" => third_status.object.data["published"]
|
||||||
|
}
|
||||||
|
|
||||||
|
assert third_group["account"]["id"] == target_user.id
|
||||||
|
|
||||||
|
assert length(third_group["actors"]) == 1
|
||||||
|
assert hd(third_group["actors"])["id"] == reporter.id
|
||||||
|
|
||||||
|
assert Enum.map(third_group["reports"], & &1["id"]) --
|
||||||
|
Enum.map(third_status_reports, & &1.id) == []
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe "POST /api/pleroma/admin/reports/:id/respond" do
|
describe "POST /api/pleroma/admin/reports/:id/respond" do
|
||||||
setup %{conn: conn} do
|
setup %{conn: conn} do
|
||||||
admin = insert(:user, is_admin: true)
|
admin = insert(:user, is_admin: true)
|
||||||
|
|
|
@ -468,6 +468,35 @@ test "does not update report state when state is unsupported" do
|
||||||
|
|
||||||
assert CommonAPI.update_report_state(report_id, "test") == {:error, "Unsupported state"}
|
assert CommonAPI.update_report_state(report_id, "test") == {:error, "Unsupported state"}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "updates state of multiple reports" do
|
||||||
|
[reporter, target_user] = insert_pair(:user)
|
||||||
|
activity = insert(:note_activity, user: target_user)
|
||||||
|
|
||||||
|
{:ok, %Activity{id: first_report_id}} =
|
||||||
|
CommonAPI.report(reporter, %{
|
||||||
|
"account_id" => target_user.id,
|
||||||
|
"comment" => "I feel offended",
|
||||||
|
"status_ids" => [activity.id]
|
||||||
|
})
|
||||||
|
|
||||||
|
{:ok, %Activity{id: second_report_id}} =
|
||||||
|
CommonAPI.report(reporter, %{
|
||||||
|
"account_id" => target_user.id,
|
||||||
|
"comment" => "I feel very offended!",
|
||||||
|
"status_ids" => [activity.id]
|
||||||
|
})
|
||||||
|
|
||||||
|
{:ok, report_ids} =
|
||||||
|
CommonAPI.update_report_state([first_report_id, second_report_id], "resolved")
|
||||||
|
|
||||||
|
first_report = Activity.get_by_id(first_report_id)
|
||||||
|
second_report = Activity.get_by_id(second_report_id)
|
||||||
|
|
||||||
|
assert report_ids -- [first_report_id, second_report_id] == []
|
||||||
|
assert first_report.data["state"] == "resolved"
|
||||||
|
assert second_report.data["state"] == "resolved"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "reblog muting" do
|
describe "reblog muting" do
|
||||||
|
|
Loading…
Reference in a new issue