diff --git a/docs/src/contributing_websocket_http_api.md b/docs/src/contributing_websocket_http_api.md index 00e26b0d3..568bafc32 100644 --- a/docs/src/contributing_websocket_http_api.md +++ b/docs/src/contributing_websocket_http_api.md @@ -17,6 +17,7 @@ - [Errors](#errors) - [API documentation](#api-documentation) * [Sort Types](#sort-types) + * [Undoing actions](#undoing-actions) * [Websocket vs HTTP](#websocket-vs-http) * [User / Authentication / Admin actions](#user--authentication--admin-actions) + [Login](#login) @@ -43,142 +44,198 @@ - [Request](#request-5) - [Response](#response-5) - [HTTP](#http-6) - + [Edit User Mention](#edit-user-mention) + + [Mark User Mention as read](#mark-user-mention-as-read) - [Request](#request-6) - [Response](#response-6) - [HTTP](#http-7) - + [Mark All As Read](#mark-all-as-read) + + [Get Private Messages](#get-private-messages) - [Request](#request-7) - [Response](#response-7) - [HTTP](#http-8) - + [Delete Account](#delete-account) + + [Create Private Message](#create-private-message) - [Request](#request-8) - [Response](#response-8) - [HTTP](#http-9) - + [Add admin](#add-admin) + + [Edit Private Message](#edit-private-message) - [Request](#request-9) - [Response](#response-9) - [HTTP](#http-10) - + [Ban user](#ban-user) + + [Delete Private Message](#delete-private-message) - [Request](#request-10) - [Response](#response-10) - [HTTP](#http-11) - * [Site](#site) - + [List Categories](#list-categories) + + [Mark Private Message as Read](#mark-private-message-as-read) - [Request](#request-11) - [Response](#response-11) - [HTTP](#http-12) - + [Search](#search) + + [Mark All As Read](#mark-all-as-read) - [Request](#request-12) - [Response](#response-12) - [HTTP](#http-13) - + [Get Modlog](#get-modlog) + + [Delete Account](#delete-account) - [Request](#request-13) - [Response](#response-13) - [HTTP](#http-14) - + [Create Site](#create-site) + + [Add admin](#add-admin) - [Request](#request-14) - [Response](#response-14) - [HTTP](#http-15) - + [Edit Site](#edit-site) + + [Ban user](#ban-user) - [Request](#request-15) - [Response](#response-15) - [HTTP](#http-16) - + [Get Site](#get-site) + * [Site](#site) + + [List Categories](#list-categories) - [Request](#request-16) - [Response](#response-16) - [HTTP](#http-17) - + [Transfer Site](#transfer-site) + + [Search](#search) - [Request](#request-17) - [Response](#response-17) - [HTTP](#http-18) - + [Get Site Config](#get-site-config) + + [Get Modlog](#get-modlog) - [Request](#request-18) - [Response](#response-18) - [HTTP](#http-19) - + [Save Site Config](#save-site-config) + + [Create Site](#create-site) - [Request](#request-19) - [Response](#response-19) - [HTTP](#http-20) - * [Community](#community) - + [Get Community](#get-community) + + [Edit Site](#edit-site) - [Request](#request-20) - [Response](#response-20) - [HTTP](#http-21) - + [Create Community](#create-community) + + [Get Site](#get-site) - [Request](#request-21) - [Response](#response-21) - [HTTP](#http-22) - + [List Communities](#list-communities) + + [Transfer Site](#transfer-site) - [Request](#request-22) - [Response](#response-22) - [HTTP](#http-23) - + [Ban from Community](#ban-from-community) + + [Get Site Config](#get-site-config) - [Request](#request-23) - [Response](#response-23) - [HTTP](#http-24) - + [Add Mod to Community](#add-mod-to-community) + + [Save Site Config](#save-site-config) - [Request](#request-24) - [Response](#response-24) - [HTTP](#http-25) - + [Edit Community](#edit-community) + * [Community](#community) + + [Get Community](#get-community) - [Request](#request-25) - [Response](#response-25) - [HTTP](#http-26) - + [Follow Community](#follow-community) + + [Create Community](#create-community) - [Request](#request-26) - [Response](#response-26) - [HTTP](#http-27) - + [Get Followed Communities](#get-followed-communities) + + [List Communities](#list-communities) - [Request](#request-27) - [Response](#response-27) - [HTTP](#http-28) - + [Transfer Community](#transfer-community) + + [Ban from Community](#ban-from-community) - [Request](#request-28) - [Response](#response-28) - [HTTP](#http-29) - * [Post](#post) - + [Create Post](#create-post) + + [Add Mod to Community](#add-mod-to-community) - [Request](#request-29) - [Response](#response-29) - [HTTP](#http-30) - + [Get Post](#get-post) + + [Edit Community](#edit-community) - [Request](#request-30) - [Response](#response-30) - [HTTP](#http-31) - + [Get Posts](#get-posts) + + [Delete Community](#delete-community) - [Request](#request-31) - [Response](#response-31) - [HTTP](#http-32) - + [Create Post Like](#create-post-like) + + [Remove Community](#remove-community) - [Request](#request-32) - [Response](#response-32) - [HTTP](#http-33) - + [Edit Post](#edit-post) + + [Follow Community](#follow-community) - [Request](#request-33) - [Response](#response-33) - [HTTP](#http-34) - + [Save Post](#save-post) + + [Get Followed Communities](#get-followed-communities) - [Request](#request-34) - [Response](#response-34) - [HTTP](#http-35) - * [Comment](#comment) - + [Create Comment](#create-comment) + + [Transfer Community](#transfer-community) - [Request](#request-35) - [Response](#response-35) - [HTTP](#http-36) - + [Edit Comment](#edit-comment) + * [Post](#post) + + [Create Post](#create-post) - [Request](#request-36) - [Response](#response-36) - [HTTP](#http-37) - + [Save Comment](#save-comment) + + [Get Post](#get-post) - [Request](#request-37) - [Response](#response-37) - [HTTP](#http-38) - + [Create Comment Like](#create-comment-like) + + [Get Posts](#get-posts) - [Request](#request-38) - [Response](#response-38) - [HTTP](#http-39) + + [Create Post Like](#create-post-like) + - [Request](#request-39) + - [Response](#response-39) + - [HTTP](#http-40) + + [Edit Post](#edit-post) + - [Request](#request-40) + - [Response](#response-40) + - [HTTP](#http-41) + + [Delete Post](#delete-post) + - [Request](#request-41) + - [Response](#response-41) + - [HTTP](#http-42) + + [Remove Post](#remove-post) + - [Request](#request-42) + - [Response](#response-42) + - [HTTP](#http-43) + + [Lock Post](#lock-post) + - [Request](#request-43) + - [Response](#response-43) + - [HTTP](#http-44) + + [Sticky Post](#sticky-post) + - [Request](#request-44) + - [Response](#response-44) + - [HTTP](#http-45) + + [Save Post](#save-post) + - [Request](#request-45) + - [Response](#response-45) + - [HTTP](#http-46) + * [Comment](#comment) + + [Create Comment](#create-comment) + - [Request](#request-46) + - [Response](#response-46) + - [HTTP](#http-47) + + [Edit Comment](#edit-comment) + - [Request](#request-47) + - [Response](#response-47) + - [HTTP](#http-48) + + [Delete Comment](#delete-comment) + - [Request](#request-48) + - [Response](#response-48) + - [HTTP](#http-49) + + [Remove Comment](#remove-comment) + - [Request](#request-49) + - [Response](#response-49) + - [HTTP](#http-50) + + [Mark Comment as Read](#mark-comment-as-read) + - [Request](#request-50) + - [Response](#response-50) + - [HTTP](#http-51) + + [Save Comment](#save-comment) + - [Request](#request-51) + - [Response](#response-51) + - [HTTP](#http-52) + + [Create Comment Like](#create-comment-like) + - [Request](#request-52) + - [Response](#response-52) + - [HTTP](#http-53) * [RSS / Atom feeds](#rss--atom-feeds) + [All](#all) + [Community](#community-1) @@ -281,6 +338,10 @@ These go wherever there is a `sort` field. The available sort types are: - `TopYear` - the most upvoted posts/communities of the current year. - `TopAll` - the most upvoted posts/communities on the current instance. +### Undoing actions + +Whenever you see a `deleted: bool`, `removed: bool`, `read: bool`, `locked: bool`, etc, you can undo this action by sending `false`. + ### Websocket vs HTTP - Below are the websocket JSON requests / responses. For HTTP, ignore all fields except those inside `data`. @@ -465,6 +526,9 @@ Only the first user will be able to be the admin. `GET /user/mentions` #### Mark User Mention as read + +Only the recipient can do this. + ##### Request ```rust { @@ -595,6 +659,9 @@ Only the first user will be able to be the admin. `POST /private_message/delete` #### Mark Private Message as Read + +Only the recipient can do this. + ##### Request ```rust { @@ -1661,6 +1728,9 @@ Only a mod or admin can remove the comment. `POST /comment/remove` #### Mark Comment as Read + +Only the recipient can do this. + ##### Request ```rust { diff --git a/server/lemmy_db/src/community.rs b/server/lemmy_db/src/community.rs index 03c47e463..3a78d769d 100644 --- a/server/lemmy_db/src/community.rs +++ b/server/lemmy_db/src/community.rs @@ -133,7 +133,7 @@ impl Community { .get_result::(conn) } - pub fn community_mods_and_admins( + fn community_mods_and_admins( conn: &PgConnection, community_id: i32, ) -> Result, Error> { @@ -147,6 +147,12 @@ impl Community { .append(&mut UserView::admins(conn).map(|v| v.into_iter().map(|a| a.id).collect())?); Ok(mods_and_admins) } + + pub fn is_mod_or_admin(conn: &PgConnection, user_id: i32, community_id: i32) -> bool { + Self::community_mods_and_admins(conn, community_id) + .unwrap_or_default() + .contains(&user_id) + } } #[derive(Identifiable, Queryable, Associations, PartialEq, Debug)] diff --git a/server/src/api/comment.rs b/server/src/api/comment.rs index 79b7b2c79..c461f7921 100644 --- a/server/src/api/comment.rs +++ b/server/src/api/comment.rs @@ -474,11 +474,11 @@ impl Perform for Oper { } // Verify that only a mod or admin can remove - let mods_and_admins = blocking(pool, move |conn| { - Community::community_mods_and_admins(conn, community_id) + let is_mod_or_admin = blocking(pool, move |conn| { + Community::is_mod_or_admin(conn, user_id, community_id) }) - .await??; - if !mods_and_admins.contains(&user_id) { + .await?; + if !is_mod_or_admin { return Err(APIError::err("not_an_admin").into()); } diff --git a/server/src/api/community.rs b/server/src/api/community.rs index 5e84bc6c6..f4ba15fb3 100644 --- a/server/src/api/community.rs +++ b/server/src/api/community.rs @@ -802,26 +802,15 @@ impl Perform for Oper { let user_id = claims.id; - let mut community_moderators: Vec = vec![]; - let community_id = data.community_id; - community_moderators.append( - &mut blocking(pool, move |conn| { - CommunityModeratorView::for_community(&conn, community_id) - .map(|v| v.into_iter().map(|m| m.user_id).collect()) - }) - .await??, - ); - community_moderators.append( - &mut blocking(pool, move |conn| { - UserView::admins(conn).map(|v| v.into_iter().map(|a| a.id).collect()) - }) - .await??, - ); - - if !community_moderators.contains(&user_id) { - return Err(APIError::err("couldnt_update_community").into()); + // Verify that only mods or admins can ban + let is_mod_or_admin = blocking(pool, move |conn| { + Community::is_mod_or_admin(conn, user_id, community_id) + }) + .await?; + if !is_mod_or_admin { + return Err(APIError::err("not_an_admin").into()); } let community_user_ban_form = CommunityUserBanForm { @@ -901,26 +890,15 @@ impl Perform for Oper { user_id: data.user_id, }; - let mut community_moderators: Vec = vec![]; - let community_id = data.community_id; - community_moderators.append( - &mut blocking(pool, move |conn| { - CommunityModeratorView::for_community(&conn, community_id) - .map(|v| v.into_iter().map(|m| m.user_id).collect()) - }) - .await??, - ); - community_moderators.append( - &mut blocking(pool, move |conn| { - UserView::admins(conn).map(|v| v.into_iter().map(|a| a.id).collect()) - }) - .await??, - ); - - if !community_moderators.contains(&user_id) { - return Err(APIError::err("couldnt_update_community").into()); + // Verify that only mods or admins can add mod + let is_mod_or_admin = blocking(pool, move |conn| { + Community::is_mod_or_admin(conn, user_id, community_id) + }) + .await?; + if !is_mod_or_admin { + return Err(APIError::err("not_an_admin").into()); } if data.added { diff --git a/server/src/api/post.rs b/server/src/api/post.rs index 390d291cf..15c38a3f6 100644 --- a/server/src/api/post.rs +++ b/server/src/api/post.rs @@ -770,11 +770,11 @@ impl Perform for Oper { } // Verify that only the mods can remove - let mods_and_admins = blocking(pool, move |conn| { - Community::community_mods_and_admins(conn, community_id) + let is_mod_or_admin = blocking(pool, move |conn| { + Community::is_mod_or_admin(conn, user_id, community_id) }) - .await??; - if !mods_and_admins.contains(&user_id) { + .await?; + if !is_mod_or_admin { return Err(APIError::err("not_an_admin").into()); } @@ -861,11 +861,11 @@ impl Perform for Oper { } // Verify that only the mods can lock - let mods_and_admins = blocking(pool, move |conn| { - Community::community_mods_and_admins(conn, community_id) + let is_mod_or_admin = blocking(pool, move |conn| { + Community::is_mod_or_admin(conn, user_id, community_id) }) - .await??; - if !mods_and_admins.contains(&user_id) { + .await?; + if !is_mod_or_admin { return Err(APIError::err("not_an_admin").into()); } @@ -943,11 +943,11 @@ impl Perform for Oper { } // Verify that only the mods can sticky - let mods_and_admins = blocking(pool, move |conn| { - Community::community_mods_and_admins(conn, community_id) + let is_mod_or_admin = blocking(pool, move |conn| { + Community::is_mod_or_admin(conn, user_id, community_id) }) - .await??; - if !mods_and_admins.contains(&user_id) { + .await?; + if !is_mod_or_admin { return Err(APIError::err("not_an_admin").into()); }