jmserver/src/v1/routes.rs

213 lines
5.9 KiB
Rust
Raw Normal View History

2022-01-02 17:25:23 +01:00
use crate::ipfs::IPFSFile;
2022-01-08 20:57:53 +01:00
use crate::lib::ExtractIP;
2021-07-19 22:29:03 +02:00
use crate::v1::models::*;
2022-01-16 22:43:45 +01:00
use crate::JMService;
2022-01-08 20:57:53 +01:00
2022-01-11 19:42:15 +01:00
use axum::extract::{ContentLengthLimit, Extension, Multipart};
2021-12-29 18:33:31 +01:00
use axum::handler::{get, post};
2021-08-26 17:45:38 +02:00
use axum::response::IntoResponse;
2021-12-29 18:33:31 +01:00
use axum::routing::BoxRoute;
use axum::{Json, Router};
2022-01-08 20:57:53 +01:00
use hyper::StatusCode;
2021-12-29 18:33:31 +01:00
2022-01-11 19:42:15 +01:00
use super::Query;
2022-07-19 21:11:13 +02:00
use crate::error::APIError;
2022-01-02 17:25:23 +01:00
2021-12-29 18:33:31 +01:00
async fn meme(
2022-01-11 19:42:15 +01:00
Query(params): Query<MemeIDQuery>,
2022-01-16 22:43:45 +01:00
Extension(service): Extension<JMService>,
2022-01-02 17:25:23 +01:00
) -> Result<impl IntoResponse, APIError> {
2022-01-16 17:46:09 +01:00
let meme = V1Meme::new(
2022-07-19 21:11:13 +02:00
service
.get_meme(params.id)
2022-01-16 17:46:09 +01:00
.await?
.ok_or_else(|| APIError::NotFound("Meme not found".to_string()))?,
service.ext_cdn_url(),
2022-01-16 17:46:09 +01:00
);
2021-12-29 18:33:31 +01:00
Ok(Json(MemeResponse {
status: 200,
error: None,
meme: Some(meme),
}))
}
2021-07-19 22:29:03 +02:00
2021-12-29 18:33:31 +01:00
async fn memes(
2022-01-16 17:46:09 +01:00
Query(params): Query<MemeFilter>,
2022-01-16 22:43:45 +01:00
Extension(service): Extension<JMService>,
2022-01-02 17:25:23 +01:00
) -> Result<impl IntoResponse, APIError> {
2022-07-19 21:11:13 +02:00
let memes = service
.get_memes(params.into())
2022-01-16 17:46:09 +01:00
.await?
.into_iter()
.map(|meme| V1Meme::new(meme, service.ext_cdn_url()))
2022-01-16 17:46:09 +01:00
.collect();
2021-12-29 18:33:31 +01:00
Ok(Json(MemesResponse {
status: 200,
error: None,
memes: Some(memes),
}))
2021-07-19 22:29:03 +02:00
}
2021-12-29 18:33:31 +01:00
async fn category(
2022-01-11 19:42:15 +01:00
Query(params): Query<IDQuery>,
2022-07-19 21:11:13 +02:00
Extension(service): Extension<JMService>,
2022-01-02 17:25:23 +01:00
) -> Result<impl IntoResponse, APIError> {
2022-07-19 21:11:13 +02:00
let category = service
.get_category(&params.id)
2022-01-16 17:46:09 +01:00
.await?
.ok_or_else(|| APIError::NotFound("Category not found".to_string()))?;
2021-12-29 18:33:31 +01:00
Ok(Json(CategoryResponse {
status: 200,
error: None,
category: Some(category),
}))
2021-07-19 22:29:03 +02:00
}
2021-12-29 18:33:31 +01:00
async fn categories(
2022-07-19 21:11:13 +02:00
Extension(service): Extension<JMService>,
2022-01-02 17:25:23 +01:00
) -> Result<impl IntoResponse, APIError> {
2022-07-19 21:11:13 +02:00
let categories = service.get_categories().await?;
2021-12-29 18:33:31 +01:00
Ok(Json(CategoriesResponse {
status: 200,
error: None,
categories: Some(categories),
}))
2021-07-19 22:29:03 +02:00
}
2021-12-29 18:33:31 +01:00
async fn user(
2022-01-11 19:42:15 +01:00
Query(params): Query<UserIDQuery>,
2022-07-19 21:11:13 +02:00
Extension(service): Extension<JMService>,
2022-01-02 17:25:23 +01:00
) -> Result<impl IntoResponse, APIError> {
2022-07-19 21:11:13 +02:00
let user = service
.get_user(params.into())
2022-01-16 17:46:09 +01:00
.await?
.ok_or_else(|| APIError::NotFound("User not found".to_string()))?;
2021-12-29 18:33:31 +01:00
Ok(Json(UserResponse {
status: 200,
error: None,
user: Some(user),
}))
2021-07-19 22:29:03 +02:00
}
2022-07-19 21:11:13 +02:00
async fn users(Extension(service): Extension<JMService>) -> Result<impl IntoResponse, APIError> {
let users = service.get_users().await?;
2021-12-29 18:33:31 +01:00
Ok(Json(UsersResponse {
status: 200,
error: None,
users: Some(users),
}))
2021-07-19 22:29:03 +02:00
}
2021-12-29 18:33:31 +01:00
async fn random(
2022-01-16 17:46:09 +01:00
Query(params): Query<MemeFilter>,
2022-01-16 22:43:45 +01:00
Extension(service): Extension<JMService>,
2022-01-02 17:25:23 +01:00
) -> Result<impl IntoResponse, APIError> {
2022-07-19 21:11:13 +02:00
let random = V1Meme::new(
service.get_random_meme(params.into()).await?,
service.ext_cdn_url(),
2022-07-19 21:11:13 +02:00
);
2021-12-29 18:33:31 +01:00
Ok(Json(MemeResponse {
status: 200,
error: None,
meme: Some(random),
}))
2021-07-19 22:29:03 +02:00
}
2021-12-29 18:33:31 +01:00
async fn upload(
ContentLengthLimit(mut form): ContentLengthLimit<Multipart, { 1024 * 1024 * 1024 }>,
2022-01-16 22:43:45 +01:00
Extension(service): Extension<JMService>,
2022-01-08 20:57:53 +01:00
ExtractIP(ip): ExtractIP,
2022-01-02 17:25:23 +01:00
) -> Result<impl IntoResponse, APIError> {
2022-01-08 20:57:53 +01:00
let mut category: Option<String> = None;
let mut token: Option<String> = None;
let mut files: Vec<IPFSFile> = vec![];
while let Some(field) = form.next_field().await? {
2022-01-10 14:37:27 +01:00
match field.name().ok_or_else(|| {
APIError::BadRequest("A multipart-form field is missing a name".to_string())
})? {
2022-01-08 20:57:53 +01:00
"token" => token = Some(field.text().await?),
"category" => category = Some(field.text().await?),
"file" | "file[]" => {
let filename = field
.file_name()
2022-01-10 14:37:27 +01:00
.ok_or_else(|| {
APIError::BadRequest("A file field has no filename".to_string())
})?
2022-01-08 20:57:53 +01:00
.to_string();
2022-07-19 21:11:13 +02:00
let file = service.ipfs_add(field.bytes().await?, filename).await?;
2022-01-08 20:57:53 +01:00
files.push(file);
2022-07-21 12:18:25 +02:00
},
2022-01-08 20:57:53 +01:00
_ => (),
}
}
2022-01-10 14:37:27 +01:00
let token = token.ok_or_else(|| APIError::Unauthorized("Missing token".to_string()))?;
let category = category.ok_or_else(|| APIError::BadRequest("Missing category".to_string()))?;
2022-07-19 21:11:13 +02:00
let user = service
.check_token(&token)
2022-01-08 20:57:53 +01:00
.await?
2022-01-10 14:37:27 +01:00
.ok_or_else(|| APIError::Forbidden("token not existing".to_string()))?;
2022-01-08 20:57:53 +01:00
let total = (user.dayuploads as isize) + (files.len() as isize);
if total > 20 {
return Err(APIError::Forbidden("Upload limit reached".to_string()));
}
2022-07-19 21:11:13 +02:00
let cat = service
.get_category(&category)
2022-01-16 17:46:09 +01:00
.await?
.ok_or_else(|| APIError::BadRequest("Category not existing".to_string()))?;
2022-01-08 20:57:53 +01:00
let ip = ip.to_string();
let mut links: Vec<String> = vec![];
for f in files {
2022-07-19 21:11:13 +02:00
let res = service.add_meme_sql(&user, &f, &ip, &cat).await?;
2022-01-16 13:31:16 +01:00
if res == 0 {
return Err(APIError::Internal("Database insertion error".to_string()));
}
2022-01-17 21:58:33 +01:00
service
.add_meme(
cat.id.clone(),
f.name.clone(),
f.hash.clone(),
user.id.clone(),
res,
)
.await?;
2022-07-19 21:11:13 +02:00
service.ipfs_pin(f.hash).await?;
2022-01-08 20:57:53 +01:00
links.push(format!(
"{}/{}/{}",
service.ext_cdn_url(),
2022-01-08 20:57:53 +01:00
user.id.clone(),
f.name.clone()
));
}
Ok((
StatusCode::CREATED,
Json(UploadResponse {
status: 201,
error: None,
files: Some(links),
token,
2022-01-08 20:57:53 +01:00
}),
))
2021-07-20 12:36:19 +02:00
}
2021-08-26 17:45:38 +02:00
pub fn routes() -> Router<BoxRoute> {
Router::new()
.route("/meme", get(meme))
.route("/memes", get(memes))
.route("/category", get(category))
.route("/categories", get(categories))
.route("/user", get(user))
.route("/users", get(users))
.route("/random", get(random))
2021-12-29 18:33:31 +01:00
.route("/upload", post(upload))
2021-08-26 17:45:38 +02:00
.boxed()
2021-07-19 22:29:03 +02:00
}