fix clippy & rustfmt
This commit is contained in:
1
rust-toolchain
Normal file
1
rust-toolchain
Normal file
@@ -0,0 +1 @@
|
|||||||
|
stable
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
use crate::api::post::ps2outputs;
|
use crate::api::post::ps2outputs;
|
||||||
use crate::api::{CurrentUser, JsonAPI, PolicyError::*, UGC};
|
use crate::api::{CurrentUser, JsonApi, PolicyError::*, Ugc};
|
||||||
use crate::db_conn::Db;
|
use crate::db_conn::Db;
|
||||||
use crate::libs::diesel_logger::LoggingConnection;
|
use crate::libs::diesel_logger::LoggingConnection;
|
||||||
use crate::models::*;
|
use crate::models::*;
|
||||||
@@ -23,7 +23,7 @@ pub async fn attention_post(
|
|||||||
user: CurrentUser,
|
user: CurrentUser,
|
||||||
db: Db,
|
db: Db,
|
||||||
rconn: RdsConn,
|
rconn: RdsConn,
|
||||||
) -> JsonAPI {
|
) -> JsonApi {
|
||||||
// 临时用户不允许手动关注
|
// 临时用户不允许手动关注
|
||||||
user.id.ok_or(YouAreTmp)?;
|
user.id.ok_or(YouAreTmp)?;
|
||||||
|
|
||||||
@@ -68,7 +68,7 @@ pub async fn attention_post(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[get("/getattention")]
|
#[get("/getattention")]
|
||||||
pub async fn get_attention(user: CurrentUser, db: Db, rconn: RdsConn) -> JsonAPI {
|
pub async fn get_attention(user: CurrentUser, db: Db, rconn: RdsConn) -> JsonApi {
|
||||||
let mut ids = Attention::init(&user.namehash, &rconn).all().await?;
|
let mut ids = Attention::init(&user.namehash, &rconn).all().await?;
|
||||||
ids.sort_by_key(|x| -x);
|
ids.sort_by_key(|x| -x);
|
||||||
let ps = Post::get_multi(&db, &rconn, &ids).await?;
|
let ps = Post::get_multi(&db, &rconn, &ids).await?;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::api::{APIError, CurrentUser, JsonAPI, PolicyError::*, UGC};
|
use crate::api::{ApiError, CurrentUser, JsonApi, PolicyError::*, Ugc};
|
||||||
use crate::cache::BlockDictCache;
|
use crate::cache::BlockDictCache;
|
||||||
use crate::db_conn::Db;
|
use crate::db_conn::Db;
|
||||||
use crate::libs::diesel_logger::LoggingConnection;
|
use crate::libs::diesel_logger::LoggingConnection;
|
||||||
@@ -40,7 +40,7 @@ pub struct CommentOutput {
|
|||||||
|
|
||||||
pub async fn c2output<'r>(
|
pub async fn c2output<'r>(
|
||||||
p: &'r Post,
|
p: &'r Post,
|
||||||
cs: &Vec<Comment>,
|
cs: &[Comment],
|
||||||
user: &CurrentUser,
|
user: &CurrentUser,
|
||||||
cached_block_dict: &HashMap<String, bool>,
|
cached_block_dict: &HashMap<String, bool>,
|
||||||
rconn: &RdsConn,
|
rconn: &RdsConn,
|
||||||
@@ -66,10 +66,10 @@ pub async fn c2output<'r>(
|
|||||||
text: (if can_view { &c.content } else { "" }).to_string(),
|
text: (if can_view { &c.content } else { "" }).to_string(),
|
||||||
author_title: c.author_title.to_string(),
|
author_title: c.author_title.to_string(),
|
||||||
can_del: c.check_permission(user, "wd").is_ok(),
|
can_del: c.check_permission(user, "wd").is_ok(),
|
||||||
name_id: name_id,
|
name_id,
|
||||||
is_tmp: c.is_tmp,
|
is_tmp: c.is_tmp,
|
||||||
create_time: c.create_time.timestamp(),
|
create_time: c.create_time.timestamp(),
|
||||||
is_blocked: is_blocked,
|
is_blocked,
|
||||||
blocked_count: if user.is_admin {
|
blocked_count: if user.is_admin {
|
||||||
BlockCounter::get_count(rconn, &c.author_hash)
|
BlockCounter::get_count(rconn, &c.author_hash)
|
||||||
.await
|
.await
|
||||||
@@ -85,18 +85,18 @@ pub async fn c2output<'r>(
|
|||||||
}))
|
}))
|
||||||
.await
|
.await
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|x| x)
|
.flatten()
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/getcomment?<pid>")]
|
#[get("/getcomment?<pid>")]
|
||||||
pub async fn get_comment(pid: i32, user: CurrentUser, db: Db, rconn: RdsConn) -> JsonAPI {
|
pub async fn get_comment(pid: i32, user: CurrentUser, db: Db, rconn: RdsConn) -> JsonApi {
|
||||||
let p = Post::get(&db, &rconn, pid).await?;
|
let p = Post::get(&db, &rconn, pid).await?;
|
||||||
if p.is_deleted {
|
if p.is_deleted {
|
||||||
return Err(APIError::PcError(IsDeleted));
|
return Err(ApiError::Pc(IsDeleted));
|
||||||
}
|
}
|
||||||
let cs = p.get_comments(&db, &rconn).await?;
|
let cs = p.get_comments(&db, &rconn).await?;
|
||||||
let hash_list = cs.iter().map(|c| &c.author_hash).collect();
|
let hash_list = cs.iter().map(|c| &c.author_hash).collect::<Vec<_>>();
|
||||||
let cached_block_dict = BlockDictCache::init(&user.namehash, p.id, &rconn)
|
let cached_block_dict = BlockDictCache::init(&user.namehash, p.id, &rconn)
|
||||||
.get_or_create(&user, &hash_list)
|
.get_or_create(&user, &hash_list)
|
||||||
.await?;
|
.await?;
|
||||||
@@ -118,7 +118,7 @@ pub async fn add_comment(
|
|||||||
user: CurrentUser,
|
user: CurrentUser,
|
||||||
db: Db,
|
db: Db,
|
||||||
rconn: RdsConn,
|
rconn: RdsConn,
|
||||||
) -> JsonAPI {
|
) -> JsonApi {
|
||||||
let mut p = Post::get(&db, &rconn, ci.pid).await?;
|
let mut p = Post::get(&db, &rconn, ci.pid).await?;
|
||||||
let c = Comment::create(
|
let c = Comment::create(
|
||||||
&db,
|
&db,
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ impl<'r> FromRequest<'r> for CurrentUser {
|
|||||||
Outcome::Failure((Status::Forbidden, ()))
|
Outcome::Failure((Status::Forbidden, ()))
|
||||||
} else {
|
} else {
|
||||||
Outcome::Success(CurrentUser {
|
Outcome::Success(CurrentUser {
|
||||||
id: id,
|
id,
|
||||||
custom_title: CustomTitle::get(&rconn, &nh)
|
custom_title: CustomTitle::get(&rconn, &nh)
|
||||||
.await
|
.await
|
||||||
.ok()
|
.ok()
|
||||||
@@ -99,7 +99,7 @@ impl<'r> FromRequest<'r> for CurrentUser {
|
|||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
auto_block_rank: AutoBlockRank::get(&rconn, &nh).await.unwrap_or(2),
|
auto_block_rank: AutoBlockRank::get(&rconn, &nh).await.unwrap_or(2),
|
||||||
namehash: nh,
|
namehash: nh,
|
||||||
is_admin: is_admin,
|
is_admin,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -119,20 +119,20 @@ pub enum PolicyError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum APIError {
|
pub enum ApiError {
|
||||||
DbError(diesel::result::Error),
|
Db(diesel::result::Error),
|
||||||
RdsError(redis::RedisError),
|
Rds(redis::RedisError),
|
||||||
PcError(PolicyError),
|
Pc(PolicyError),
|
||||||
IoError(std::io::Error),
|
IO(std::io::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'r> Responder<'r, 'static> for APIError {
|
impl<'r> Responder<'r, 'static> for ApiError {
|
||||||
fn respond_to(self, req: &'r Request<'_>) -> response::Result<'static> {
|
fn respond_to(self, req: &'r Request<'_>) -> response::Result<'static> {
|
||||||
match self {
|
match self {
|
||||||
APIError::DbError(e) => e2s!(e).respond_to(req),
|
ApiError::Db(e) => e2s!(e).respond_to(req),
|
||||||
APIError::RdsError(e) => e2s!(e).respond_to(req),
|
ApiError::Rds(e) => e2s!(e).respond_to(req),
|
||||||
APIError::IoError(e) => e2s!(e).respond_to(req),
|
ApiError::IO(e) => e2s!(e).respond_to(req),
|
||||||
APIError::PcError(e) => json!({
|
ApiError::Pc(e) => json!({
|
||||||
"code": -1,
|
"code": -1,
|
||||||
"msg": match e {
|
"msg": match e {
|
||||||
PolicyError::IsReported => "内容被举报,处理中",
|
PolicyError::IsReported => "内容被举报,处理中",
|
||||||
@@ -148,60 +148,60 @@ impl<'r> Responder<'r, 'static> for APIError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<diesel::result::Error> for APIError {
|
impl From<diesel::result::Error> for ApiError {
|
||||||
fn from(err: diesel::result::Error) -> APIError {
|
fn from(err: diesel::result::Error) -> ApiError {
|
||||||
APIError::DbError(err)
|
ApiError::Db(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<redis::RedisError> for APIError {
|
impl From<redis::RedisError> for ApiError {
|
||||||
fn from(err: redis::RedisError) -> APIError {
|
fn from(err: redis::RedisError) -> ApiError {
|
||||||
APIError::RdsError(err)
|
ApiError::Rds(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<std::io::Error> for APIError {
|
impl From<std::io::Error> for ApiError {
|
||||||
fn from(err: std::io::Error) -> APIError {
|
fn from(err: std::io::Error) -> ApiError {
|
||||||
APIError::IoError(err)
|
ApiError::IO(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<PolicyError> for APIError {
|
impl From<PolicyError> for ApiError {
|
||||||
fn from(err: PolicyError) -> APIError {
|
fn from(err: PolicyError) -> ApiError {
|
||||||
APIError::PcError(err)
|
ApiError::Pc(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type API<T> = Result<T, APIError>;
|
pub type Api<T> = Result<T, ApiError>;
|
||||||
pub type JsonAPI = API<Value>;
|
pub type JsonApi = Api<Value>;
|
||||||
|
|
||||||
#[rocket::async_trait]
|
#[rocket::async_trait]
|
||||||
pub trait UGC {
|
pub trait Ugc {
|
||||||
fn get_author_hash(&self) -> &str;
|
fn get_author_hash(&self) -> &str;
|
||||||
fn get_is_deleted(&self) -> bool;
|
fn get_is_deleted(&self) -> bool;
|
||||||
fn get_is_reported(&self) -> bool;
|
fn get_is_reported(&self) -> bool;
|
||||||
fn extra_delete_condition(&self) -> bool;
|
fn extra_delete_condition(&self) -> bool;
|
||||||
async fn do_set_deleted(&mut self, db: &Db) -> API<()>;
|
async fn do_set_deleted(&mut self, db: &Db) -> Api<()>;
|
||||||
fn check_permission(&self, user: &CurrentUser, mode: &str) -> API<()> {
|
fn check_permission(&self, user: &CurrentUser, mode: &str) -> Api<()> {
|
||||||
if user.is_admin {
|
if user.is_admin {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
if mode.contains('r') && self.get_is_deleted() {
|
if mode.contains('r') && self.get_is_deleted() {
|
||||||
return Err(APIError::PcError(PolicyError::IsDeleted));
|
return Err(ApiError::Pc(PolicyError::IsDeleted));
|
||||||
}
|
}
|
||||||
if mode.contains('o') && self.get_is_reported() {
|
if mode.contains('o') && self.get_is_reported() {
|
||||||
return Err(APIError::PcError(PolicyError::IsReported));
|
return Err(ApiError::Pc(PolicyError::IsReported));
|
||||||
}
|
}
|
||||||
if mode.contains('w') && self.get_author_hash() != user.namehash {
|
if mode.contains('w') && self.get_author_hash() != user.namehash {
|
||||||
return Err(APIError::PcError(PolicyError::NotAllowed));
|
return Err(ApiError::Pc(PolicyError::NotAllowed));
|
||||||
}
|
}
|
||||||
if mode.contains('d') && !self.extra_delete_condition() {
|
if mode.contains('d') && !self.extra_delete_condition() {
|
||||||
return Err(APIError::PcError(PolicyError::NotAllowed));
|
return Err(ApiError::Pc(PolicyError::NotAllowed));
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn soft_delete(&mut self, user: &CurrentUser, db: &Db) -> API<()> {
|
async fn soft_delete(&mut self, user: &CurrentUser, db: &Db) -> Api<()> {
|
||||||
self.check_permission(user, "rwd")?;
|
self.check_permission(user, "rwd")?;
|
||||||
|
|
||||||
self.do_set_deleted(db).await?;
|
self.do_set_deleted(db).await?;
|
||||||
@@ -210,7 +210,7 @@ pub trait UGC {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[rocket::async_trait]
|
#[rocket::async_trait]
|
||||||
impl UGC for Post {
|
impl Ugc for Post {
|
||||||
fn get_author_hash(&self) -> &str {
|
fn get_author_hash(&self) -> &str {
|
||||||
&self.author_hash
|
&self.author_hash
|
||||||
}
|
}
|
||||||
@@ -223,14 +223,14 @@ impl UGC for Post {
|
|||||||
fn extra_delete_condition(&self) -> bool {
|
fn extra_delete_condition(&self) -> bool {
|
||||||
!self.content.starts_with("[系统自动代发]\n")
|
!self.content.starts_with("[系统自动代发]\n")
|
||||||
}
|
}
|
||||||
async fn do_set_deleted(&mut self, db: &Db) -> API<()> {
|
async fn do_set_deleted(&mut self, db: &Db) -> Api<()> {
|
||||||
update!(*self, posts, db, { is_deleted, to true });
|
update!(*self, posts, db, { is_deleted, to true });
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rocket::async_trait]
|
#[rocket::async_trait]
|
||||||
impl UGC for Comment {
|
impl Ugc for Comment {
|
||||||
fn get_author_hash(&self) -> &str {
|
fn get_author_hash(&self) -> &str {
|
||||||
&self.author_hash
|
&self.author_hash
|
||||||
}
|
}
|
||||||
@@ -243,7 +243,7 @@ impl UGC for Comment {
|
|||||||
fn extra_delete_condition(&self) -> bool {
|
fn extra_delete_condition(&self) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
async fn do_set_deleted(&mut self, db: &Db) -> API<()> {
|
async fn do_set_deleted(&mut self, db: &Db) -> Api<()> {
|
||||||
update!(*self, comments, db, { is_deleted, to true });
|
update!(*self, comments, db, { is_deleted, to true });
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::api::{APIError, CurrentUser, JsonAPI, PolicyError::*, UGC};
|
use crate::api::{ApiError, CurrentUser, JsonApi, PolicyError::*, Ugc};
|
||||||
use crate::cache::*;
|
use crate::cache::*;
|
||||||
use crate::db_conn::Db;
|
use crate::db_conn::Db;
|
||||||
use crate::libs::diesel_logger::LoggingConnection;
|
use crate::libs::diesel_logger::LoggingConnection;
|
||||||
@@ -20,7 +20,7 @@ pub struct DeleteInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[post("/delete", data = "<di>")]
|
#[post("/delete", data = "<di>")]
|
||||||
pub async fn delete(di: Form<DeleteInput>, user: CurrentUser, db: Db, rconn: RdsConn) -> JsonAPI {
|
pub async fn delete(di: Form<DeleteInput>, user: CurrentUser, db: Db, rconn: RdsConn) -> JsonApi {
|
||||||
let (author_hash, p) = match di.id_type.as_str() {
|
let (author_hash, p) = match di.id_type.as_str() {
|
||||||
"cid" => {
|
"cid" => {
|
||||||
let mut c = Comment::get(&db, di.id).await?;
|
let mut c = Comment::get(&db, di.id).await?;
|
||||||
@@ -98,7 +98,7 @@ pub struct ReportInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[post("/report", data = "<ri>")]
|
#[post("/report", data = "<ri>")]
|
||||||
pub async fn report(ri: Form<ReportInput>, user: CurrentUser, db: Db, rconn: RdsConn) -> JsonAPI {
|
pub async fn report(ri: Form<ReportInput>, user: CurrentUser, db: Db, rconn: RdsConn) -> JsonApi {
|
||||||
// 临时用户不允许举报
|
// 临时用户不允许举报
|
||||||
user.id.ok_or(NotAllowed)?;
|
user.id.ok_or(NotAllowed)?;
|
||||||
|
|
||||||
@@ -154,10 +154,10 @@ pub struct BlockInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[post("/block", data = "<bi>")]
|
#[post("/block", data = "<bi>")]
|
||||||
pub async fn block(bi: Form<BlockInput>, user: CurrentUser, db: Db, rconn: RdsConn) -> JsonAPI {
|
pub async fn block(bi: Form<BlockInput>, user: CurrentUser, db: Db, rconn: RdsConn) -> JsonApi {
|
||||||
user.id.ok_or_else(|| NotAllowed)?;
|
user.id.ok_or(NotAllowed)?;
|
||||||
|
|
||||||
let mut blk = BlockedUsers::init(user.id.ok_or_else(|| NotAllowed)?, &rconn);
|
let mut blk = BlockedUsers::init(user.id.ok_or(NotAllowed)?, &rconn);
|
||||||
|
|
||||||
let pid;
|
let pid;
|
||||||
let nh_to_block = match bi.content_type.as_str() {
|
let nh_to_block = match bi.content_type.as_str() {
|
||||||
@@ -171,7 +171,7 @@ pub async fn block(bi: Form<BlockInput>, user: CurrentUser, db: Db, rconn: RdsCo
|
|||||||
pid = c.post_id;
|
pid = c.post_id;
|
||||||
c.author_hash
|
c.author_hash
|
||||||
}
|
}
|
||||||
_ => return Err(APIError::PcError(NotAllowed)),
|
_ => return Err(ApiError::Pc(NotAllowed)),
|
||||||
};
|
};
|
||||||
|
|
||||||
if nh_to_block.eq(&user.namehash) {
|
if nh_to_block.eq(&user.namehash) {
|
||||||
@@ -203,7 +203,7 @@ pub struct TitleInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[post("/title", data = "<ti>")]
|
#[post("/title", data = "<ti>")]
|
||||||
pub async fn set_title(ti: Form<TitleInput>, user: CurrentUser, rconn: RdsConn) -> JsonAPI {
|
pub async fn set_title(ti: Form<TitleInput>, user: CurrentUser, rconn: RdsConn) -> JsonApi {
|
||||||
if CustomTitle::set(&rconn, &user.namehash, &ti.title).await? {
|
if CustomTitle::set(&rconn, &user.namehash, &ti.title).await? {
|
||||||
code0!()
|
code0!()
|
||||||
} else {
|
} else {
|
||||||
@@ -221,7 +221,7 @@ pub async fn set_auto_block(
|
|||||||
ai: Form<AutoBlockInput>,
|
ai: Form<AutoBlockInput>,
|
||||||
user: CurrentUser,
|
user: CurrentUser,
|
||||||
rconn: RdsConn,
|
rconn: RdsConn,
|
||||||
) -> JsonAPI {
|
) -> JsonApi {
|
||||||
AutoBlockRank::set(&rconn, &user.namehash, ai.rank).await?;
|
AutoBlockRank::set(&rconn, &user.namehash, ai.rank).await?;
|
||||||
code0!()
|
code0!()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use crate::api::comment::{c2output, CommentOutput};
|
use crate::api::comment::{c2output, CommentOutput};
|
||||||
use crate::api::vote::get_poll_dict;
|
use crate::api::vote::get_poll_dict;
|
||||||
use crate::api::{CurrentUser, JsonAPI, PolicyError::*, API, UGC};
|
use crate::api::{CurrentUser, JsonApi, PolicyError::*, Api, Ugc};
|
||||||
use crate::cache::*;
|
use crate::cache::*;
|
||||||
use crate::db_conn::Db;
|
use crate::db_conn::Db;
|
||||||
use crate::libs::diesel_logger::LoggingConnection;
|
use crate::libs::diesel_logger::LoggingConnection;
|
||||||
@@ -63,7 +63,7 @@ pub struct CwInput {
|
|||||||
cw: String,
|
cw: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn p2output(p: &Post, user: &CurrentUser, db: &Db, rconn: &RdsConn) -> API<PostOutput> {
|
async fn p2output(p: &Post, user: &CurrentUser, db: &Db, rconn: &RdsConn) -> Api<PostOutput> {
|
||||||
let comments: Option<Vec<Comment>> = if p.n_comments < 5 {
|
let comments: Option<Vec<Comment>> = if p.n_comments < 5 {
|
||||||
Some(p.get_comments(db, rconn).await?)
|
Some(p.get_comments(db, rconn).await?)
|
||||||
} else {
|
} else {
|
||||||
@@ -74,10 +74,10 @@ async fn p2output(p: &Post, user: &CurrentUser, db: &Db, rconn: &RdsConn) -> API
|
|||||||
.flatten()
|
.flatten()
|
||||||
.map(|c| &c.author_hash)
|
.map(|c| &c.author_hash)
|
||||||
.chain(std::iter::once(&p.author_hash))
|
.chain(std::iter::once(&p.author_hash))
|
||||||
.collect();
|
.collect::<Vec<_>>();
|
||||||
//dbg!(&hash_list);
|
//dbg!(&hash_list);
|
||||||
let cached_block_dict = BlockDictCache::init(&user.namehash, p.id, rconn)
|
let cached_block_dict = BlockDictCache::init(&user.namehash, p.id, rconn)
|
||||||
.get_or_create(&user, &hash_list)
|
.get_or_create(user, &hash_list)
|
||||||
.await?;
|
.await?;
|
||||||
let is_blocked = cached_block_dict[&p.author_hash];
|
let is_blocked = cached_block_dict[&p.author_hash];
|
||||||
let can_view =
|
let can_view =
|
||||||
@@ -100,9 +100,9 @@ async fn p2output(p: &Post, user: &CurrentUser, db: &Db, rconn: &RdsConn) -> API
|
|||||||
)
|
)
|
||||||
.await,
|
.await,
|
||||||
can_del: p.check_permission(user, "wd").is_ok(),
|
can_del: p.check_permission(user, "wd").is_ok(),
|
||||||
attention: Attention::init(&user.namehash, &rconn).has(p.id).await?,
|
attention: Attention::init(&user.namehash, rconn).has(p.id).await?,
|
||||||
hot_score: user.is_admin.then(|| p.hot_score),
|
hot_score: user.is_admin.then(|| p.hot_score),
|
||||||
is_blocked: is_blocked,
|
is_blocked,
|
||||||
blocked_count: if user.is_admin {
|
blocked_count: if user.is_admin {
|
||||||
BlockCounter::get_count(rconn, &p.author_hash).await?
|
BlockCounter::get_count(rconn, &p.author_hash).await?
|
||||||
} else {
|
} else {
|
||||||
@@ -122,20 +122,20 @@ async fn p2output(p: &Post, user: &CurrentUser, db: &Db, rconn: &RdsConn) -> API
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn ps2outputs(
|
pub async fn ps2outputs(
|
||||||
ps: &Vec<Post>,
|
ps: &[Post],
|
||||||
user: &CurrentUser,
|
user: &CurrentUser,
|
||||||
db: &Db,
|
db: &Db,
|
||||||
rconn: &RdsConn,
|
rconn: &RdsConn,
|
||||||
) -> API<Vec<PostOutput>> {
|
) -> Api<Vec<PostOutput>> {
|
||||||
future::try_join_all(
|
future::try_join_all(
|
||||||
ps.iter()
|
ps.iter()
|
||||||
.map(|p| async { Ok(p2output(p, &user, &db, &rconn).await?) }),
|
.map(|p| async { p2output(p, user, db, rconn).await }),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/getone?<pid>")]
|
#[get("/getone?<pid>")]
|
||||||
pub async fn get_one(pid: i32, user: CurrentUser, db: Db, rconn: RdsConn) -> JsonAPI {
|
pub async fn get_one(pid: i32, user: CurrentUser, db: Db, rconn: RdsConn) -> JsonApi {
|
||||||
let p = Post::get(&db, &rconn, pid).await?;
|
let p = Post::get(&db, &rconn, pid).await?;
|
||||||
p.check_permission(&user, "ro")?;
|
p.check_permission(&user, "ro")?;
|
||||||
Ok(json!({
|
Ok(json!({
|
||||||
@@ -151,8 +151,8 @@ pub async fn get_list(
|
|||||||
user: CurrentUser,
|
user: CurrentUser,
|
||||||
db: Db,
|
db: Db,
|
||||||
rconn: RdsConn,
|
rconn: RdsConn,
|
||||||
) -> JsonAPI {
|
) -> JsonApi {
|
||||||
user.id.ok_or_else(|| YouAreTmp)?;
|
user.id.ok_or(YouAreTmp)?;
|
||||||
let page = p.unwrap_or(1);
|
let page = p.unwrap_or(1);
|
||||||
let page_size = 25;
|
let page_size = 25;
|
||||||
let start = (page - 1) * page_size;
|
let start = (page - 1) * page_size;
|
||||||
@@ -173,7 +173,7 @@ pub async fn publish_post(
|
|||||||
user: CurrentUser,
|
user: CurrentUser,
|
||||||
db: Db,
|
db: Db,
|
||||||
rconn: RdsConn,
|
rconn: RdsConn,
|
||||||
) -> JsonAPI {
|
) -> JsonApi {
|
||||||
let p = Post::create(
|
let p = Post::create(
|
||||||
&db,
|
&db,
|
||||||
NewPost {
|
NewPost {
|
||||||
@@ -199,7 +199,7 @@ pub async fn publish_post(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[post("/editcw", data = "<cwi>")]
|
#[post("/editcw", data = "<cwi>")]
|
||||||
pub async fn edit_cw(cwi: Form<CwInput>, user: CurrentUser, db: Db, rconn: RdsConn) -> JsonAPI {
|
pub async fn edit_cw(cwi: Form<CwInput>, user: CurrentUser, db: Db, rconn: RdsConn) -> JsonApi {
|
||||||
let mut p = Post::get(&db, &rconn, cwi.pid).await?;
|
let mut p = Post::get(&db, &rconn, cwi.pid).await?;
|
||||||
p.check_permission(&user, "w")?;
|
p.check_permission(&user, "w")?;
|
||||||
update!(p, posts, &db, { cw, to cwi.cw.to_string() });
|
update!(p, posts, &db, { cw, to cwi.cw.to_string() });
|
||||||
@@ -208,8 +208,8 @@ pub async fn edit_cw(cwi: Form<CwInput>, user: CurrentUser, db: Db, rconn: RdsCo
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[get("/getmulti?<pids>")]
|
#[get("/getmulti?<pids>")]
|
||||||
pub async fn get_multi(pids: Vec<i32>, user: CurrentUser, db: Db, rconn: RdsConn) -> JsonAPI {
|
pub async fn get_multi(pids: Vec<i32>, user: CurrentUser, db: Db, rconn: RdsConn) -> JsonApi {
|
||||||
user.id.ok_or_else(|| YouAreTmp)?;
|
user.id.ok_or(YouAreTmp)?;
|
||||||
let ps = Post::get_multi(&db, &rconn, &pids).await?;
|
let ps = Post::get_multi(&db, &rconn, &pids).await?;
|
||||||
let ps_data = ps2outputs(&ps, &user, &db, &rconn).await?;
|
let ps_data = ps2outputs(&ps, &user, &db, &rconn).await?;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use crate::api::post::ps2outputs;
|
use crate::api::post::ps2outputs;
|
||||||
use crate::api::{CurrentUser, JsonAPI, PolicyError::*};
|
use crate::api::{CurrentUser, JsonApi, PolicyError::*};
|
||||||
use crate::db_conn::Db;
|
use crate::db_conn::Db;
|
||||||
use crate::models::*;
|
use crate::models::*;
|
||||||
use crate::rds_conn::RdsConn;
|
use crate::rds_conn::RdsConn;
|
||||||
@@ -13,17 +13,13 @@ pub async fn search(
|
|||||||
user: CurrentUser,
|
user: CurrentUser,
|
||||||
db: Db,
|
db: Db,
|
||||||
rconn: RdsConn,
|
rconn: RdsConn,
|
||||||
) -> JsonAPI {
|
) -> JsonApi {
|
||||||
user.id.ok_or_else(|| YouAreTmp)?;
|
user.id.ok_or(YouAreTmp)?;
|
||||||
|
|
||||||
let page_size = 25;
|
let page_size = 25;
|
||||||
let start = (page - 1) * page_size;
|
let start = (page - 1) * page_size;
|
||||||
|
|
||||||
let kws = keywords
|
let ps = if !keywords.chars().any(|c| !c.eq(&' ')) {
|
||||||
.split(" ")
|
|
||||||
.filter(|x| !x.is_empty())
|
|
||||||
.collect::<Vec<&str>>();
|
|
||||||
let ps = if kws.is_empty() {
|
|
||||||
vec![]
|
vec![]
|
||||||
} else {
|
} else {
|
||||||
Post::search(
|
Post::search(
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
use crate::api::{CurrentUser, JsonAPI};
|
use crate::api::{CurrentUser, JsonApi};
|
||||||
use crate::random_hasher::RandomHasher;
|
use crate::random_hasher::RandomHasher;
|
||||||
use crate::rds_conn::RdsConn;
|
use crate::rds_conn::RdsConn;
|
||||||
use crate::rds_models::{Systemlog};
|
use crate::rds_models::Systemlog;
|
||||||
use rocket::serde::json::{json, Value};
|
use rocket::serde::json::{json, Value};
|
||||||
use rocket::State;
|
use rocket::State;
|
||||||
|
|
||||||
#[get("/systemlog")]
|
#[get("/systemlog")]
|
||||||
pub async fn get_systemlog(user: CurrentUser, rh: &State<RandomHasher>, rconn: RdsConn) -> JsonAPI {
|
pub async fn get_systemlog(user: CurrentUser, rh: &State<RandomHasher>, rconn: RdsConn) -> JsonApi {
|
||||||
let logs = Systemlog::get_list(&rconn, 50).await?;
|
let logs = Systemlog::get_list(&rconn, 50).await?;
|
||||||
|
|
||||||
Ok(json!({
|
Ok(json!({
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
use crate::api::{CurrentUser, JsonAPI};
|
use crate::api::{CurrentUser, JsonApi};
|
||||||
use rocket::fs::TempFile;
|
use rocket::fs::TempFile;
|
||||||
use rocket::serde::json::json;
|
use rocket::serde::json::json;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
|
||||||
#[post("/upload", data = "<file>")]
|
#[post("/upload", data = "<file>")]
|
||||||
pub async fn ipfs_upload(_user: CurrentUser, file: TempFile<'_>) -> JsonAPI {
|
pub async fn ipfs_upload(_user: CurrentUser, file: TempFile<'_>) -> JsonApi {
|
||||||
// dbg!(&file);
|
// dbg!(&file);
|
||||||
|
|
||||||
// dbg!(&file.path());
|
// dbg!(&file.path());
|
||||||
@@ -21,7 +21,7 @@ pub async fn ipfs_upload(_user: CurrentUser, file: TempFile<'_>) -> JsonAPI {
|
|||||||
// dbg!(&output);
|
// dbg!(&output);
|
||||||
let hash = std::str::from_utf8(&output.stdout)
|
let hash = std::str::from_utf8(&output.stdout)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.split_terminator("\n")
|
.split_terminator('\n')
|
||||||
.last()
|
.last()
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
dbg!(&output);
|
dbg!(&output);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::api::{CurrentUser, JsonAPI, PolicyError::*};
|
use crate::api::{CurrentUser, JsonApi, PolicyError::*};
|
||||||
use crate::rds_conn::RdsConn;
|
use crate::rds_conn::RdsConn;
|
||||||
use crate::rds_models::*;
|
use crate::rds_models::*;
|
||||||
use rocket::form::Form;
|
use rocket::form::Form;
|
||||||
@@ -22,7 +22,7 @@ pub async fn get_poll_dict(pid: i32, rconn: &RdsConn, namehash: &str) -> Option<
|
|||||||
}))
|
}))
|
||||||
.await
|
.await
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|x| x)
|
.flatten()
|
||||||
.collect::<Vec<&String>>()
|
.collect::<Vec<&String>>()
|
||||||
.pop();
|
.pop();
|
||||||
Some(json!({
|
Some(json!({
|
||||||
@@ -46,8 +46,8 @@ pub struct VoteInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[post("/vote", data = "<vi>")]
|
#[post("/vote", data = "<vi>")]
|
||||||
pub async fn vote(vi: Form<VoteInput>, user: CurrentUser, rconn: RdsConn) -> JsonAPI {
|
pub async fn vote(vi: Form<VoteInput>, user: CurrentUser, rconn: RdsConn) -> JsonApi {
|
||||||
user.id.ok_or_else(|| NotAllowed)?;
|
user.id.ok_or(NotAllowed)?;
|
||||||
|
|
||||||
let pid = vi.pid;
|
let pid = vi.pid;
|
||||||
let opts = PollOption::init(pid, &rconn).get_list().await?;
|
let opts = PollOption::init(pid, &rconn).get_list().await?;
|
||||||
@@ -61,10 +61,7 @@ pub async fn vote(vi: Form<VoteInput>, user: CurrentUser, rconn: RdsConn) -> Jso
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let idx: usize = opts
|
let idx: usize = opts.iter().position(|x| x.eq(&vi.vote)).ok_or(NotAllowed)?;
|
||||||
.iter()
|
|
||||||
.position(|x| x.eq(&vi.vote))
|
|
||||||
.ok_or_else(|| NotAllowed)?;
|
|
||||||
|
|
||||||
PollVote::init(pid, idx, &rconn).add(&user.namehash).await?;
|
PollVote::init(pid, idx, &rconn).add(&user.namehash).await?;
|
||||||
|
|
||||||
|
|||||||
12
src/cache.rs
12
src/cache.rs
@@ -28,7 +28,7 @@ pub struct PostCache {
|
|||||||
impl PostCache {
|
impl PostCache {
|
||||||
init!();
|
init!();
|
||||||
|
|
||||||
pub async fn sets(&mut self, ps: &Vec<&Post>) {
|
pub async fn sets(&mut self, ps: &[&Post]) {
|
||||||
if ps.is_empty() {
|
if ps.is_empty() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -61,7 +61,7 @@ impl PostCache {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn gets(&mut self, pids: &Vec<i32>) -> Vec<Option<Post>> {
|
pub async fn gets(&mut self, pids: &[i32]) -> Vec<Option<Post>> {
|
||||||
// 长度为1时会走GET而非MGET,返回值格式不兼容。愚蠢的设计。
|
// 长度为1时会走GET而非MGET,返回值格式不兼容。愚蠢的设计。
|
||||||
match pids.len() {
|
match pids.len() {
|
||||||
0 => vec![],
|
0 => vec![],
|
||||||
@@ -128,7 +128,7 @@ pub struct PostCommentCache {
|
|||||||
impl PostCommentCache {
|
impl PostCommentCache {
|
||||||
init!(i32, "hole_v2:cache:post_comments:{}");
|
init!(i32, "hole_v2:cache:post_comments:{}");
|
||||||
|
|
||||||
pub async fn set(&mut self, cs: &Vec<Comment>) {
|
pub async fn set(&mut self, cs: &[Comment]) {
|
||||||
self.rconn
|
self.rconn
|
||||||
.set_ex(
|
.set_ex(
|
||||||
&self.key,
|
&self.key,
|
||||||
@@ -183,7 +183,7 @@ impl PostListCommentCache {
|
|||||||
pub fn init(mode: u8, rconn: &RdsConn) -> Self {
|
pub fn init(mode: u8, rconn: &RdsConn) -> Self {
|
||||||
Self {
|
Self {
|
||||||
key: format!("hole_v2:cache:post_list:{}", &mode),
|
key: format!("hole_v2:cache:post_list:{}", &mode),
|
||||||
mode: mode,
|
mode,
|
||||||
rconn: rconn.clone(),
|
rconn: rconn.clone(),
|
||||||
length: 0,
|
length: 0,
|
||||||
}
|
}
|
||||||
@@ -229,7 +229,7 @@ impl PostListCommentCache {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn fill(&mut self, ps: &Vec<Post>) {
|
pub async fn fill(&mut self, ps: &[Post]) {
|
||||||
let items: Vec<(i64, i32)> = ps.iter().map(|p| self.p2pair(p)).collect();
|
let items: Vec<(i64, i32)> = ps.iter().map(|p| self.p2pair(p)).collect();
|
||||||
self.rconn
|
self.rconn
|
||||||
.zadd_multiple(&self.key, &items)
|
.zadd_multiple(&self.key, &items)
|
||||||
@@ -337,7 +337,7 @@ impl BlockDictCache {
|
|||||||
pub async fn get_or_create(
|
pub async fn get_or_create(
|
||||||
&mut self,
|
&mut self,
|
||||||
user: &CurrentUser,
|
user: &CurrentUser,
|
||||||
hash_list: &Vec<&String>,
|
hash_list: &[&String],
|
||||||
) -> RedisResult<HashMap<String, bool>> {
|
) -> RedisResult<HashMap<String, bool>> {
|
||||||
let mut block_dict = self
|
let mut block_dict = self
|
||||||
.rconn
|
.rconn
|
||||||
|
|||||||
11
src/cors.rs
11
src/cors.rs
@@ -3,12 +3,12 @@ use rocket::http::Header;
|
|||||||
use rocket::{Request, Response};
|
use rocket::{Request, Response};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
pub struct CORS {
|
pub struct Cors {
|
||||||
pub whitelist: Vec<String>,
|
pub whitelist: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rocket::async_trait]
|
#[rocket::async_trait]
|
||||||
impl Fairing for CORS {
|
impl Fairing for Cors {
|
||||||
fn info(&self) -> Info {
|
fn info(&self) -> Info {
|
||||||
Info {
|
Info {
|
||||||
name: "Add CORS headers to responses",
|
name: "Add CORS headers to responses",
|
||||||
@@ -17,11 +17,11 @@ impl Fairing for CORS {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn on_response<'r>(&self, request: &'r Request<'_>, response: &mut Response<'r>) {
|
async fn on_response<'r>(&self, request: &'r Request<'_>, response: &mut Response<'r>) {
|
||||||
request
|
if let Some(origin) = request
|
||||||
.headers()
|
.headers()
|
||||||
.get_one("Origin")
|
.get_one("Origin")
|
||||||
.and_then(|origin| self.whitelist.contains(&origin.to_string()).then(|| origin))
|
.and_then(|origin| self.whitelist.contains(&origin.to_string()).then(|| origin))
|
||||||
.and_then(|origin| {
|
{
|
||||||
response.set_header(Header::new("Access-Control-Allow-Origin", origin));
|
response.set_header(Header::new("Access-Control-Allow-Origin", origin));
|
||||||
response.set_header(Header::new(
|
response.set_header(Header::new(
|
||||||
"Access-Control-Allow-Methods",
|
"Access-Control-Allow-Methods",
|
||||||
@@ -32,8 +32,7 @@ impl Fairing for CORS {
|
|||||||
"Access-Control-Allow-Headers",
|
"Access-Control-Allow-Headers",
|
||||||
"User-Token, Content-Type",
|
"User-Token, Content-Type",
|
||||||
));
|
));
|
||||||
Some(())
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use rocket_sync_db_pools::{database, diesel};
|
|
||||||
use diesel::Connection;
|
use diesel::Connection;
|
||||||
|
use rocket_sync_db_pools::{database, diesel};
|
||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
pub type Conn = diesel::pg::PgConnection;
|
pub type Conn = diesel::pg::PgConnection;
|
||||||
@@ -7,11 +7,9 @@ pub type Conn = diesel::pg::PgConnection;
|
|||||||
#[database("pg_v2")]
|
#[database("pg_v2")]
|
||||||
pub struct Db(Conn);
|
pub struct Db(Conn);
|
||||||
|
|
||||||
|
|
||||||
// get sync connection, only for annealing
|
// get sync connection, only for annealing
|
||||||
pub fn establish_connection() -> Conn {
|
pub fn establish_connection() -> Conn {
|
||||||
let database_url = env::var("DATABASE_URL")
|
let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
|
||||||
.expect("DATABASE_URL must be set");
|
|
||||||
Conn::establish(&database_url)
|
Conn::establish(&database_url)
|
||||||
.expect(&format!("Error connecting to {}", database_url))
|
.unwrap_or_else(|_| panic!("Error connecting to {}", database_url))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ async fn main() -> Result<(), rocket::Error> {
|
|||||||
.manage(RandomHasher::get_random_one())
|
.manage(RandomHasher::get_random_one())
|
||||||
.manage(rmc)
|
.manage(rmc)
|
||||||
.attach(Db::fairing())
|
.attach(Db::fairing())
|
||||||
.attach(cors::CORS {
|
.attach(cors::Cors {
|
||||||
whitelist: env::var("FRONTEND_WHITELIST")
|
whitelist: env::var("FRONTEND_WHITELIST")
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
.split(',')
|
.split(',')
|
||||||
|
|||||||
@@ -171,7 +171,7 @@ impl Post {
|
|||||||
let missing_ps = Self::_get_multi(db, missing_ids).await?;
|
let missing_ps = Self::_get_multi(db, missing_ids).await?;
|
||||||
// dbg!(&missing_ps);
|
// dbg!(&missing_ps);
|
||||||
|
|
||||||
cacher.sets(&missing_ps.iter().collect()).await;
|
cacher.sets(&missing_ps.iter().collect::<Vec<_>>()).await;
|
||||||
|
|
||||||
for p in missing_ps.into_iter() {
|
for p in missing_ps.into_iter() {
|
||||||
if let Some(op) = id2po.get_mut(&p.id) {
|
if let Some(op) = id2po.get_mut(&p.id) {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use redis::aio::MultiplexedConnection;
|
use redis::aio::MultiplexedConnection;
|
||||||
use rocket::request::{FromRequest, Outcome, Request};
|
use rocket::request::{FromRequest, Outcome, Request};
|
||||||
use std::ops::{Deref, DerefMut};
|
|
||||||
use std::env;
|
use std::env;
|
||||||
|
use std::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
pub struct RdsConn(pub MultiplexedConnection);
|
pub struct RdsConn(pub MultiplexedConnection);
|
||||||
|
|
||||||
@@ -34,7 +34,6 @@ impl DerefMut for RdsConn {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub async fn init_rds_client() -> MultiplexedConnection {
|
pub async fn init_rds_client() -> MultiplexedConnection {
|
||||||
let redis_url = env::var("REDIS_URL").expect("REDIS_URL must be set");
|
let redis_url = env::var("REDIS_URL").expect("REDIS_URL must be set");
|
||||||
let client = redis::Client::open(redis_url).expect("connect to redis fail");
|
let client = redis::Client::open(redis_url).expect("connect to redis fail");
|
||||||
|
|||||||
@@ -284,10 +284,10 @@ impl PollVote {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn clear_outdate_redis_data(rconn: &RdsConn) {
|
pub async fn clear_outdate_redis_data(rconn: &RdsConn) {
|
||||||
BannedUsers::clear(&rconn).await.unwrap();
|
BannedUsers::clear(rconn).await.unwrap();
|
||||||
CustomTitle::clear(&rconn).await.unwrap();
|
CustomTitle::clear(rconn).await.unwrap();
|
||||||
AutoBlockRank::clear(&rconn).await.unwrap();
|
AutoBlockRank::clear(rconn).await.unwrap();
|
||||||
Attention::clear_all(&rconn).await;
|
Attention::clear_all(rconn).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) use init;
|
pub(crate) use init;
|
||||||
|
|||||||
@@ -42,8 +42,4 @@ table! {
|
|||||||
|
|
||||||
joinable!(comments -> posts (post_id));
|
joinable!(comments -> posts (post_id));
|
||||||
|
|
||||||
allow_tables_to_appear_in_same_query!(
|
allow_tables_to_appear_in_same_query!(comments, posts, users,);
|
||||||
comments,
|
|
||||||
posts,
|
|
||||||
users,
|
|
||||||
);
|
|
||||||
|
|||||||
Reference in New Issue
Block a user