Merge pull request 'Add user search form to admin panel' (#1143) from moderation-improvement into main
Reviewed-on: https://git.joinplu.me/Plume/Plume/pulls/1143
This commit is contained in:
		
						commit
						613ccbcd94
					
				| @ -422,6 +422,7 @@ impl CommentTree { | ||||
| mod tests { | ||||
|     use super::*; | ||||
|     use crate::blogs::Blog; | ||||
|     use crate::db_conn::DbConn; | ||||
|     use crate::inbox::{inbox, tests::fill_database, InboxResult}; | ||||
|     use crate::safe_string::SafeString; | ||||
|     use crate::tests::{db, format_datetime}; | ||||
|  | ||||
| @ -232,7 +232,9 @@ impl IntoId for Follow { | ||||
| #[cfg(test)] | ||||
| mod tests { | ||||
|     use super::*; | ||||
|     use crate::{tests::db, users::tests as user_tests, users::tests::fill_database}; | ||||
|     use crate::{ | ||||
|         db_conn::DbConn, tests::db, users::tests as user_tests, users::tests::fill_database, | ||||
|     }; | ||||
|     use assert_json_diff::assert_json_eq; | ||||
|     use diesel::Connection; | ||||
|     use serde_json::{json, to_value}; | ||||
|  | ||||
| @ -1027,6 +1027,7 @@ impl From<PostEvent> for Arc<Post> { | ||||
| #[cfg(test)] | ||||
| mod tests { | ||||
|     use super::*; | ||||
|     use crate::db_conn::DbConn; | ||||
|     use crate::inbox::{inbox, tests::fill_database, InboxResult}; | ||||
|     use crate::mentions::{Mention, NewMention}; | ||||
|     use crate::safe_string::SafeString; | ||||
|  | ||||
| @ -15,7 +15,10 @@ use activitystreams::{ | ||||
|     prelude::*, | ||||
| }; | ||||
| use chrono::{NaiveDateTime, Utc}; | ||||
| use diesel::{self, BelongingToDsl, ExpressionMethods, OptionalExtension, QueryDsl, RunQueryDsl}; | ||||
| use diesel::{ | ||||
|     self, BelongingToDsl, BoolExpressionMethods, ExpressionMethods, OptionalExtension, QueryDsl, | ||||
|     RunQueryDsl, TextExpressionMethods, | ||||
| }; | ||||
| use ldap3::{LdapConn, Scope, SearchEntry}; | ||||
| use openssl::{ | ||||
|     hash::MessageDigest, | ||||
| @ -186,6 +189,7 @@ impl User { | ||||
|     pub fn count_local(conn: &Connection) -> Result<i64> { | ||||
|         users::table | ||||
|             .filter(users::instance_id.eq(Instance::get_local()?.id)) | ||||
|             .filter(users::role.ne(Role::Instance as i32)) | ||||
|             .count() | ||||
|             .get_result(conn) | ||||
|             .map_err(Error::from) | ||||
| @ -203,6 +207,27 @@ impl User { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn search_local_by_name( | ||||
|         conn: &Connection, | ||||
|         name: &str, | ||||
|         (min, max): (i32, i32), | ||||
|     ) -> Result<Vec<User>> { | ||||
|         users::table | ||||
|             .filter(users::instance_id.eq(Instance::get_local()?.id)) | ||||
|             .filter(users::role.ne(Role::Instance as i32)) | ||||
|             // TODO: use `ilike` instead of `like` for PostgreSQL
 | ||||
|             .filter( | ||||
|                 users::username | ||||
|                     .like(format!("%{}%", name)) | ||||
|                     .or(users::display_name.like(format!("%{}%", name))), | ||||
|             ) | ||||
|             .order(users::username.asc()) | ||||
|             .offset(min.into()) | ||||
|             .limit((max - min).into()) | ||||
|             .load::<User>(conn) | ||||
|             .map_err(Error::from) | ||||
|     } | ||||
| 
 | ||||
|     /**
 | ||||
|      * TODO: Should create user record with normalized(lowercased) email | ||||
|      */ | ||||
| @ -431,6 +456,7 @@ impl User { | ||||
|     pub fn get_local_page(conn: &Connection, (min, max): (i32, i32)) -> Result<Vec<User>> { | ||||
|         users::table | ||||
|             .filter(users::instance_id.eq(Instance::get_local()?.id)) | ||||
|             .filter(users::role.ne(Role::Instance as i32)) | ||||
|             .order(users::username.asc()) | ||||
|             .offset(min.into()) | ||||
|             .limit((max - min).into()) | ||||
|  | ||||
| @ -157,6 +157,7 @@ Then try to restart Plume. | ||||
|                 routes::instance::admin_mod, | ||||
|                 routes::instance::admin_instances, | ||||
|                 routes::instance::admin_users, | ||||
|                 routes::instance::admin_search_users, | ||||
|                 routes::instance::admin_email_blocklist, | ||||
|                 routes::instance::add_email_blocklist, | ||||
|                 routes::instance::delete_email_blocklist, | ||||
|  | ||||
| @ -160,7 +160,7 @@ pub fn toggle_block( | ||||
|     )) | ||||
| } | ||||
| 
 | ||||
| #[get("/admin/users?<page>")] | ||||
| #[get("/admin/users?<page>", rank = 2)] | ||||
| pub fn admin_users( | ||||
|     _mod: Moderator, | ||||
|     page: Option<Page>, | ||||
| @ -171,6 +171,30 @@ pub fn admin_users( | ||||
|     Ok(render!(instance::users( | ||||
|         &(&conn, &rockets).to_context(), | ||||
|         User::get_local_page(&conn, page.limits())?, | ||||
|         None, | ||||
|         page.0, | ||||
|         Page::total(User::count_local(&conn)? as i32) | ||||
|     ))) | ||||
| } | ||||
| #[get("/admin/users?<user>&<page>", rank = 1)] | ||||
| pub fn admin_search_users( | ||||
|     _mod: Moderator, | ||||
|     user: String, | ||||
|     page: Option<Page>, | ||||
|     conn: DbConn, | ||||
|     rockets: PlumeRocket, | ||||
| ) -> Result<Ructe, ErrorPage> { | ||||
|     let page = page.unwrap_or_default(); | ||||
|     let users = if user.is_empty() { | ||||
|         User::get_local_page(&conn, page.limits())? | ||||
|     } else { | ||||
|         User::search_local_by_name(&conn, &user, page.limits())? | ||||
|     }; | ||||
| 
 | ||||
|     Ok(render!(instance::users( | ||||
|         &(&conn, &rockets).to_context(), | ||||
|         users, | ||||
|         Some(user.as_str()), | ||||
|         page.0, | ||||
|         Page::total(User::count_local(&conn)? as i32) | ||||
|     ))) | ||||
|  | ||||
| @ -3,7 +3,7 @@ | ||||
| @use crate::template_utils::*; | ||||
| @use crate::routes::*; | ||||
| 
 | ||||
| @(ctx: BaseContext, users: Vec<User>, page: i32, n_pages: i32) | ||||
| @(ctx: BaseContext, users: Vec<User>, user: Option<&str>, page: i32, n_pages: i32) | ||||
| 
 | ||||
| @:base(ctx, i18n!(ctx.1, "Users"), {}, {}, { | ||||
|     <h1>@i18n!(ctx.1, "Users")</h1> | ||||
| @ -15,6 +15,13 @@ | ||||
|         (&uri!(instance::admin_email_blocklist: page=_).to_string(), i18n!(ctx.1, "Email blocklist"), false) | ||||
|     ]) | ||||
| 
 | ||||
|     <form method="get" action="@uri!(instance::admin_search_users: page = _, user = user.unwrap_or_default())"> | ||||
|         <header> | ||||
|             <input type="search" name="user" value="@user.unwrap_or_default()"> | ||||
|             <input type="submit" value="@i18n!(ctx.1, "Search users")"> | ||||
|         </header> | ||||
|     </form> | ||||
| 
 | ||||
|     <form method="post" action="@uri!(instance::edit_users)"> | ||||
|         <header> | ||||
|             <select name="action"> | ||||
| @ -46,5 +53,9 @@ | ||||
|             } | ||||
|         </div> | ||||
|     </form> | ||||
|     @paginate(ctx.1, page, n_pages) | ||||
|     @if user.is_some() { | ||||
|       @paginate_param(ctx.1, page, n_pages, Some(format!("user={}", encode_query_param(user.unwrap_or_default())))) | ||||
|     } else { | ||||
|       @paginate(ctx.1, page, n_pages) | ||||
|     } | ||||
| }) | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user