diff --git a/crates/app/src/public/html/communities/settings.lisp b/crates/app/src/public/html/communities/settings.lisp
index 239d3cc..29b171e 100644
--- a/crates/app/src/public/html/communities/settings.lisp
+++ b/crates/app/src/public/html/communities/settings.lisp
@@ -686,12 +686,12 @@
(div
("class" "flex flex_col gap_1")
(label
- ("for" "description")
+ ("for" "{{ id }}-description")
(str (text "communities:label.description")))
(input
("type" "text")
("name" "description")
- ("id" "description")
+ ("id" "{{ id }}-description")
("placeholder" "description")
("value" "{{ topic.description }}")
("required" "")
@@ -700,12 +700,12 @@
(div
("class" "flex flex_col gap_1")
(label
- ("for" "color")
+ ("for" "{{ id }}-color")
(str (text "communities:label.color")))
(input
("type" "color")
("name" "color")
- ("id" "color")
+ ("id" "{{ id }}-color")
("placeholder" "color")
("required" "")
("value" "{{ topic.color }}")
@@ -713,17 +713,37 @@
(div
("class" "flex flex_col gap_1")
(label
- ("for" "position")
+ ("for" "{{ id }}-position")
(str (text "communities:label.position")))
(input
("type" "number")
("name" "position")
- ("id" "position")
+ ("id" "{{ id }}-position")
("placeholder" "position")
("required" "")
("value" "{{ topic.position }}")
("min" "0")
("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
(icon (text "check"))
(str (text "general:action.save")))))))
@@ -794,6 +814,7 @@
description: e.target.description.value,
color: e.target.color.value,
position: Number.parseInt(e.target.position.value),
+ write_access: e.target.write_access.selectedOptions[0].value,
}),
})
.then((res) => res.json())
diff --git a/crates/app/src/public/html/communities/topic.lisp b/crates/app/src/public/html/communities/topic.lisp
index ce14857..08ed014 100644
--- a/crates/app/src/public/html/communities/topic.lisp
+++ b/crates/app/src/public/html/communities/topic.lisp
@@ -9,6 +9,7 @@
(text "{{ components::topic_display(id=topic_id, topic=topic, community=community, show_description=false) }}")
(div
("class" "flex gap_2")
+ (text "{% if can_post -%}")
(a
("href" "/communities/intents/post?community={{ community.id }}&topic={{ topic_id }}&sig=true")
("class" "button small lowered")
@@ -16,6 +17,7 @@
(icon (text "plus"))
(span
(str (text "general:action.post"))))
+ (text "{%- endif %}")
(a
("href" "/community/{{ community.title }}")
("class" "button lowered small")
diff --git a/crates/app/src/routes/api/v1/communities/communities.rs b/crates/app/src/routes/api/v1/communities/communities.rs
index 39bfea5..066c8a5 100644
--- a/crates/app/src/routes/api/v1/communities/communities.rs
+++ b/crates/app/src/routes/api/v1/communities/communities.rs
@@ -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);
match data
@@ -616,6 +622,7 @@ pub async fn update_topic_request(
description: req.description,
color: req.color,
position: req.position,
+ write_access: req.write_access,
};
community.topics.insert(topic_id, topic);
diff --git a/crates/app/src/routes/api/v1/mod.rs b/crates/app/src/routes/api/v1/mod.rs
index 5f553a6..2b148df 100644
--- a/crates/app/src/routes/api/v1/mod.rs
+++ b/crates/app/src/routes/api/v1/mod.rs
@@ -797,6 +797,8 @@ pub struct AddTopic {
pub color: String,
#[serde(default)]
pub position: i32,
+ #[serde(default)]
+ pub write_access: CommunityWriteAccess,
}
#[derive(Deserialize)]
diff --git a/crates/core/src/database/posts.rs b/crates/core/src/database/posts.rs
index a3e7336..bd326f9 100644
--- a/crates/core/src/database/posts.rs
+++ b/crates/core/src/database/posts.rs
@@ -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.
///
/// # 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()));
}
}
diff --git a/crates/core/src/model/communities.rs b/crates/core/src/model/communities.rs
index 2108847..5b5a869 100644
--- a/crates/core/src/model/communities.rs
+++ b/crates/core/src/model/communities.rs
@@ -541,6 +541,8 @@ pub struct ForumTopic {
pub description: String,
pub color: String,
pub position: i32,
+ #[serde(default)]
+ pub write_access: CommunityWriteAccess,
}
impl ForumTopic {
@@ -549,7 +551,13 @@ impl ForumTopic {
/// # Returns
/// * ID for [`Community`] hashmap
/// * [`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::().unwrap(),
Self {
@@ -557,6 +565,7 @@ impl ForumTopic {
description,
color,
position,
+ write_access,
},
)
}