use crate::{get_user_from_token, routes::pages::PaginatedQuery, State}; use axum::{ extract::{Path, Query}, response::IntoResponse, Extension, Json, }; use axum_extra::extract::CookieJar; use tetratto_core::{ model::{ oauth, permissions::FinePermission, stacks::{StackBlock, StackMode, StackPrivacy, UserStack}, ApiReturn, Error, }, DataManager, }; use super::{ AddOrRemoveStackUser, CreateStack, UpdateStackMode, UpdateStackName, UpdateStackPrivacy, UpdateStackSort, }; pub async fn create_request( jar: CookieJar, Extension(data): Extension, Json(req): Json, ) -> impl IntoResponse { let data = &(data.read().await).0; let user = match get_user_from_token!(jar, data, oauth::AppScope::UserCreateStacks) { Some(ua) => ua, None => return Json(Error::NotAllowed.into()), }; match data .create_stack(UserStack::new(req.name, user.id, Vec::new())) .await { Ok(s) => Json(ApiReturn { ok: true, message: "Stack created".to_string(), payload: s.id.to_string(), }), Err(e) => Json(e.into()), } } pub async fn update_name_request( jar: CookieJar, Extension(data): Extension, Path(id): Path, Json(req): Json, ) -> impl IntoResponse { let data = &(data.read().await).0; let user = match get_user_from_token!(jar, data, oauth::AppScope::UserManageStacks) { Some(ua) => ua, None => return Json(Error::NotAllowed.into()), }; match data.update_stack_name(id, &user, &req.name).await { Ok(_) => Json(ApiReturn { ok: true, message: "Stack updated".to_string(), payload: (), }), Err(e) => Json(e.into()), } } pub async fn update_privacy_request( jar: CookieJar, Extension(data): Extension, Path(id): Path, Json(req): Json, ) -> impl IntoResponse { let data = &(data.read().await).0; let user = match get_user_from_token!(jar, data, oauth::AppScope::UserManageStacks) { Some(ua) => ua, None => return Json(Error::NotAllowed.into()), }; match data.update_stack_privacy(id, &user, req.privacy).await { Ok(_) => Json(ApiReturn { ok: true, message: "Stack updated".to_string(), payload: (), }), Err(e) => Json(e.into()), } } pub async fn update_mode_request( jar: CookieJar, Extension(data): Extension, Path(id): Path, Json(req): Json, ) -> impl IntoResponse { let data = &(data.read().await).0; let user = match get_user_from_token!(jar, data, oauth::AppScope::UserManageStacks) { Some(ua) => ua, None => return Json(Error::NotAllowed.into()), }; match data.update_stack_mode(id, &user, req.mode).await { Ok(_) => Json(ApiReturn { ok: true, message: "Stack updated".to_string(), payload: (), }), Err(e) => Json(e.into()), } } pub async fn update_sort_request( jar: CookieJar, Extension(data): Extension, Path(id): Path, Json(req): Json, ) -> impl IntoResponse { let data = &(data.read().await).0; let user = match get_user_from_token!(jar, data, oauth::AppScope::UserManageStacks) { Some(ua) => ua, None => return Json(Error::NotAllowed.into()), }; match data.update_stack_sort(id, &user, req.sort).await { Ok(_) => Json(ApiReturn { ok: true, message: "Stack updated".to_string(), payload: (), }), Err(e) => Json(e.into()), } } pub async fn add_user_request( jar: CookieJar, Extension(data): Extension, Path(id): Path, Json(req): Json, ) -> impl IntoResponse { let data = &(data.read().await).0; let user = match get_user_from_token!(jar, data, oauth::AppScope::UserManageStacks) { Some(ua) => ua, None => return Json(Error::NotAllowed.into()), }; let other_user = match data.get_user_by_username(&req.username).await { Ok(c) => c, Err(e) => return Json(Error::MiscError(e.to_string()).into()), }; // check block status if data .get_userblock_by_initiator_receiver(other_user.id, user.id) .await .is_ok() { return Json(Error::NotAllowed.into()); } // add user let mut stack = match data.get_stack_by_id(id).await { Ok(s) => s, Err(e) => return Json(e.into()), }; stack.users.push(other_user.id); // check number of stacks let owner = match data.get_user_by_id(stack.owner).await { Ok(ua) => ua, Err(e) => return Json(e.into()), }; if !owner.permissions.check(FinePermission::SUPPORTER) { if stack.users.len() >= DataManager::MAXIMUM_FREE_STACK_USERS { return Json( Error::MiscError( "This stack already has the maximum users it can have".to_string(), ) .into(), ); } } // ... match data.update_stack_users(id, &user, stack.users).await { Ok(_) => Json(ApiReturn { ok: true, message: "User added".to_string(), payload: (), }), Err(e) => Json(e.into()), } } pub async fn remove_user_request( jar: CookieJar, Extension(data): Extension, Path(id): Path, Json(req): Json, ) -> impl IntoResponse { let data = &(data.read().await).0; let user = match get_user_from_token!(jar, data, oauth::AppScope::UserManageStacks) { Some(ua) => ua, None => return Json(Error::NotAllowed.into()), }; let mut stack = match data.get_stack_by_id(id).await { Ok(s) => s, Err(e) => return Json(e.into()), }; let other_user = match data.get_user_by_username(&req.username).await { Ok(c) => c, Err(e) => return Json(Error::MiscError(e.to_string()).into()), }; stack .users .remove(match stack.users.iter().position(|x| x == &other_user.id) { Some(idx) => idx, None => return Json(Error::GeneralNotFound("user".to_string()).into()), }); match data.update_stack_users(id, &user, stack.users).await { Ok(_) => Json(ApiReturn { ok: true, message: "User removed".to_string(), payload: (), }), Err(e) => Json(e.into()), } } pub async fn delete_request( jar: CookieJar, Extension(data): Extension, Path(id): Path, ) -> impl IntoResponse { let data = &(data.read().await).0; let user = match get_user_from_token!(jar, data, oauth::AppScope::UserManageStacks) { Some(ua) => ua, None => return Json(Error::NotAllowed.into()), }; match data.delete_stack(id, &user).await { Ok(_) => Json(ApiReturn { ok: true, message: "Stack deleted".to_string(), payload: (), }), Err(e) => Json(e.into()), } } pub async fn get_users_request( jar: CookieJar, Extension(data): Extension, Path(id): Path, Query(props): Query, ) -> impl IntoResponse { let data = &(data.read().await).0; let user = match get_user_from_token!(jar, data, oauth::AppScope::UserReadProfiles) { Some(ua) => ua, None => return Json(Error::NotAllowed.into()), }; let stack = match data.get_stack_by_id(id).await { Ok(s) => s, Err(e) => return Json(e.into()), }; if stack.privacy == StackPrivacy::Private && user.id != stack.owner && !(stack.mode == StackMode::Circle && stack.users.contains(&user.id)) && !user.permissions.check(FinePermission::MANAGE_STACKS) { return Json(Error::NotAllowed.into()); } match data.get_stack_users(id, 12, props.page).await { Ok(users) => Json(ApiReturn { ok: true, message: "Success".to_string(), payload: Some({ let mut out = Vec::new(); for mut u in users.clone() { u.clean(); out.push(u) } out }), }), Err(e) => Json(e.into()), } } pub async fn block_request( jar: CookieJar, Extension(data): Extension, Path(id): Path, ) -> impl IntoResponse { let data = &(data.read().await).0; let user = match get_user_from_token!(jar, data, oauth::AppScope::UserReadProfiles) { Some(ua) => ua, None => return Json(Error::NotAllowed.into()), }; match data.create_stackblock(StackBlock::new(user.id, id)).await { Ok(_) => Json(ApiReturn { ok: true, message: "Success".to_string(), payload: (), }), Err(e) => Json(e.into()), } } pub async fn unblock_request( jar: CookieJar, Extension(data): Extension, Path(id): Path, ) -> impl IntoResponse { let data = &(data.read().await).0; let user = match get_user_from_token!(jar, data, oauth::AppScope::UserReadProfiles) { Some(ua) => ua, None => return Json(Error::NotAllowed.into()), }; let block = match data.get_stackblock_by_initiator_stack(user.id, id).await { Ok(b) => b, Err(e) => return Json(e.into()), }; match data.delete_stackblock(block.id, user).await { Ok(_) => Json(ApiReturn { ok: true, message: "Success".to_string(), payload: (), }), Err(e) => Json(e.into()), } }