add: individual topic write permissions

This commit is contained in:
trisua 2025-08-04 13:23:27 -04:00
parent 3738a5cd1f
commit 8c779b2f2e
6 changed files with 80 additions and 9 deletions

View file

@ -686,12 +686,12 @@
(div (div
("class" "flex flex_col gap_1") ("class" "flex flex_col gap_1")
(label (label
("for" "description") ("for" "{{ id }}-description")
(str (text "communities:label.description"))) (str (text "communities:label.description")))
(input (input
("type" "text") ("type" "text")
("name" "description") ("name" "description")
("id" "description") ("id" "{{ id }}-description")
("placeholder" "description") ("placeholder" "description")
("value" "{{ topic.description }}") ("value" "{{ topic.description }}")
("required" "") ("required" "")
@ -700,12 +700,12 @@
(div (div
("class" "flex flex_col gap_1") ("class" "flex flex_col gap_1")
(label (label
("for" "color") ("for" "{{ id }}-color")
(str (text "communities:label.color"))) (str (text "communities:label.color")))
(input (input
("type" "color") ("type" "color")
("name" "color") ("name" "color")
("id" "color") ("id" "{{ id }}-color")
("placeholder" "color") ("placeholder" "color")
("required" "") ("required" "")
("value" "{{ topic.color }}") ("value" "{{ topic.color }}")
@ -713,17 +713,37 @@
(div (div
("class" "flex flex_col gap_1") ("class" "flex flex_col gap_1")
(label (label
("for" "position") ("for" "{{ id }}-position")
(str (text "communities:label.position"))) (str (text "communities:label.position")))
(input (input
("type" "number") ("type" "number")
("name" "position") ("name" "position")
("id" "position") ("id" "{{ id }}-position")
("placeholder" "position") ("placeholder" "position")
("required" "") ("required" "")
("value" "{{ topic.position }}") ("value" "{{ topic.position }}")
("min" "0") ("min" "0")
("max" "256"))) ("max" "256")))
(div
("class" "flex flex_col gap_1")
(label
("for" "{{ id }}-write_access")
(text "Post permission"))
(select
("name" "write_access")
("id" "{{ id }}-write_access")
(option
("value" "Everybody")
("selected" "{% if topic.write_access == 'Everybody' -%}true{% else %}false{%- endif %}")
(text "Everybody"))
(option
("value" "Joined")
("selected" "{% if topic.write_access == 'Joined' -%}true{% else %}false{%- endif %}")
(text "Joined"))
(option
("value" "Owner")
("selected" "{% if topic.write_access == 'Owner' -%}true{% else %}false{%- endif %}")
(text "Owner only"))))
(button (button
(icon (text "check")) (icon (text "check"))
(str (text "general:action.save"))))))) (str (text "general:action.save")))))))
@ -794,6 +814,7 @@
description: e.target.description.value, description: e.target.description.value,
color: e.target.color.value, color: e.target.color.value,
position: Number.parseInt(e.target.position.value), position: Number.parseInt(e.target.position.value),
write_access: e.target.write_access.selectedOptions[0].value,
}), }),
}) })
.then((res) => res.json()) .then((res) => res.json())

View file

@ -9,6 +9,7 @@
(text "{{ components::topic_display(id=topic_id, topic=topic, community=community, show_description=false) }}") (text "{{ components::topic_display(id=topic_id, topic=topic, community=community, show_description=false) }}")
(div (div
("class" "flex gap_2") ("class" "flex gap_2")
(text "{% if can_post -%}")
(a (a
("href" "/communities/intents/post?community={{ community.id }}&topic={{ topic_id }}&sig=true") ("href" "/communities/intents/post?community={{ community.id }}&topic={{ topic_id }}&sig=true")
("class" "button small lowered") ("class" "button small lowered")
@ -16,6 +17,7 @@
(icon (text "plus")) (icon (text "plus"))
(span (span
(str (text "general:action.post")))) (str (text "general:action.post"))))
(text "{%- endif %}")
(a (a
("href" "/community/{{ community.title }}") ("href" "/community/{{ community.title }}")
("class" "button lowered small") ("class" "button lowered small")

View file

@ -560,7 +560,13 @@ pub async fn add_topic_request(
} }
// ... // ...
let (topic_id, topic) = ForumTopic::new(req.title, req.description, req.color, req.position); let (topic_id, topic) = ForumTopic::new(
req.title,
req.description,
req.color,
req.position,
community.write_access,
);
community.topics.insert(topic_id, topic); community.topics.insert(topic_id, topic);
match data match data
@ -616,6 +622,7 @@ pub async fn update_topic_request(
description: req.description, description: req.description,
color: req.color, color: req.color,
position: req.position, position: req.position,
write_access: req.write_access,
}; };
community.topics.insert(topic_id, topic); community.topics.insert(topic_id, topic);

View file

@ -797,6 +797,8 @@ pub struct AddTopic {
pub color: String, pub color: String,
#[serde(default)] #[serde(default)]
pub position: i32, pub position: i32,
#[serde(default)]
pub write_access: CommunityWriteAccess,
} }
#[derive(Deserialize)] #[derive(Deserialize)]

View file

@ -1783,6 +1783,28 @@ impl DataManager {
} }
} }
/// Check if the given `uid` can post in the given `community` with the given `access`.
pub async fn check_can_post_with_access(
&self,
community: &Community,
access: &CommunityWriteAccess,
uid: usize,
) -> bool {
match *access {
CommunityWriteAccess::Owner => uid == community.owner,
CommunityWriteAccess::Joined => {
match self
.get_membership_by_owner_community(uid, community.id)
.await
{
Ok(m) => m.role.check_member(),
Err(_) => false,
}
}
_ => true,
}
}
/// Create a new post in the database. /// Create a new post in the database.
/// ///
/// # Arguments /// # Arguments
@ -1840,7 +1862,15 @@ impl DataManager {
)); ));
} }
if community.topics.get(&data.topic).is_none() { if let Some(topic) = community.topics.get(&data.topic) {
// check permission
if !self
.check_can_post_with_access(&community, &topic.write_access, data.owner)
.await
{
return Err(Error::NotAllowed);
}
} else {
return Err(Error::GeneralNotFound("topic".to_string())); return Err(Error::GeneralNotFound("topic".to_string()));
} }
} }

View file

@ -541,6 +541,8 @@ pub struct ForumTopic {
pub description: String, pub description: String,
pub color: String, pub color: String,
pub position: i32, pub position: i32,
#[serde(default)]
pub write_access: CommunityWriteAccess,
} }
impl ForumTopic { impl ForumTopic {
@ -549,7 +551,13 @@ impl ForumTopic {
/// # Returns /// # Returns
/// * ID for [`Community`] hashmap /// * ID for [`Community`] hashmap
/// * [`ForumTopic`] /// * [`ForumTopic`]
pub fn new(title: String, description: String, color: String, position: i32) -> (usize, Self) { pub fn new(
title: String,
description: String,
color: String,
position: i32,
write_access: CommunityWriteAccess,
) -> (usize, Self) {
( (
Snowflake::new().to_string().parse::<usize>().unwrap(), Snowflake::new().to_string().parse::<usize>().unwrap(),
Self { Self {
@ -557,6 +565,7 @@ impl ForumTopic {
description, description,
color, color,
position, position,
write_access,
}, },
) )
} }