Browse Source

is_candidate and is_admin

master
hole-thu 3 years ago
parent
commit
8639ed0c88
  1. 10
      src/api/comment.rs
  2. 81
      src/api/mod.rs
  3. 8
      src/api/post.rs
  4. 10
      src/rds_models.rs

10
src/api/comment.rs

@ -125,17 +125,17 @@ pub async fn add_comment(
rconn: RdsConn, rconn: RdsConn,
) -> JsonApi { ) -> JsonApi {
let mut p = Post::get(&db, &rconn, pid).await?; 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( let c = Comment::create(
&db, &db,
NewComment { NewComment {
content: ci.text.to_string(), content: ci.text.to_string(),
author_hash: user.namehash.to_string(), author_hash: user.namehash.to_string(),
author_title: (if ci.use_title.is_some() { author_title: if use_title {
CustomTitle::get(&rconn, &user.namehash).await? user.custom_title
} else { } else {
None "".to_owned()
}) },
.unwrap_or_default(),
is_tmp: user.id.is_none(), is_tmp: user.id.is_none(),
post_id: pid, post_id: pid,
}, },

81
src/api/mod.rs

@ -57,10 +57,28 @@ pub struct CurrentUser {
pub id: Option<i32>, // tmp user has no id, only for block pub id: Option<i32>, // tmp user has no id, only for block
namehash: String, namehash: String,
is_admin: bool, is_admin: bool,
is_candidate: bool,
custom_title: String, custom_title: String,
pub auto_block_rank: u8, 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] #[rocket::async_trait]
impl<'r> FromRequest<'r> for CurrentUser { impl<'r> FromRequest<'r> for CurrentUser {
type Error = (); type Error = ();
@ -68,44 +86,37 @@ impl<'r> FromRequest<'r> for CurrentUser {
let rh = request.rocket().state::<RandomHasher>().unwrap(); let rh = request.rocket().state::<RandomHasher>().unwrap();
let rconn = try_outcome!(request.guard::<RdsConn>().await); let rconn = try_outcome!(request.guard::<RdsConn>().await);
let mut id = None; if let Some(user) = {
let mut namehash = None; if let Some(token) = request.headers().get_one("User-Token") {
let mut is_admin = false; let sp = token.split('_').collect::<Vec<&str>>();
if sp.len() == 2 && sp[0] == rh.get_tmp_token() {
if let Some(token) = request.headers().get_one("User-Token") { Some(CurrentUser::from_hash(&rconn, rh.hash_with_salt(sp[1])).await)
let sp = token.split('_').collect::<Vec<&str>>();
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::<Db>().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, ()))
} else { } else {
Outcome::Success(CurrentUser { let db = try_outcome!(request.guard::<Db>().await);
id, if let Some(u) = User::get_by_token(&db, &rconn, token).await {
custom_title: CustomTitle::get(&rconn, &nh) let namehash = rh.hash_with_salt(&u.name);
.await Some(CurrentUser {
.ok() id: Some(u.id),
.flatten() is_admin: u.is_admin
.unwrap_or_default(), || is_elected_admin(&rconn, &namehash).await.unwrap(),
auto_block_rank: AutoBlockRank::get(&rconn, &nh).await.unwrap_or(2), is_candidate: is_elected_candidate(&rconn, &namehash).await.unwrap(),
namehash: nh, ..CurrentUser::from_hash(&rconn, namehash).await
is_admin, })
}) } 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, ()))
} }
} }
} }

8
src/api/post.rs

@ -197,13 +197,19 @@ pub async fn publish_post(
poi.text.to_string() poi.text.to_string()
}; };
let use_title = poi.use_title.is_some() || user.is_admin || user.is_candidate;
let p = Post::create( let p = Post::create(
&db, &db,
NewPost { NewPost {
content: text, content: text,
cw: poi.cw.to_string(), cw: poi.cw.to_string(),
author_hash: user.namehash.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(), is_tmp: user.id.is_none(),
n_attentions: 1, n_attentions: 1,
allow_search: poi.allow_search.is_some(), allow_search: poi.allow_search.is_some(),

10
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_CUSTOM_TITLE: &str = "hole_v2:title";
const KEY_AUTO_BLOCK_RANK: &str = "hole_v2:auto_block_rank"; // rank * 5: 自动过滤的拉黑数阈值 const KEY_AUTO_BLOCK_RANK: &str = "hole_v2:auto_block_rank"; // rank * 5: 自动过滤的拉黑数阈值
const KEY_ANNOUNCEMENT: &str = "hole_v2:announcement"; 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; const SYSTEMLOG_MAX_LEN: isize = 1000;
@ -295,4 +297,12 @@ pub async fn get_announcement(rconn: &RdsConn) -> RedisResult<Option<String>> {
rconn.clone().get(KEY_ANNOUNCEMENT).await rconn.clone().get(KEY_ANNOUNCEMENT).await
} }
pub async fn is_elected_candidate(rconn: &RdsConn, namehash: &str) -> RedisResult<bool> {
rconn.clone().sismember(KEY_CANDIDATE, namehash).await
}
pub async fn is_elected_admin(rconn: &RdsConn, namehash: &str) -> RedisResult<bool> {
rconn.clone().sismember(KEY_ADMIN, namehash).await
}
pub(crate) use init; pub(crate) use init;

Loading…
Cancel
Save