add: user stacks

This commit is contained in:
trisua 2025-05-08 22:18:04 -04:00
parent 8c3024cb40
commit 75d72460ae
28 changed files with 1028 additions and 9 deletions

View file

@ -4,6 +4,7 @@ pub mod notifications;
pub mod reactions;
pub mod reports;
pub mod requests;
pub mod stacks;
pub mod util;
#[cfg(feature = "redis")]
@ -22,6 +23,7 @@ use tetratto_core::model::{
communities_permissions::CommunityPermission,
permissions::FinePermission,
reactions::AssetType,
stacks::StackPrivacy,
};
pub fn routes() -> Router {
@ -320,6 +322,13 @@ pub fn routes() -> Router {
"/lookup_emoji",
post(communities::emojis::get_emoji_shortcode),
)
// stacks
.route("/stacks", post(stacks::create_request))
.route("/stacks/{id}/name", post(stacks::update_name_request))
.route("/stacks/{id}/privacy", post(stacks::update_privacy_request))
.route("/stacks/{id}/users", post(stacks::add_user_request))
.route("/stacks/{id}/users", delete(stacks::remove_user_request))
.route("/stacks/{id}", delete(stacks::delete_request))
}
#[derive(Deserialize)]
@ -506,3 +515,23 @@ pub struct CreateMessage {
pub struct KickMember {
pub member: String,
}
#[derive(Deserialize)]
pub struct CreateStack {
pub name: String,
}
#[derive(Deserialize)]
pub struct UpdateStackName {
pub name: String,
}
#[derive(Deserialize)]
pub struct UpdateStackPrivacy {
pub privacy: StackPrivacy,
}
#[derive(Deserialize)]
pub struct AddOrRemoveStackUser {
pub username: String,
}

View file

@ -0,0 +1,176 @@
use crate::{State, get_user_from_token};
use axum::{Extension, Json, extract::Path, response::IntoResponse};
use axum_extra::extract::CookieJar;
use tetratto_core::model::{stacks::UserStack, ApiReturn, Error};
use super::{AddOrRemoveStackUser, CreateStack, UpdateStackName, UpdateStackPrivacy};
pub async fn create_request(
jar: CookieJar,
Extension(data): Extension<State>,
Json(req): Json<CreateStack>,
) -> impl IntoResponse {
let data = &(data.read().await).0;
let user = match get_user_from_token!(jar, data) {
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,
}),
Err(e) => Json(e.into()),
}
}
pub async fn update_name_request(
jar: CookieJar,
Extension(data): Extension<State>,
Path(id): Path<usize>,
Json(req): Json<UpdateStackName>,
) -> impl IntoResponse {
let data = &(data.read().await).0;
let user = match get_user_from_token!(jar, data) {
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<State>,
Path(id): Path<usize>,
Json(req): Json<UpdateStackPrivacy>,
) -> impl IntoResponse {
let data = &(data.read().await).0;
let user = match get_user_from_token!(jar, data) {
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 add_user_request(
jar: CookieJar,
Extension(data): Extension<State>,
Path(id): Path<usize>,
Json(req): Json<AddOrRemoveStackUser>,
) -> impl IntoResponse {
let data = &(data.read().await).0;
let user = match get_user_from_token!(jar, data) {
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);
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<State>,
Path(id): Path<usize>,
Json(req): Json<AddOrRemoveStackUser>,
) -> impl IntoResponse {
let data = &(data.read().await).0;
let user = match get_user_from_token!(jar, data) {
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<State>,
Path(id): Path<usize>,
) -> impl IntoResponse {
let data = &(data.read().await).0;
let user = match get_user_from_token!(jar, data) {
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()),
}
}