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 {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::blogs::Blog;
|
use crate::blogs::Blog;
|
||||||
|
use crate::db_conn::DbConn;
|
||||||
use crate::inbox::{inbox, tests::fill_database, InboxResult};
|
use crate::inbox::{inbox, tests::fill_database, InboxResult};
|
||||||
use crate::safe_string::SafeString;
|
use crate::safe_string::SafeString;
|
||||||
use crate::tests::{db, format_datetime};
|
use crate::tests::{db, format_datetime};
|
||||||
|
@ -232,7 +232,9 @@ impl IntoId for Follow {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
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 assert_json_diff::assert_json_eq;
|
||||||
use diesel::Connection;
|
use diesel::Connection;
|
||||||
use serde_json::{json, to_value};
|
use serde_json::{json, to_value};
|
||||||
|
@ -1027,6 +1027,7 @@ impl From<PostEvent> for Arc<Post> {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::db_conn::DbConn;
|
||||||
use crate::inbox::{inbox, tests::fill_database, InboxResult};
|
use crate::inbox::{inbox, tests::fill_database, InboxResult};
|
||||||
use crate::mentions::{Mention, NewMention};
|
use crate::mentions::{Mention, NewMention};
|
||||||
use crate::safe_string::SafeString;
|
use crate::safe_string::SafeString;
|
||||||
|
@ -15,7 +15,10 @@ use activitystreams::{
|
|||||||
prelude::*,
|
prelude::*,
|
||||||
};
|
};
|
||||||
use chrono::{NaiveDateTime, Utc};
|
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 ldap3::{LdapConn, Scope, SearchEntry};
|
||||||
use openssl::{
|
use openssl::{
|
||||||
hash::MessageDigest,
|
hash::MessageDigest,
|
||||||
@ -186,6 +189,7 @@ impl User {
|
|||||||
pub fn count_local(conn: &Connection) -> Result<i64> {
|
pub fn count_local(conn: &Connection) -> Result<i64> {
|
||||||
users::table
|
users::table
|
||||||
.filter(users::instance_id.eq(Instance::get_local()?.id))
|
.filter(users::instance_id.eq(Instance::get_local()?.id))
|
||||||
|
.filter(users::role.ne(Role::Instance as i32))
|
||||||
.count()
|
.count()
|
||||||
.get_result(conn)
|
.get_result(conn)
|
||||||
.map_err(Error::from)
|
.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
|
* 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>> {
|
pub fn get_local_page(conn: &Connection, (min, max): (i32, i32)) -> Result<Vec<User>> {
|
||||||
users::table
|
users::table
|
||||||
.filter(users::instance_id.eq(Instance::get_local()?.id))
|
.filter(users::instance_id.eq(Instance::get_local()?.id))
|
||||||
|
.filter(users::role.ne(Role::Instance as i32))
|
||||||
.order(users::username.asc())
|
.order(users::username.asc())
|
||||||
.offset(min.into())
|
.offset(min.into())
|
||||||
.limit((max - min).into())
|
.limit((max - min).into())
|
||||||
|
@ -157,6 +157,7 @@ Then try to restart Plume.
|
|||||||
routes::instance::admin_mod,
|
routes::instance::admin_mod,
|
||||||
routes::instance::admin_instances,
|
routes::instance::admin_instances,
|
||||||
routes::instance::admin_users,
|
routes::instance::admin_users,
|
||||||
|
routes::instance::admin_search_users,
|
||||||
routes::instance::admin_email_blocklist,
|
routes::instance::admin_email_blocklist,
|
||||||
routes::instance::add_email_blocklist,
|
routes::instance::add_email_blocklist,
|
||||||
routes::instance::delete_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(
|
pub fn admin_users(
|
||||||
_mod: Moderator,
|
_mod: Moderator,
|
||||||
page: Option<Page>,
|
page: Option<Page>,
|
||||||
@ -171,6 +171,30 @@ pub fn admin_users(
|
|||||||
Ok(render!(instance::users(
|
Ok(render!(instance::users(
|
||||||
&(&conn, &rockets).to_context(),
|
&(&conn, &rockets).to_context(),
|
||||||
User::get_local_page(&conn, page.limits())?,
|
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.0,
|
||||||
Page::total(User::count_local(&conn)? as i32)
|
Page::total(User::count_local(&conn)? as i32)
|
||||||
)))
|
)))
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
@use crate::template_utils::*;
|
@use crate::template_utils::*;
|
||||||
@use crate::routes::*;
|
@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"), {}, {}, {
|
@:base(ctx, i18n!(ctx.1, "Users"), {}, {}, {
|
||||||
<h1>@i18n!(ctx.1, "Users")</h1>
|
<h1>@i18n!(ctx.1, "Users")</h1>
|
||||||
@ -15,6 +15,13 @@
|
|||||||
(&uri!(instance::admin_email_blocklist: page=_).to_string(), i18n!(ctx.1, "Email blocklist"), false)
|
(&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)">
|
<form method="post" action="@uri!(instance::edit_users)">
|
||||||
<header>
|
<header>
|
||||||
<select name="action">
|
<select name="action">
|
||||||
@ -46,5 +53,9 @@
|
|||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</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…
Reference in New Issue
Block a user