From 8639ed0c8812ba6ac2a85ef0604611001b170ada Mon Sep 17 00:00:00 2001 From: hole-thu Date: Wed, 31 Aug 2022 00:53:17 +0800 Subject: [PATCH] is_candidate and is_admin --- src/api/comment.rs | 10 +++--- src/api/mod.rs | 81 ++++++++++++++++++++++++++-------------------- src/api/post.rs | 8 ++++- src/rds_models.rs | 10 ++++++ 4 files changed, 68 insertions(+), 41 deletions(-) diff --git a/src/api/comment.rs b/src/api/comment.rs index 321886b..7f49402 100644 --- a/src/api/comment.rs +++ b/src/api/comment.rs @@ -125,17 +125,17 @@ pub async fn add_comment( rconn: RdsConn, ) -> JsonApi { let mut p = Post::get(&db, &rconn, pid).await?; + let use_title = ci.use_title.is_some() || user.is_admin || user.is_candidate; let c = Comment::create( &db, NewComment { content: ci.text.to_string(), author_hash: user.namehash.to_string(), - author_title: (if ci.use_title.is_some() { - CustomTitle::get(&rconn, &user.namehash).await? + author_title: if use_title { + user.custom_title } else { - None - }) - .unwrap_or_default(), + "".to_owned() + }, is_tmp: user.id.is_none(), post_id: pid, }, diff --git a/src/api/mod.rs b/src/api/mod.rs index 08aa2cc..0a290f8 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -57,10 +57,28 @@ pub struct CurrentUser { pub id: Option, // tmp user has no id, only for block namehash: String, is_admin: bool, + is_candidate: bool, custom_title: String, pub auto_block_rank: u8, } +impl CurrentUser { + pub async fn from_hash(rconn: &RdsConn, namehash: String) -> Self { + Self { + id: None, + is_admin: false, + is_candidate: false, + custom_title: CustomTitle::get(rconn, &namehash) + .await + .ok() + .flatten() + .unwrap_or_default(), + auto_block_rank: AutoBlockRank::get(rconn, &namehash).await.unwrap_or(2), + namehash, + } + } +} + #[rocket::async_trait] impl<'r> FromRequest<'r> for CurrentUser { type Error = (); @@ -68,44 +86,37 @@ impl<'r> FromRequest<'r> for CurrentUser { let rh = request.rocket().state::().unwrap(); let rconn = try_outcome!(request.guard::().await); - let mut id = None; - let mut namehash = None; - let mut is_admin = false; - - if let Some(token) = request.headers().get_one("User-Token") { - let sp = token.split('_').collect::>(); - if sp.len() == 2 && sp[0] == rh.get_tmp_token() { - namehash = Some(rh.hash_with_salt(sp[1])); - id = None; - is_admin = false; - } else { - let db = try_outcome!(request.guard::().await); - if let Some(u) = User::get_by_token(&db, &rconn, token).await { - id = Some(u.id); - namehash = Some(rh.hash_with_salt(&u.name)); - is_admin = u.is_admin; - } - } - } - match namehash { - Some(nh) => { - if BannedUsers::has(&rconn, &nh).await.unwrap() { - Outcome::Failure((Status::Forbidden, ())) + if let Some(user) = { + if let Some(token) = request.headers().get_one("User-Token") { + let sp = token.split('_').collect::>(); + if sp.len() == 2 && sp[0] == rh.get_tmp_token() { + Some(CurrentUser::from_hash(&rconn, rh.hash_with_salt(sp[1])).await) } else { - Outcome::Success(CurrentUser { - id, - custom_title: CustomTitle::get(&rconn, &nh) - .await - .ok() - .flatten() - .unwrap_or_default(), - auto_block_rank: AutoBlockRank::get(&rconn, &nh).await.unwrap_or(2), - namehash: nh, - is_admin, - }) + let db = try_outcome!(request.guard::().await); + if let Some(u) = User::get_by_token(&db, &rconn, token).await { + let namehash = rh.hash_with_salt(&u.name); + Some(CurrentUser { + id: Some(u.id), + is_admin: u.is_admin + || is_elected_admin(&rconn, &namehash).await.unwrap(), + is_candidate: is_elected_candidate(&rconn, &namehash).await.unwrap(), + ..CurrentUser::from_hash(&rconn, namehash).await + }) + } else { + None + } } + } else { + None + } + } { + if BannedUsers::has(&rconn, &user.namehash).await.unwrap() { + Outcome::Failure((Status::Forbidden, ())) + } else { + Outcome::Success(user) } - None => Outcome::Failure((Status::Unauthorized, ())), + } else { + Outcome::Failure((Status::Unauthorized, ())) } } } diff --git a/src/api/post.rs b/src/api/post.rs index 6f5ecc6..79a2698 100644 --- a/src/api/post.rs +++ b/src/api/post.rs @@ -197,13 +197,19 @@ pub async fn publish_post( poi.text.to_string() }; + let use_title = poi.use_title.is_some() || user.is_admin || user.is_candidate; + let p = Post::create( &db, NewPost { content: text, cw: poi.cw.to_string(), author_hash: user.namehash.to_string(), - author_title: poi.use_title.map(|_| user.custom_title).unwrap_or_default(), + author_title: if use_title { + user.custom_title + } else { + "".to_owned() + }, is_tmp: user.id.is_none(), n_attentions: 1, allow_search: poi.allow_search.is_some(), diff --git a/src/rds_models.rs b/src/rds_models.rs index 7fa7d62..2a343eb 100644 --- a/src/rds_models.rs +++ b/src/rds_models.rs @@ -53,6 +53,8 @@ const KEY_BLOCKED_COUNTER: &str = "hole_v2:blocked_counter"; const KEY_CUSTOM_TITLE: &str = "hole_v2:title"; const KEY_AUTO_BLOCK_RANK: &str = "hole_v2:auto_block_rank"; // rank * 5: 自动过滤的拉黑数阈值 const KEY_ANNOUNCEMENT: &str = "hole_v2:announcement"; +const KEY_CANDIDATE: &str = "hole_v2:candidate"; +const KEY_ADMIN: &str = "hole_v2:admin"; const SYSTEMLOG_MAX_LEN: isize = 1000; @@ -295,4 +297,12 @@ pub async fn get_announcement(rconn: &RdsConn) -> RedisResult> { rconn.clone().get(KEY_ANNOUNCEMENT).await } +pub async fn is_elected_candidate(rconn: &RdsConn, namehash: &str) -> RedisResult { + rconn.clone().sismember(KEY_CANDIDATE, namehash).await +} + +pub async fn is_elected_admin(rconn: &RdsConn, namehash: &str) -> RedisResult { + rconn.clone().sismember(KEY_ADMIN, namehash).await +} + pub(crate) use init;