add: community topic endpoints

This commit is contained in:
trisua 2025-08-03 11:45:57 -04:00
parent 12fa80c7c0
commit ef029c59b3
7 changed files with 201 additions and 28 deletions

View file

@ -3,12 +3,14 @@ use axum::{
extract::Path,
response::{IntoResponse, Redirect},
};
use crate::cookie::CookieJar;
use crate::{cookie::CookieJar, routes::api::v1::AddTopic};
use tetratto_core::model::{
auth::Notification,
communities::{Community, CommunityMembership},
communities::{Community, CommunityMembership, ForumTopic},
communities_permissions::CommunityPermission,
oauth, ApiReturn, Error,
oauth,
permissions::FinePermission,
ApiReturn, Error,
};
use crate::{
@ -269,7 +271,7 @@ pub async fn get_membership(
Err(e) => return Json(e.into()),
};
if user.id != community.owner {
if user.id != community.owner && !user.permissions.check(FinePermission::MANAGE_MEMBERSHIPS) {
// only the owner can select community memberships
return Json(Error::NotAllowed.into());
}
@ -523,3 +525,117 @@ pub async fn get_communities_request(
payload: Some(communities),
})
}
pub async fn add_topic_request(
jar: CookieJar,
Extension(data): Extension<State>,
Path(id): Path<usize>,
Json(req): Json<AddTopic>,
) -> impl IntoResponse {
let data = &(data.read().await).0;
let user = match get_user_from_token!(jar, data, oauth::AppScope::CommunityManage) {
Some(ua) => ua,
None => return Json(Error::NotAllowed.into()),
};
let mut community = match data.get_community_by_id(id).await {
Ok(x) => x,
Err(e) => return Json(e.into()),
};
if !community.is_forum {
return Json(Error::DoesNotSupportField("community".to_string()).into());
}
let (id, topic) = ForumTopic::new(req.title, req.description, req.color);
community.topics.insert(id, topic);
match data
.update_community_topics(id, &user, community.topics)
.await
{
Ok(_) => Json(ApiReturn {
ok: true,
message: "Community updated".to_string(),
payload: (),
}),
Err(e) => Json(e.into()),
}
}
pub async fn update_topic_request(
jar: CookieJar,
Extension(data): Extension<State>,
Path((id, topic_id)): Path<(usize, usize)>,
Json(req): Json<AddTopic>,
) -> impl IntoResponse {
let data = &(data.read().await).0;
let user = match get_user_from_token!(jar, data, oauth::AppScope::CommunityManage) {
Some(ua) => ua,
None => return Json(Error::NotAllowed.into()),
};
let mut community = match data.get_community_by_id(id).await {
Ok(x) => x,
Err(e) => return Json(e.into()),
};
if !community.is_forum {
return Json(Error::DoesNotSupportField("community".to_string()).into());
}
let topic = ForumTopic {
title: req.title,
description: req.description,
color: req.color,
};
community.topics.insert(topic_id, topic);
match data
.update_community_topics(id, &user, community.topics)
.await
{
Ok(_) => Json(ApiReturn {
ok: true,
message: "Community updated".to_string(),
payload: (),
}),
Err(e) => Json(e.into()),
}
}
pub async fn delete_topic_request(
jar: CookieJar,
Extension(data): Extension<State>,
Path((id, topic_id)): Path<(usize, usize)>,
) -> impl IntoResponse {
let data = &(data.read().await).0;
let user = match get_user_from_token!(jar, data, oauth::AppScope::CommunityManage) {
Some(ua) => ua,
None => return Json(Error::NotAllowed.into()),
};
let mut community = match data.get_community_by_id(id).await {
Ok(x) => x,
Err(e) => return Json(e.into()),
};
if !community.is_forum {
return Json(Error::DoesNotSupportField("community".to_string()).into());
}
community.topics.remove(&topic_id);
match data
.update_community_topics(id, &user, community.topics)
.await
{
Ok(_) => Json(ApiReturn {
ok: true,
message: "Community updated".to_string(),
payload: (),
}),
Err(e) => Json(e.into()),
}
}

View file

@ -131,6 +131,18 @@ pub fn routes() -> Router {
"/communities/{id}/supports_titles",
get(communities::communities::supports_titles_request),
)
.route(
"/communities/{id}/topics",
post(communities::communities::add_topic_request),
)
.route(
"/communities/{id}/topics/{id}",
post(communities::communities::update_topic_request),
)
.route(
"/communities/{id}/topics/{id}",
delete(communities::communities::delete_topic_request),
)
// posts
.route("/posts", post(communities::posts::create_request))
.route("/posts/{id}", delete(communities::posts::delete_request))
@ -778,6 +790,13 @@ pub struct UpdateCommunityJoinAccess {
pub access: CommunityJoinAccess,
}
#[derive(Deserialize)]
pub struct AddTopic {
pub title: String,
pub description: String,
pub color: String,
}
#[derive(Deserialize)]
pub struct CreatePostPoll {
pub option_a: String,