2021-12-17 23:50:03 +01:00
|
|
|
use crate::config::ConfVars;
|
2022-01-02 17:25:23 +01:00
|
|
|
use crate::ipfs::IPFSFile;
|
2022-01-08 20:57:53 +01:00
|
|
|
use crate::lib::ExtractIP;
|
2022-01-16 17:46:09 +01:00
|
|
|
use crate::models::{Category, Meme, MemeFilter, User};
|
2021-07-19 22:29:03 +02:00
|
|
|
use crate::v1::models::*;
|
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
|
|
|
use sqlx::MySqlPool;
|
|
|
|
|
2022-01-02 17:25:23 +01:00
|
|
|
use super::error::APIError;
|
2022-01-11 19:42:15 +01:00
|
|
|
use super::Query;
|
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>,
|
2021-12-29 18:33:31 +01:00
|
|
|
Extension(db_pool): Extension<MySqlPool>,
|
|
|
|
Extension(vars): Extension<ConfVars>,
|
2022-01-02 17:25:23 +01:00
|
|
|
) -> Result<impl IntoResponse, APIError> {
|
2022-01-16 17:46:09 +01:00
|
|
|
let meme = V1Meme::new(
|
|
|
|
Meme::get(params.id, &db_pool)
|
|
|
|
.await?
|
|
|
|
.ok_or_else(|| APIError::NotFound("Meme not found".to_string()))?,
|
|
|
|
vars.cdn,
|
|
|
|
);
|
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>,
|
2021-12-29 18:33:31 +01:00
|
|
|
Extension(db_pool): Extension<MySqlPool>,
|
|
|
|
Extension(vars): Extension<ConfVars>,
|
2022-01-02 17:25:23 +01:00
|
|
|
) -> Result<impl IntoResponse, APIError> {
|
2022-01-16 17:46:09 +01:00
|
|
|
let memes = Meme::get_all(params, &db_pool)
|
|
|
|
.await?
|
|
|
|
.into_iter()
|
|
|
|
.map(|meme| V1Meme::new(meme, vars.cdn.clone()))
|
|
|
|
.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>,
|
2021-12-29 18:33:31 +01:00
|
|
|
Extension(db_pool): Extension<MySqlPool>,
|
2022-01-02 17:25:23 +01:00
|
|
|
) -> Result<impl IntoResponse, APIError> {
|
2022-01-16 17:46:09 +01:00
|
|
|
let category = Category::get(¶ms.id, &db_pool)
|
|
|
|
.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(
|
|
|
|
Extension(db_pool): Extension<MySqlPool>,
|
2022-01-02 17:25:23 +01:00
|
|
|
) -> Result<impl IntoResponse, APIError> {
|
2021-12-29 18:33:31 +01:00
|
|
|
let categories = Category::get_all(&db_pool).await?;
|
|
|
|
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>,
|
2021-12-29 18:33:31 +01:00
|
|
|
Extension(db_pool): Extension<MySqlPool>,
|
2022-01-02 17:25:23 +01:00
|
|
|
) -> Result<impl IntoResponse, APIError> {
|
2022-01-16 17:46:09 +01:00
|
|
|
let user = User::get(params.into(), &db_pool)
|
|
|
|
.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-01-02 17:25:23 +01:00
|
|
|
async fn users(Extension(db_pool): Extension<MySqlPool>) -> Result<impl IntoResponse, APIError> {
|
2021-12-29 18:33:31 +01:00
|
|
|
let users = User::get_all(&db_pool).await?;
|
|
|
|
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>,
|
2021-12-29 18:33:31 +01:00
|
|
|
Extension(db_pool): Extension<MySqlPool>,
|
|
|
|
Extension(vars): Extension<ConfVars>,
|
2022-01-02 17:25:23 +01:00
|
|
|
) -> Result<impl IntoResponse, APIError> {
|
2022-01-16 17:46:09 +01:00
|
|
|
let random = V1Meme::new(Meme::get_random(params, &db_pool).await?, vars.cdn);
|
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 }>,
|
|
|
|
Extension(db_pool): Extension<MySqlPool>,
|
|
|
|
Extension(vars): Extension<ConfVars>,
|
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![];
|
|
|
|
|
|
|
|
let ipfs = vars.ipfs_client()?;
|
|
|
|
|
|
|
|
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();
|
|
|
|
let file = ipfs.add(field.bytes().await?, filename).await?;
|
|
|
|
files.push(file);
|
|
|
|
}
|
|
|
|
_ => (),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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-01-10 19:07:57 +01:00
|
|
|
let user = User::check_token(&token, &db_pool)
|
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-01-16 17:46:09 +01:00
|
|
|
let cat = Category::get(&category, &db_pool)
|
|
|
|
.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 {
|
|
|
|
let res = cat.add_meme(&user, &f, &ip, &db_pool).await?;
|
2022-01-08 23:52:15 +01:00
|
|
|
|
2022-01-16 13:31:16 +01:00
|
|
|
if res == 0 {
|
2022-01-08 23:52:15 +01:00
|
|
|
return Err(APIError::Internal("Database insertion error".to_string()));
|
|
|
|
}
|
|
|
|
|
2022-01-08 20:57:53 +01:00
|
|
|
ipfs.pin(f.hash).await?;
|
|
|
|
links.push(format!(
|
|
|
|
"{}/{}/{}",
|
|
|
|
vars.cdn,
|
|
|
|
user.id.clone(),
|
|
|
|
f.name.clone()
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok((
|
|
|
|
StatusCode::CREATED,
|
|
|
|
Json(UploadResponse {
|
|
|
|
status: 201,
|
|
|
|
error: None,
|
|
|
|
files: Some(links),
|
2022-01-10 19:07:57 +01:00
|
|
|
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
|
|
|
}
|