Browse Source

Add sitemod feature.

pull/269/head
Stalinist Apologist 2 years ago
parent
commit
fc65016ad9
  1. 12
      README.md
  2. 388
      docs/src/contributing_websocket_http_api.md
  3. 1
      server/lemmy_db/src/activity.rs
  4. 1
      server/lemmy_db/src/comment.rs
  5. 1
      server/lemmy_db/src/comment_view.rs
  6. 1
      server/lemmy_db/src/community.rs
  7. 2
      server/lemmy_db/src/moderator.rs
  8. 1
      server/lemmy_db/src/password_reset_request.rs
  9. 1
      server/lemmy_db/src/post.rs
  10. 1
      server/lemmy_db/src/post_view.rs
  11. 2
      server/lemmy_db/src/private_message.rs
  12. 2
      server/lemmy_db/src/schema.rs
  13. 13
      server/lemmy_db/src/user.rs
  14. 2
      server/lemmy_db/src/user_mention.rs
  15. 35
      server/lemmy_db/src/user_view.rs
  16. 45
      server/migrations/2020-08-02-052800_add_sitemod_column/down.sql
  17. 46
      server/migrations/2020-08-02-052800_add_sitemod_column/up.sql
  18. 18
      server/src/api/comment.rs
  19. 6
      server/src/api/community.rs
  20. 8
      server/src/api/post.rs
  21. 6
      server/src/api/site.rs
  22. 85
      server/src/api/user.rs
  23. 1
      server/src/apub/user.rs
  24. 1
      server/src/code_migrations.rs
  25. 6
      server/src/routes/api.rs
  26. 1
      server/src/routes/index.rs
  27. 1
      server/src/websocket/mod.rs
  28. 1
      server/src/websocket/server.rs

12
README.md

@ -7,3 +7,15 @@
The goal is to contribute to the upstream [Lemmy](https://github.com/LemmyNet/lemmy) project while also trying to retain the r/CTH flavor that brought the community together in the first place.
Please make sure to visit the original readme for all of the information.
## Running in Docker
The doc
```
cd docker/dev
sudo ./docker_update.sh
sudo docker-compose down
# connect to the docker postgresql
psql -h localhost -p 5432 -U lemmy # password is password
```

388
docs/src/contributing_websocket_http_api.md

@ -4,185 +4,190 @@
<!-- toc -->
- [Data types](#data-types)
- [Basic usage](#basic-usage)
* [WebSocket](#websocket)
+ [Testing with Websocat](#testing-with-websocat)
+ [Testing with the WebSocket JavaScript API](#testing-with-the-websocket-javascript-api)
* [HTTP](#http)
+ [Testing with Curl](#testing-with-curl)
- [Get Example](#get-example)
- [Post Example](#post-example)
- [Rate limits](#rate-limits)
- [Errors](#errors)
- [API documentation](#api-documentation)
* [Sort Types](#sort-types)
* [Websocket vs HTTP](#websocket-vs-http)
* [User / Authentication / Admin actions](#user--authentication--admin-actions)
+ [Login](#login)
- [Request](#request)
- [Response](#response)
- [HTTP](#http-1)
+ [Register](#register)
- [Request](#request-1)
- [Response](#response-1)
- [HTTP](#http-2)
+ [Get User Details](#get-user-details)
- [Request](#request-2)
- [Response](#response-2)
- [HTTP](#http-3)
+ [Save User Settings](#save-user-settings)
- [Request](#request-3)
- [Response](#response-3)
- [HTTP](#http-4)
+ [Get Replies / Inbox](#get-replies--inbox)
- [Request](#request-4)
- [Response](#response-4)
- [HTTP](#http-5)
+ [Get User Mentions](#get-user-mentions)
- [Request](#request-5)
- [Response](#response-5)
- [HTTP](#http-6)
+ [Edit User Mention](#edit-user-mention)
- [Request](#request-6)
- [Response](#response-6)
- [HTTP](#http-7)
+ [Mark All As Read](#mark-all-as-read)
- [Request](#request-7)
- [Response](#response-7)
- [HTTP](#http-8)
+ [Delete Account](#delete-account)
- [Request](#request-8)
- [Response](#response-8)
- [HTTP](#http-9)
+ [Add admin](#add-admin)
- [Request](#request-9)
- [Response](#response-9)
- [HTTP](#http-10)
+ [Ban user](#ban-user)
- [Request](#request-10)
- [Response](#response-10)
- [HTTP](#http-11)
* [Site](#site)
+ [List Categories](#list-categories)
- [Request](#request-11)
- [Response](#response-11)
- [HTTP](#http-12)
+ [Search](#search)
- [Request](#request-12)
- [Response](#response-12)
- [HTTP](#http-13)
+ [Get Modlog](#get-modlog)
- [Request](#request-13)
- [Response](#response-13)
- [HTTP](#http-14)
+ [Create Site](#create-site)
- [Request](#request-14)
- [Response](#response-14)
- [HTTP](#http-15)
+ [Edit Site](#edit-site)
- [Request](#request-15)
- [Response](#response-15)
- [HTTP](#http-16)
+ [Get Site](#get-site)
- [Request](#request-16)
- [Response](#response-16)
- [HTTP](#http-17)
+ [Transfer Site](#transfer-site)
- [Request](#request-17)
- [Response](#response-17)
- [HTTP](#http-18)
+ [Get Site Config](#get-site-config)
- [Request](#request-18)
- [Response](#response-18)
- [HTTP](#http-19)
+ [Save Site Config](#save-site-config)
- [Request](#request-19)
- [Response](#response-19)
- [HTTP](#http-20)
* [Community](#community)
+ [Get Community](#get-community)
- [Request](#request-20)
- [Response](#response-20)
- [HTTP](#http-21)
+ [Create Community](#create-community)
- [Request](#request-21)
- [Response](#response-21)
- [HTTP](#http-22)
+ [List Communities](#list-communities)
- [Request](#request-22)
- [Response](#response-22)
- [HTTP](#http-23)
+ [Ban from Community](#ban-from-community)
- [Request](#request-23)
- [Response](#response-23)
- [HTTP](#http-24)
+ [Add Mod to Community](#add-mod-to-community)
- [Request](#request-24)
- [Response](#response-24)
- [HTTP](#http-25)
+ [Edit Community](#edit-community)
- [Request](#request-25)
- [Response](#response-25)
- [HTTP](#http-26)
+ [Follow Community](#follow-community)
- [Request](#request-26)
- [Response](#response-26)
- [HTTP](#http-27)
+ [Get Followed Communities](#get-followed-communities)
- [Request](#request-27)
- [Response](#response-27)
- [HTTP](#http-28)
+ [Transfer Community](#transfer-community)
- [Request](#request-28)
- [Response](#response-28)
- [HTTP](#http-29)
* [Post](#post)
+ [Create Post](#create-post)
- [Request](#request-29)
- [Response](#response-29)
- [HTTP](#http-30)
+ [Get Post](#get-post)
- [Request](#request-30)
- [Response](#response-30)
- [HTTP](#http-31)
+ [Get Posts](#get-posts)
- [Request](#request-31)
- [Response](#response-31)
- [HTTP](#http-32)
+ [Create Post Like](#create-post-like)
- [Request](#request-32)
- [Response](#response-32)
- [HTTP](#http-33)
+ [Edit Post](#edit-post)
- [Request](#request-33)
- [Response](#response-33)
- [HTTP](#http-34)
+ [Save Post](#save-post)
- [Request](#request-34)
- [Response](#response-34)
- [HTTP](#http-35)
* [Comment](#comment)
+ [Create Comment](#create-comment)
- [Request](#request-35)
- [Response](#response-35)
- [HTTP](#http-36)
+ [Edit Comment](#edit-comment)
- [Request](#request-36)
- [Response](#response-36)
- [HTTP](#http-37)
+ [Save Comment](#save-comment)
- [Request](#request-37)
- [Response](#response-37)
- [HTTP](#http-38)
+ [Create Comment Like](#create-comment-like)
- [Request](#request-38)
- [Response](#response-38)
- [HTTP](#http-39)
* [RSS / Atom feeds](#rss--atom-feeds)
+ [All](#all)
+ [Community](#community-1)
+ [User](#user)
- [Lemmy API](#lemmy-api)
- [Data types](#data-types)
- [Basic usage](#basic-usage)
- [WebSocket](#websocket)
- [Testing with Websocat](#testing-with-websocat)
- [Testing with the WebSocket JavaScript API](#testing-with-the-websocket-javascript-api)
- [HTTP](#http)
- [Testing with Curl](#testing-with-curl)
- [Get Example](#get-example)
- [Post Example](#post-example)
- [Rate limits](#rate-limits)
- [Errors](#errors)
- [API documentation](#api-documentation)
- [Sort Types](#sort-types)
- [Websocket vs HTTP](#websocket-vs-http)
- [User / Authentication / Admin actions](#user--authentication--admin-actions)
- [Login](#login)
- [Request](#request)
- [Response](#response)
- [HTTP](#http-1)
- [Register](#register)
- [Request](#request-1)
- [Response](#response-1)
- [HTTP](#http-2)
- [Get User Details](#get-user-details)
- [Request](#request-2)
- [Response](#response-2)
- [HTTP](#http-3)
- [Save User Settings](#save-user-settings)
- [Request](#request-3)
- [Response](#response-3)
- [HTTP](#http-4)
- [Get Replies / Inbox](#get-replies--inbox)
- [Request](#request-4)
- [Response](#response-4)
- [HTTP](#http-5)
- [Get User Mentions](#get-user-mentions)
- [Request](#request-5)
- [Response](#response-5)
- [HTTP](#http-6)
- [Edit User Mention](#edit-user-mention)
- [Request](#request-6)
- [Response](#response-6)
- [HTTP](#http-7)
- [Mark All As Read](#mark-all-as-read)
- [Request](#request-7)
- [Response](#response-7)
- [HTTP](#http-8)
- [Delete Account](#delete-account)
- [Request](#request-8)
- [Response](#response-8)
- [HTTP](#http-9)
- [Add admin](#add-admin)
- [Request](#request-9)
- [Response](#response-9)
- [HTTP](#http-10)
- [Add sitemod](#add-sitemod)
- [Request](#request-10)
- [Response](#response-10)
- [HTTP](#http-11)
- [Ban user](#ban-user)
- [Request](#request-11)
- [Response](#response-11)
- [HTTP](#http-12)
- [Site](#site)
- [List Categories](#list-categories)
- [Request](#request-12)
- [Response](#response-12)
- [HTTP](#http-13)
- [Search](#search)
- [Request](#request-13)
- [Response](#response-13)
- [HTTP](#http-14)
- [Get Modlog](#get-modlog)
- [Request](#request-14)
- [Response](#response-14)
- [HTTP](#http-15)
- [Create Site](#create-site)
- [Request](#request-15)
- [Response](#response-15)
- [HTTP](#http-16)
- [Edit Site](#edit-site)
- [Request](#request-16)
- [Response](#response-16)
- [HTTP](#http-17)
- [Get Site](#get-site)
- [Request](#request-17)
- [Response](#response-17)
- [HTTP](#http-18)
- [Transfer Site](#transfer-site)
- [Request](#request-18)
- [Response](#response-18)
- [HTTP](#http-19)
- [Get Site Config](#get-site-config)
- [Request](#request-19)
- [Response](#response-19)
- [HTTP](#http-20)
- [Save Site Config](#save-site-config)
- [Request](#request-20)
- [Response](#response-20)
- [HTTP](#http-21)
- [Community](#community)
- [Get Community](#get-community)
- [Request](#request-21)
- [Response](#response-21)
- [HTTP](#http-22)
- [Create Community](#create-community)
- [Request](#request-22)
- [Response](#response-22)
- [HTTP](#http-23)
- [List Communities](#list-communities)
- [Request](#request-23)
- [Response](#response-23)
- [HTTP](#http-24)
- [Ban from Community](#ban-from-community)
- [Request](#request-24)
- [Response](#response-24)
- [HTTP](#http-25)
- [Add Mod to Community](#add-mod-to-community)
- [Request](#request-25)
- [Response](#response-25)
- [HTTP](#http-26)
- [Edit Community](#edit-community)
- [Request](#request-26)
- [Response](#response-26)
- [HTTP](#http-27)
- [Follow Community](#follow-community)
- [Request](#request-27)
- [Response](#response-27)
- [HTTP](#http-28)
- [Get Followed Communities](#get-followed-communities)
- [Request](#request-28)
- [Response](#response-28)
- [HTTP](#http-29)
- [Transfer Community](#transfer-community)
- [Request](#request-29)
- [Response](#response-29)
- [HTTP](#http-30)
- [Post](#post)
- [Create Post](#create-post)
- [Request](#request-30)
- [Response](#response-30)
- [HTTP](#http-31)
- [Get Post](#get-post)
- [Request](#request-31)
- [Response](#response-31)
- [HTTP](#http-32)
- [Get Posts](#get-posts)
- [Request](#request-32)
- [Response](#response-32)
- [HTTP](#http-33)
- [Create Post Like](#create-post-like)
- [Request](#request-33)
- [Response](#response-33)
- [HTTP](#http-34)
- [Edit Post](#edit-post)
- [Request](#request-34)
- [Response](#response-34)
- [HTTP](#http-35)
- [Save Post](#save-post)
- [Request](#request-35)
- [Response](#response-35)
- [HTTP](#http-36)
- [Comment](#comment)
- [Create Comment](#create-comment)
- [Request](#request-36)
- [Response](#response-36)
- [HTTP](#http-37)
- [Edit Comment](#edit-comment)
- [Request](#request-37)
- [Response](#response-37)
- [HTTP](#http-38)
- [Save Comment](#save-comment)
- [Request](#request-38)
- [Response](#response-38)
- [HTTP](#http-39)
- [Create Comment Like](#create-comment-like)
- [Request](#request-39)
- [Response](#response-39)
- [HTTP](#http-40)
- [RSS / Atom feeds](#rss--atom-feeds)
- [All](#all)
- [Community](#community-1)
- [User](#user)
<!-- tocstop -->
@ -569,6 +574,31 @@ Marks all user replies and mentions as read.
`POST /admin/add`
#### Add sitemod
##### Request
```rust
{
op: "AddSitemod",
data: {
user_id: i32,
added: bool,
auth: String
}
}
```
##### Response
```rust
{
op: "AddSitemod",
data: {
sitemods: Vec<UserView>,
}
}
```
##### HTTP
`POST /sitemod/add`
#### Ban user
##### Request
```rust

1
server/lemmy_db/src/activity.rs

@ -108,6 +108,7 @@ mod tests {
matrix_user_id: None,
avatar: None,
admin: false,
sitemod: false,
banned: false,
updated: None,
show_nsfw: false,

1
server/lemmy_db/src/comment.rs

@ -266,6 +266,7 @@ mod tests {
matrix_user_id: None,
avatar: None,
admin: false,
sitemod: false,
banned: false,
updated: None,
show_nsfw: false,

1
server/lemmy_db/src/comment_view.rs

@ -489,6 +489,7 @@ mod tests {
matrix_user_id: None,
avatar: None,
admin: false,
sitemod: false,
banned: false,
updated: None,
show_nsfw: false,

1
server/lemmy_db/src/community.rs

@ -254,6 +254,7 @@ mod tests {
matrix_user_id: None,
avatar: None,
admin: false,
sitemod: false,
banned: false,
updated: None,
show_nsfw: false,

2
server/lemmy_db/src/moderator.rs

@ -461,6 +461,7 @@ mod tests {
matrix_user_id: None,
avatar: None,
admin: false,
sitemod: false,
banned: false,
updated: None,
show_nsfw: false,
@ -488,6 +489,7 @@ mod tests {
matrix_user_id: None,
avatar: None,
admin: false,
sitemod: false,
banned: false,
updated: None,
show_nsfw: false,

1
server/lemmy_db/src/password_reset_request.rs

@ -96,6 +96,7 @@ mod tests {
matrix_user_id: None,
avatar: None,
admin: false,
sitemod: false,
banned: false,
updated: None,
show_nsfw: false,

1
server/lemmy_db/src/post.rs

@ -317,6 +317,7 @@ mod tests {
matrix_user_id: None,
avatar: None,
admin: false,
sitemod: false,
banned: false,
updated: None,
show_nsfw: false,

1
server/lemmy_db/src/post_view.rs

@ -407,6 +407,7 @@ mod tests {
avatar: None,
updated: None,
admin: false,
sitemod: false,
banned: false,
show_nsfw: false,
theme: "darkly".into(),

2
server/lemmy_db/src/private_message.rs

@ -104,6 +104,7 @@ mod tests {
matrix_user_id: None,
avatar: None,
admin: false,
sitemod: false,
banned: false,
updated: None,
show_nsfw: false,
@ -131,6 +132,7 @@ mod tests {
matrix_user_id: None,
avatar: None,
admin: false,
sitemod: false,
banned: false,
updated: None,
show_nsfw: false,

2
server/lemmy_db/src/schema.rs

@ -444,6 +444,7 @@ table! {
email -> Nullable<Text>,
avatar -> Nullable<Text>,
admin -> Bool,
sitemod -> Bool,
banned -> Bool,
published -> Timestamp,
updated -> Nullable<Timestamp>,
@ -483,6 +484,7 @@ table! {
bio -> Nullable<Text>,
local -> Nullable<Bool>,
admin -> Nullable<Bool>,
sitemod -> Nullable<Bool>,
banned -> Nullable<Bool>,
show_avatars -> Nullable<Bool>,
send_notifications_to_email -> Nullable<Bool>,

13
server/lemmy_db/src/user.rs

@ -21,6 +21,7 @@ pub struct User_ {
pub email: Option<String>,
pub avatar: Option<String>,
pub admin: bool,
pub sitemod: bool,
pub banned: bool,
pub published: chrono::NaiveDateTime,
pub updated: Option<chrono::NaiveDateTime>,
@ -47,6 +48,7 @@ pub struct UserForm {
pub preferred_username: Option<String>,
pub password_encrypted: String,
pub admin: bool,
pub sitemod: bool,
pub banned: bool,
pub email: Option<String>,
pub avatar: Option<String>,
@ -122,6 +124,12 @@ impl User_ {
.get_result::<Self>(conn)
}
pub fn add_sitemod(conn: &PgConnection, user_id: i32, added: bool) -> Result<Self, Error> {
diesel::update(user_.find(user_id))
.set(sitemod.eq(added))
.get_result::<Self>(conn)
}
pub fn ban_user(conn: &PgConnection, user_id: i32, ban: bool) -> Result<Self, Error> {
diesel::update(user_.find(user_id))
.set(banned.eq(ban))
@ -184,6 +192,7 @@ mod tests {
avatar: None,
admin: false,
banned: false,
sitemod: false,
updated: None,
show_nsfw: false,
theme: "darkly".into(),
@ -211,6 +220,7 @@ mod tests {
matrix_user_id: None,
avatar: None,
admin: false,
sitemod: false,
banned: false,
published: inserted_user.published,
updated: None,
@ -252,6 +262,7 @@ mod tests {
matrix_user_id: None,
avatar: None,
admin: false,
sitemod: false,
banned: false,
updated: None,
show_nsfw: false,
@ -277,6 +288,7 @@ mod tests {
matrix_user_id: None,
avatar: None,
admin: false,
sitemod: false,
banned: false,
updated: None,
show_nsfw: false,
@ -302,6 +314,7 @@ mod tests {
matrix_user_id: None,
avatar: None,
admin: false,
sitemod: false,
banned: false,
updated: None,
show_nsfw: false,

2
server/lemmy_db/src/user_mention.rs

@ -77,6 +77,7 @@ mod tests {
matrix_user_id: None,
avatar: None,
admin: false,
sitemod: false,
banned: false,
updated: None,
show_nsfw: false,
@ -104,6 +105,7 @@ mod tests {
matrix_user_id: None,
avatar: None,
admin: false,
sitemod: false,
banned: false,
updated: None,
show_nsfw: false,

35
server/lemmy_db/src/user_view.rs

@ -14,6 +14,7 @@ table! {
bio -> Nullable<Text>,
local -> Bool,
admin -> Bool,
sitemod -> Bool,
banned -> Bool,
show_avatars -> Bool,
send_notifications_to_email -> Bool,
@ -36,6 +37,7 @@ table! {
bio -> Nullable<Text>,
local -> Bool,
admin -> Bool,
sitemod -> Bool,
banned -> Bool,
show_avatars -> Bool,
send_notifications_to_email -> Bool,
@ -61,6 +63,7 @@ pub struct UserView {
pub bio: Option<String>,
pub local: bool,
pub admin: bool,
pub sitemod: bool,
pub banned: bool,
pub show_avatars: bool,
pub send_notifications_to_email: bool,
@ -170,6 +173,7 @@ impl UserView {
bio,
local,
admin,
sitemod,
banned,
show_avatars,
send_notifications_to_email,
@ -184,6 +188,36 @@ impl UserView {
.load::<Self>(conn)
}
pub fn sitemods(conn: &PgConnection) -> Result<Vec<Self>, Error> {
use super::user_view::user_fast::dsl::*;
use diesel::sql_types::{Nullable, Text};
user_fast
// The select is necessary here to not get back emails
.select((
id,
actor_id,
name,
avatar,
"".into_sql::<Nullable<Text>>(),
matrix_user_id,
bio,
local,
admin,
sitemod,
banned,
show_avatars,
send_notifications_to_email,
published,
number_of_posts,
post_score,
number_of_comments,
comment_score,
))
.filter(sitemod.eq(true))
.order_by(published)
.load::<Self>(conn)
}
pub fn banned(conn: &PgConnection) -> Result<Vec<Self>, Error> {
use super::user_view::user_fast::dsl::*;
use diesel::sql_types::{Nullable, Text};
@ -198,6 +232,7 @@ impl UserView {
bio,
local,
admin,
sitemod,
banned,
show_avatars,
send_notifications_to_email,

45
server/migrations/2020-08-02-052800_add_sitemod_column/down.sql

@ -0,0 +1,45 @@
alter table user_ drop column sitemod;
-- User
drop view user_view;
create view user_view as
select
u.id,
u.actor_id,
u.name,
u.avatar,
u.email,
u.matrix_user_id,
u.bio,
u.local,
u.admin,
u.banned,
u.show_avatars,
u.send_notifications_to_email,
u.published,
coalesce(pd.posts, 0) as number_of_posts,
coalesce(pd.score, 0) as post_score,
coalesce(cd.comments, 0) as number_of_comments,
coalesce(cd.score, 0) as comment_score
from user_ u
left join (
select
p.creator_id as creator_id,
count(distinct p.id) as posts,
sum(pl.score) as score
from post p
join post_like pl on p.id = pl.post_id
group by p.creator_id
) pd on u.id = pd.creator_id
left join (
select
c.creator_id,
count(distinct c.id) as comments,
sum(cl.score) as score
from comment c
join comment_like cl on c.id = cl.comment_id
group by c.creator_id
) cd on u.id = cd.creator_id;
drop table user_fast;
create table user_fast as select * from user_view;

46
server/migrations/2020-08-02-052800_add_sitemod_column/up.sql

@ -0,0 +1,46 @@
alter table user_ add column sitemod bool not null default false;
-- User
drop view user_view;
create view user_view as
select
u.id,
u.actor_id,
u.name,
u.avatar,
u.email,
u.matrix_user_id,
u.bio,
u.local,
u.admin,
u.sitemod,
u.banned,
u.show_avatars,
u.send_notifications_to_email,
u.published,
coalesce(pd.posts, 0) as number_of_posts,
coalesce(pd.score, 0) as post_score,
coalesce(cd.comments, 0) as number_of_comments,
coalesce(cd.score, 0) as comment_score
from user_ u
left join (
select
p.creator_id as creator_id,
count(distinct p.id) as posts,
sum(pl.score) as score
from post p
join post_like pl on p.id = pl.post_id
group by p.creator_id
) pd on u.id = pd.creator_id
left join (
select
c.creator_id,
count(distinct c.id) as comments,
sum(cl.score) as score
from comment c
join comment_like cl on c.id = cl.comment_id
group by c.creator_id
) cd on u.id = cd.creator_id;
drop table user_fast;
create table user_fast as select * from user_view;

18
server/src/api/comment.rs

@ -176,6 +176,7 @@ impl Perform for Oper<CreateComment> {
let mut moderators: Vec<i32> = vec![];
let mut admins: Vec<i32> = vec![];
let mut sitemods: Vec<i32> = vec![];
admins.append(
&mut blocking(pool, move |conn| {
@ -184,6 +185,13 @@ impl Perform for Oper<CreateComment> {
.await??,
);
sitemods.append(
&mut blocking(pool, move |conn| {
UserView::sitemods(conn).map(|v| v.into_iter().map(|a| a.id).collect())
})
.await??,
);
moderators.append(
&mut blocking(pool, move |conn| {
CommunityModeratorView::for_community(conn, community_id)
@ -192,7 +200,7 @@ impl Perform for Oper<CreateComment> {
.await??,
);
if !(admins.contains(&user_id) | moderators.contains(&user_id)) {
if !(admins.contains(&user_id) || sitemods.contains(&user_id) || moderators.contains(&user_id)) {
return Err(APIError::err("post_is_locked").into());
}
}
@ -325,11 +333,17 @@ impl Perform for Oper<EditComment> {
})
.await??,
);
moderators.append(
&mut blocking(pool, move |conn| {
UserView::sitemods(conn).map(|v| v.into_iter().map(|a| a.id).collect())
})
.await??,
);
editors.extend(&moderators);
// You are allowed to mark the comment as read even if you're banned.
if data.read.is_none() {
// Verify its the creator or a mod, or an admin
// Verify its the creator or a mod, or an admin or sitemod
if !editors.contains(&user_id) {
return Err(APIError::err("no_comment_edit_allowed").into());

6
server/src/api/community.rs

@ -33,6 +33,7 @@ pub struct GetCommunityResponse {
pub community: CommunityView,
pub moderators: Vec<CommunityModeratorView>,
pub admins: Vec<UserView>,
pub sitemods: Vec<UserView>,
pub online: usize,
}
@ -185,6 +186,7 @@ impl Perform for Oper<GetCommunity> {
let site = blocking(pool, move |conn| Site::read(conn, 1)).await??;
let site_creator_id = site.creator_id;
let mut admins = blocking(pool, move |conn| UserView::admins(conn)).await??;
let sitemods = blocking(pool, move |conn| UserView::sitemods(conn)).await??;
let creator_index = admins.iter().position(|r| r.id == site_creator_id).unwrap();
let creator_user = admins.remove(creator_index);
admins.insert(0, creator_user);
@ -218,6 +220,7 @@ impl Perform for Oper<GetCommunity> {
community: community_view,
moderators,
admins,
sitemods,
online,
};
@ -886,6 +889,8 @@ impl Perform for Oper<TransferCommunity> {
let mut admins = blocking(pool, move |conn| UserView::admins(conn)).await??;
let sitemods = blocking(pool, move |conn| UserView::sitemods(conn)).await??;
let creator_index = admins.iter().position(|r| r.id == site_creator_id).unwrap();
let creator_user = admins.remove(creator_index);
admins.insert(0, creator_user);
@ -985,6 +990,7 @@ impl Perform for Oper<TransferCommunity> {
community: community_view,
moderators,
admins,
sitemods,
online: 0,
})
}

8
server/src/api/post.rs

@ -191,8 +191,8 @@ impl Perform for Oper<CreatePost> {
let score = user_view.post_score + user_view.comment_score;
// no upstream, dessalines wants to leverage rate limiting
if score < 0 {
return Err(APIError::err("score_too_low").into());
if score < 0 && !privileged {
return Err(APIError::err(format!("score_too_low, {}", score).as_str()).into());
}
let url = match data.url.to_owned() {
@ -201,8 +201,8 @@ impl Perform for Oper<CreatePost> {
None
} else {
// no upstream, dessalines wants to leverage rate limiting
if score < 5 {
return Err(APIError::err("score_too_low").into());
if score < 5 && !privileged {
return Err(APIError::err(format!("score_too_low, {}", score).as_str()).into());
}
match Url::parse(&url) {
Ok(_t) => Some(url),

6
server/src/api/site.rs

@ -101,6 +101,7 @@ pub struct SiteResponse {
pub struct GetSiteResponse {
site: Option<SiteView>,
admins: Vec<UserView>,
sitemods: Vec<UserView>,
banned: Vec<UserView>,
pub online: usize,
}
@ -413,6 +414,7 @@ impl Perform for Oper<GetSite> {
password: setup.admin_password.to_owned(),
password_verify: setup.admin_password.to_owned(),
admin: true,
sitemod: true,
show_nsfw: true,
captcha_id: "".to_string(),
};
@ -439,6 +441,7 @@ impl Perform for Oper<GetSite> {
};
let mut admins = blocking(pool, move |conn| UserView::admins(conn)).await??;
let sitemods = blocking(pool, move |conn| UserView::sitemods(conn)).await??;
// Make sure the site creator is the top admin
if let Some(site_view) = site_view.to_owned() {
@ -474,6 +477,7 @@ impl Perform for Oper<GetSite> {
Ok(GetSiteResponse {
site: site_view,
admins,
sitemods,
banned,
online,
})
@ -705,6 +709,7 @@ impl Perform for Oper<TransferSite> {
let site_view = blocking(pool, move |conn| SiteView::read(conn)).await??;
let mut admins = blocking(pool, move |conn| UserView::admins(conn)).await??;
let sitemods = blocking(pool, move |conn| UserView::sitemods(conn)).await??;
let creator_index = admins
.iter()
.position(|r| r.id == site_view.creator_id)
@ -717,6 +722,7 @@ impl Perform for Oper<TransferSite> {
Ok(GetSiteResponse {
site: Some(site_view),
admins,
sitemods,
banned,
online: 0,
})

85
server/src/api/user.rs

@ -68,6 +68,7 @@ pub struct Register {
pub password: String,
pub password_verify: String,
pub admin: bool,
pub sitemod: bool,
pub show_nsfw: bool,
pub captcha_id: String,
}
@ -144,6 +145,18 @@ pub struct AddAdminResponse {
admins: Vec<UserView>,
}
#[derive(Serialize, Deserialize)]
pub struct AddSitemod {
user_id: i32,
added: bool,
auth: String,
}
#[derive(Serialize, Deserialize, Clone)]
pub struct AddSitemodResponse {
sitemods: Vec<UserView>,
}
#[derive(Serialize, Deserialize)]
pub struct BanUser {
user_id: i32,
@ -420,6 +433,7 @@ impl Perform for Oper<Register> {
preferred_username: None,
updated: None,
admin: data.admin,
sitemod: data.sitemod,
banned: false,
show_nsfw: data.show_nsfw,
theme: "darkly".into(),
@ -610,6 +624,7 @@ impl Perform for Oper<SaveUserSettings> {
preferred_username: read_user.preferred_username,
updated: Some(naive_now()),
admin: read_user.admin,
sitemod: read_user.sitemod,
banned: read_user.banned,
show_nsfw: data.show_nsfw,
theme: data.theme.to_owned(),
@ -834,15 +849,15 @@ impl Perform for Oper<AddAdmin> {
}
#[async_trait::async_trait(?Send)]
impl Perform for Oper<BanUser> {
type Response = BanUserResponse;
impl Perform for Oper<AddSitemod> {
type Response = AddSitemodResponse;
async fn perform(
&self,
pool: &DbPool,
websocket_info: Option<WebsocketInfo>,
) -> Result<BanUserResponse, LemmyError> {
let data: &BanUser = &self.data;
) -> Result<AddSitemodResponse, LemmyError> {
let data: &AddSitemod = &self.data;
let claims = match Claims::decode(&data.auth) {
Ok(claims) => claims.claims,
@ -857,6 +872,68 @@ impl Perform for Oper<BanUser> {
return Err(APIError::err("not_an_admin").into());
}
let added = data.added;
let added_user_id = data.user_id;
let add_sitemod = move |conn: &'_ _| User_::add_sitemod(conn, added_user_id, added);
if blocking(pool, add_sitemod).await?.is_err() {
return Err(APIError::err("couldnt_update_user").into());
}
// Mod tables
let form = ModAddForm {
mod_user_id: user_id,
other_user_id: data.user_id,
removed: Some(!data.added),
};
blocking(pool, move |conn| ModAdd::create(conn, &form)).await??;
let site_creator_id =
blocking(pool, move |conn| Site::read(conn, 1).map(|s| s.creator_id)).await??;
let mut sitemods = blocking(pool, move |conn| UserView::sitemods(conn)).await??;
let creator_index = sitemods.iter().position(|r| r.id == site_creator_id).unwrap();
let creator_user = sitemods.remove(creator_index);
sitemods.insert(0, creator_user);
let res = AddSitemodResponse { sitemods };
if let Some(ws) = websocket_info {
ws.chatserver.do_send(SendAllMessage {
op: UserOperation::AddSitemod,
response: res.clone(),
my_id: ws.id,
});
}
Ok(res)
}
}
#[async_trait::async_trait(?Send)]
impl Perform for Oper<BanUser> {
type Response = BanUserResponse;
async fn perform(
&self,
pool: &DbPool,
websocket_info: Option<WebsocketInfo>,
) -> Result<BanUserResponse, LemmyError> {
let data: &BanUser = &self.data;
let claims = match Claims::decode(&data.auth) {
Ok(claims) => claims.claims,
Err(_e) => return Err(APIError::err("not_logged_in").into()),
};
let user_id = claims.id;
// Make sure user is an admin or sitemod
let user = blocking(pool, move |conn| User_::read(&conn, user_id)).await??;
if !user.admin || !user.sitemod {
return Err(APIError::err("not_an_admin_or_sitemod").into());
}
let ban = data.ban;
let banned_user_id = data.user_id;
let ban_user = move |conn: &'_ _| User_::ban_user(conn, banned_user_id, ban);

1
server/src/apub/user.rs

@ -221,6 +221,7 @@ impl FromApub for UserForm {
preferred_username: person.inner.preferred_username().map(|u| u.to_string()),
password_encrypted: "".to_string(),
admin: false,
sitemod: false,
banned: false,
email: None,
avatar,

1
server/src/code_migrations.rs

@ -48,6 +48,7 @@ fn user_updates_2020_04_02(conn: &PgConnection) -> Result<(), LemmyError> {
preferred_username: cuser.preferred_username.to_owned(),
updated: None,
admin: cuser.admin,
sitemod: cuser.sitemod,
banned: cuser.banned,
show_nsfw: cuser.show_nsfw,
theme: cuser.theme.to_owned(),

6
server/src/routes/api.rs

@ -200,6 +200,12 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimit) {
web::resource("/admin/add")
.wrap(rate_limit.message())
.route(web::post().to(route_post::<AddAdmin>)),
)
// Sitemod Actions
.service(
web::resource("/sitemod/add")
.wrap(rate_limit.message())
.route(web::post().to(route_post::<AddSitemod>)),
),
);
}

1
server/src/routes/index.rs

@ -34,6 +34,7 @@ pub fn config(cfg: &mut web::ServiceConfig) {
.route("/modlog", web::get().to(index))
.route("/setup", web::get().to(index))
.route("/admin", web::get().to(index))
.route("/sitemod", web::get().to(index))
.route(
"/search/q/{q}/type/{type}/sort/{sort}/page/{page}",
web::get().to(index),

1
server/src/websocket/mod.rs

@ -56,6 +56,7 @@ pub enum UserOperation {
EditSite,
GetSite,
AddAdmin,
AddSitemod,
BanUser,
Search,
MarkAllAsRead,

1
server/src/websocket/server.rs

@ -441,6 +441,7 @@ impl ChatServer {
UserOperation::GetUserDetails => do_user_operation::<GetUserDetails>(args).await,
UserOperation::GetReplies => do_user_operation::<GetReplies>(args).await,
UserOperation::AddAdmin => do_user_operation::<AddAdmin>(args).await,
UserOperation::AddSitemod => do_user_operation::<AddSitemod>(args).await,
UserOperation::BanUser => do_user_operation::<BanUser>(args).await,
UserOperation::GetUserMentions => do_user_operation::<GetUserMentions>(args).await,
UserOperation::EditUserMention => do_user_operation::<EditUserMention>(args).await,

Loading…
Cancel
Save