feat: support upload files & adjust output
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,6 +1,9 @@
|
|||||||
# --> sqlite3
|
# --> sqlite3
|
||||||
*.db
|
*.db
|
||||||
|
|
||||||
|
# user files
|
||||||
|
/user_files
|
||||||
|
|
||||||
# ---> Rust
|
# ---> Rust
|
||||||
# Generated by Cargo
|
# Generated by Cargo
|
||||||
# will have compiled files and executables
|
# will have compiled files and executables
|
||||||
|
|||||||
2
Rocket.toml
Normal file
2
Rocket.toml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
[default]
|
||||||
|
limits = { file = "200MB", files = "200MB" }
|
||||||
@@ -5,7 +5,6 @@ use crate::models::*;
|
|||||||
use crate::rds_conn::RdsConn;
|
use crate::rds_conn::RdsConn;
|
||||||
use crate::rds_models::*;
|
use crate::rds_models::*;
|
||||||
use crate::schema;
|
use crate::schema;
|
||||||
use chrono::{offset::Utc, DateTime};
|
|
||||||
use diesel::{ExpressionMethods, QueryDsl, RunQueryDsl};
|
use diesel::{ExpressionMethods, QueryDsl, RunQueryDsl};
|
||||||
use rocket::form::Form;
|
use rocket::form::Form;
|
||||||
use rocket::futures::future;
|
use rocket::futures::future;
|
||||||
@@ -30,7 +29,7 @@ pub struct CommentOutput {
|
|||||||
can_del: bool,
|
can_del: bool,
|
||||||
name_id: i32,
|
name_id: i32,
|
||||||
is_tmp: bool,
|
is_tmp: bool,
|
||||||
create_time: DateTime<Utc>,
|
create_time: i64,
|
||||||
is_blocked: bool,
|
is_blocked: bool,
|
||||||
blocked_count: Option<i32>,
|
blocked_count: Option<i32>,
|
||||||
// for old version frontend
|
// for old version frontend
|
||||||
@@ -61,19 +60,16 @@ pub async fn c2output<'r>(
|
|||||||
BlockedUsers::check_blocked(rconn, user.id, &user.namehash, &c.author_hash)
|
BlockedUsers::check_blocked(rconn, user.id, &user.namehash, &c.author_hash)
|
||||||
.await
|
.await
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
let can_view = !is_blocked && user.id.is_some() || user.namehash.eq(&c.author_hash);
|
let can_view = user.is_admin
|
||||||
|
|| (!is_blocked && user.id.is_some() || user.namehash.eq(&c.author_hash));
|
||||||
Some(CommentOutput {
|
Some(CommentOutput {
|
||||||
cid: c.id,
|
cid: c.id,
|
||||||
text: format!(
|
text: (if can_view { &c.content } else { "" }).to_string(),
|
||||||
"{}{}",
|
|
||||||
if c.is_tmp { "[tmp]\n" } else { "" },
|
|
||||||
if can_view { &c.content } else { "" }
|
|
||||||
),
|
|
||||||
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: name_id,
|
||||||
is_tmp: c.is_tmp,
|
is_tmp: c.is_tmp,
|
||||||
create_time: c.create_time,
|
create_time: c.create_time.timestamp(),
|
||||||
is_blocked: 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).await.ok()
|
BlockCounter::get_count(rconn, &c.author_hash).await.ok()
|
||||||
|
|||||||
@@ -25,6 +25,13 @@ macro_rules! code0 {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! e2s {
|
||||||
|
($e:expr) => (json!({
|
||||||
|
"code": -1,
|
||||||
|
"msg": $e.to_string()
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
#[catch(401)]
|
#[catch(401)]
|
||||||
pub fn catch_401_error() -> &'static str {
|
pub fn catch_401_error() -> &'static str {
|
||||||
"未登录或token过期"
|
"未登录或token过期"
|
||||||
@@ -100,21 +107,15 @@ pub enum APIError {
|
|||||||
DbError(diesel::result::Error),
|
DbError(diesel::result::Error),
|
||||||
RdsError(redis::RedisError),
|
RdsError(redis::RedisError),
|
||||||
PcError(PolicyError),
|
PcError(PolicyError),
|
||||||
|
IoError(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) => json!({
|
APIError::DbError(e) => e2s!(e).respond_to(req),
|
||||||
"code": -1,
|
APIError::RdsError(e) => e2s!(e).respond_to(req),
|
||||||
"msg": e.to_string()
|
APIError::IoError(e) => e2s!(e).respond_to(req),
|
||||||
})
|
|
||||||
.respond_to(req),
|
|
||||||
APIError::RdsError(e) => json!({
|
|
||||||
"code": -1,
|
|
||||||
"msg": e.to_string()
|
|
||||||
})
|
|
||||||
.respond_to(req),
|
|
||||||
APIError::PcError(e) => json!({
|
APIError::PcError(e) => json!({
|
||||||
"code": -1,
|
"code": -1,
|
||||||
"msg": match e {
|
"msg": match e {
|
||||||
@@ -142,6 +143,12 @@ impl From<redis::RedisError> for APIError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<std::io::Error> for APIError {
|
||||||
|
fn from(err: std::io::Error) -> APIError {
|
||||||
|
APIError::IoError(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::PcError(err)
|
||||||
@@ -237,4 +244,5 @@ pub mod operation;
|
|||||||
pub mod post;
|
pub mod post;
|
||||||
pub mod search;
|
pub mod search;
|
||||||
pub mod systemlog;
|
pub mod systemlog;
|
||||||
|
pub mod upload;
|
||||||
pub mod vote;
|
pub mod vote;
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
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, UGC, PolicyError::*};
|
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::*;
|
||||||
use crate::rds_conn::RdsConn;
|
use crate::rds_conn::RdsConn;
|
||||||
use crate::rds_models::*;
|
use crate::rds_models::*;
|
||||||
use crate::schema;
|
use crate::schema;
|
||||||
use chrono::{offset::Utc, DateTime};
|
|
||||||
use diesel::{ExpressionMethods, QueryDsl, RunQueryDsl};
|
use diesel::{ExpressionMethods, QueryDsl, RunQueryDsl};
|
||||||
use rocket::form::Form;
|
use rocket::form::Form;
|
||||||
use rocket::futures::future;
|
use rocket::futures::future;
|
||||||
@@ -38,8 +37,8 @@ pub struct PostOutput {
|
|||||||
is_tmp: bool,
|
is_tmp: bool,
|
||||||
n_attentions: i32,
|
n_attentions: i32,
|
||||||
n_comments: i32,
|
n_comments: i32,
|
||||||
create_time: DateTime<Utc>,
|
create_time: i64,
|
||||||
last_comment_time: DateTime<Utc>,
|
last_comment_time: i64,
|
||||||
allow_search: bool,
|
allow_search: bool,
|
||||||
is_reported: Option<bool>,
|
is_reported: Option<bool>,
|
||||||
comments: Option<Vec<CommentOutput>>,
|
comments: Option<Vec<CommentOutput>>,
|
||||||
@@ -67,19 +66,16 @@ async fn p2output(p: &Post, user: &CurrentUser, db: &Db, rconn: &RdsConn) -> Pos
|
|||||||
let is_blocked = BlockedUsers::check_blocked(rconn, user.id, &user.namehash, &p.author_hash)
|
let is_blocked = BlockedUsers::check_blocked(rconn, user.id, &user.namehash, &p.author_hash)
|
||||||
.await
|
.await
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
let can_view = !is_blocked && user.id.is_some() || user.namehash.eq(&p.author_hash);
|
let can_view =
|
||||||
|
user.is_admin || (!is_blocked && user.id.is_some() || user.namehash.eq(&p.author_hash));
|
||||||
PostOutput {
|
PostOutput {
|
||||||
pid: p.id,
|
pid: p.id,
|
||||||
text: format!(
|
text: (if can_view { &p.content } else { "" }).to_string(),
|
||||||
"{}{}",
|
|
||||||
if p.is_tmp { "[tmp]\n" } else { "" },
|
|
||||||
if can_view { &p.content } else { "" }
|
|
||||||
),
|
|
||||||
cw: (!p.cw.is_empty()).then(|| p.cw.to_string()),
|
cw: (!p.cw.is_empty()).then(|| p.cw.to_string()),
|
||||||
n_attentions: p.n_attentions,
|
n_attentions: p.n_attentions,
|
||||||
n_comments: p.n_comments,
|
n_comments: p.n_comments,
|
||||||
create_time: p.create_time,
|
create_time: p.create_time.timestamp(),
|
||||||
last_comment_time: p.last_comment_time,
|
last_comment_time: p.last_comment_time.timestamp(),
|
||||||
allow_search: p.allow_search,
|
allow_search: p.allow_search,
|
||||||
author_title: (!p.author_title.is_empty()).then(|| p.author_title.to_string()),
|
author_title: (!p.author_title.is_empty()).then(|| p.author_title.to_string()),
|
||||||
is_tmp: p.is_tmp,
|
is_tmp: p.is_tmp,
|
||||||
|
|||||||
37
src/api/upload.rs
Normal file
37
src/api/upload.rs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
use crate::api::{CurrentUser, JsonAPI};
|
||||||
|
use rocket::form::Form;
|
||||||
|
use rocket::fs::TempFile;
|
||||||
|
use rocket::serde::json::json;
|
||||||
|
use std::fs;
|
||||||
|
use std::path::Path;
|
||||||
|
use std::process::Command;
|
||||||
|
|
||||||
|
#[derive(FromForm)]
|
||||||
|
pub struct Upload<'f> {
|
||||||
|
file: TempFile<'f>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[post("/upload", data = "<form>")]
|
||||||
|
pub async fn ipfs_upload(user: CurrentUser, mut form: Form<Upload<'_>>) -> JsonAPI {
|
||||||
|
let file_dir = Path::new("user_files").join(user.namehash);
|
||||||
|
fs::create_dir_all(&file_dir)?;
|
||||||
|
let file = &mut form.file;
|
||||||
|
// dbg!(&file);
|
||||||
|
let filename = file.name().unwrap_or("file").to_string()
|
||||||
|
+ "."
|
||||||
|
+ &file.content_type().map_or("", |ct| ct.sub().as_str());
|
||||||
|
file.persist_to(file_dir.with_file_name(&filename)).await?;
|
||||||
|
let output = Command::new("ipfs")
|
||||||
|
.args(["add", "-q", "-r", "-cid-version=1", "user_files"])
|
||||||
|
.output()?;
|
||||||
|
// dbg!(&output);
|
||||||
|
let hash = std::str::from_utf8(&output.stdout)
|
||||||
|
.unwrap()
|
||||||
|
.split_terminator("\n")
|
||||||
|
.last()
|
||||||
|
.unwrap();
|
||||||
|
code0!(json!({
|
||||||
|
"hash": hash,
|
||||||
|
"filename": filename,
|
||||||
|
}))
|
||||||
|
}
|
||||||
@@ -71,6 +71,7 @@ async fn main() -> Result<(), rocket::Error> {
|
|||||||
api::operation::set_title,
|
api::operation::set_title,
|
||||||
api::operation::block,
|
api::operation::block,
|
||||||
api::vote::vote,
|
api::vote::vote,
|
||||||
|
api::upload::ipfs_upload,
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
.mount(
|
.mount(
|
||||||
|
|||||||
Reference in New Issue
Block a user