diff --git a/src/api/mod.rs b/src/api/mod.rs index ab53a09..f3a06ff 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -105,12 +105,17 @@ impl<'r> FromRequest<'r> for CurrentUser { 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); + let user_base = CurrentUser::from_hash(&rconn, namehash).await; 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 + || is_elected_admin(&rconn, &user_base.custom_title) + .await + .unwrap(), + is_candidate: is_elected_candidate(&rconn, &user_base.custom_title) + .await + .unwrap(), + ..user_base }) } else { None diff --git a/src/api/post.rs b/src/api/post.rs index c65e6ed..960919f 100644 --- a/src/api/post.rs +++ b/src/api/post.rs @@ -177,6 +177,8 @@ pub async fn get_list( "count": ps_data.len(), "custom_title": user.custom_title, "title_secret": user.title_secret, + "is_admin": user.is_admin, + "is_candidate": user.is_candidate, "auto_block_rank": user.auto_block_rank, "announcement": get_announcement(&rconn).await?, "code": 0 diff --git a/src/api/systemlog.rs b/src/api/systemlog.rs index f399360..068b287 100644 --- a/src/api/systemlog.rs +++ b/src/api/systemlog.rs @@ -1,7 +1,7 @@ use crate::api::{CurrentUser, JsonApi}; use crate::random_hasher::RandomHasher; use crate::rds_conn::RdsConn; -use crate::rds_models::Systemlog; +use crate::rds_models::{get_admin_list, get_candidate_list, Systemlog}; use rocket::serde::json::{json, Value}; use rocket::State; @@ -14,6 +14,8 @@ pub async fn get_systemlog(user: CurrentUser, rh: &State, rconn: R "salt": look!(rh.salt), "start_time": rh.start_time.timestamp(), "custom_title": user.custom_title, + "admin_list": get_admin_list(&rconn).await?, + "candidate_list": get_candidate_list(&rconn).await?, "data": logs.into_iter().map(|log| json!({ "type": log.action_type, diff --git a/src/rds_models.rs b/src/rds_models.rs index 488eda4..4d6111e 100644 --- a/src/rds_models.rs +++ b/src/rds_models.rs @@ -233,9 +233,17 @@ impl CustomTitle { Err(PolicyError::TitleUsed)? } else { let ori_secret: Option = rconn.get(KEY_TITLE_SECRET!(title)).await?; + if ori_secret.is_none() { + clear_title_from_admins(&rconn, title).await?; + } ori_secret .map_or(Some(()), |s| (s.eq(&secret).then_some(()))) .ok_or(PolicyError::TitleProtected)?; + + let old_title: Option = rconn.hget(KEY_CUSTOM_TITLE, namehash).await?; + if let Some(t) = old_title { + clear_title_from_admins(&rconn, &t).await?; + } rconn.hset(KEY_CUSTOM_TITLE, namehash, title).await?; rconn.hset(KEY_CUSTOM_TITLE, title, namehash).await?; Ok(Self::gen_and_set_secret(&rconn, title).await?) @@ -332,12 +340,33 @@ 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_candidate(rconn: &RdsConn, title: &str) -> RedisResult { + if title.is_empty() { + return Ok(false); + } + rconn.clone().sismember(KEY_CANDIDATE, title).await +} + +pub async fn is_elected_admin(rconn: &RdsConn, title: &str) -> RedisResult { + if title.is_empty() { + return Ok(false); + } + rconn.clone().sismember(KEY_ADMIN, title).await +} + +pub async fn get_admin_list(rconn: &RdsConn) -> RedisResult> { + rconn.clone().smembers(KEY_ADMIN).await +} + +pub async fn get_candidate_list(rconn: &RdsConn) -> RedisResult> { + rconn.clone().smembers(KEY_CANDIDATE).await } -pub async fn is_elected_admin(rconn: &RdsConn, namehash: &str) -> RedisResult { - rconn.clone().sismember(KEY_ADMIN, namehash).await +pub async fn clear_title_from_admins(rconn: &RdsConn, title: &str) -> RedisResult<()> { + let mut rconn = rconn.clone(); + rconn.srem(KEY_CANDIDATE, title).await?; + rconn.srem(KEY_ADMIN, title).await?; + Ok(()) } pub(crate) use init;