aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorrebecca <ubq323@ubq323.website>2026-10-31 23:25:13 +0000
committerrebecca <ubq323@ubq323.website>2026-10-31 23:25:13 +0000
commita941ab9dda34000c17b3113fee6df752ab7995d5 (patch)
tree878e5a7a1be6f5f867b3847ebf95e8263dc5be98
parenta77caf60a3053c2c114c2ff7eeafe52374bebaec (diff)
add thread locking
-rw-r--r--apioforum/db.py3
-rw-r--r--apioforum/forum.py8
-rw-r--r--apioforum/templates/config_thread.html12
-rw-r--r--apioforum/templates/view_thread.html51
-rw-r--r--apioforum/thread.py20
5 files changed, 66 insertions, 28 deletions
diff --git a/apioforum/db.py b/apioforum/db.py
index 116f136..ead4e5a 100644
--- a/apioforum/db.py
+++ b/apioforum/db.py
@@ -258,6 +258,9 @@ DROP VIEW public_forums;
ALTER TABLE users ADD COLUMN banned INT NOT NULL DEFAULT 0;
ALTER TABLE users ADD COLUMN banreason TEXT;
""",
+"""
+ALTER TABLE threads ADD COLUMN locked INT NOT NULL DEFAULT 0;
+""",
]
diff --git a/apioforum/forum.py b/apioforum/forum.py
index f1fae28..a955ed5 100644
--- a/apioforum/forum.py
+++ b/apioforum/forum.py
@@ -291,12 +291,16 @@ def create_thread(forum):
err = None
if len(title.strip()) == 0 or len(content.strip()) == 0:
err = "title and content can't be empty"
+ elif 'lock' in request.form and not has_permission(forum['id'], g.user, "p_manage_threads"):
+ err = "you do not have permission to lock threads"
if err is None:
+ lock = int(request.form.get('lock','0'))
cur = db.cursor()
cur.execute(
- "INSERT INTO threads (title,creator,created,updated,forum) VALUES (?,?,current_timestamp,current_timestamp,?);",
- (title,g.user,forum['id'])
+ """INSERT INTO threads (title,creator,created,updated,forum,locked)
+ VALUES (?,?,current_timestamp,current_timestamp,?,?);""",
+ (title,g.user,forum['id'],lock)
)
thread_id = cur.lastrowid
cur.execute(
diff --git a/apioforum/templates/config_thread.html b/apioforum/templates/config_thread.html
index a66d786..aa4575f 100644
--- a/apioforum/templates/config_thread.html
+++ b/apioforum/templates/config_thread.html
@@ -37,6 +37,18 @@
<p>there are no available tags.</p>
{% endif %}
</fieldset>
+
+{% if has_permission(thread.forum if thread else forum.id, g.user, "p_manage_threads") %}
+<fieldset>
+<legend>locking</legend>
+{% set already_locked = thread and thread.locked %}
+<input type="radio" id="unlock" name="lock" value="0" {{"" if already_locked else "checked"}}>
+ <label for="unlock">unlocked</label>
+<input type="radio" id="lock" name="lock" value="1" {{"checked" if already_locked else ""}}>
+ <label for="lock">locked (only those with "manage threads" may reply)</label>
+</fieldset>
+{% endif %}
+
{% if thread %}
<p>confirm changes?</p>
<input type="submit" value="confirm">
diff --git a/apioforum/templates/view_thread.html b/apioforum/templates/view_thread.html
index c77d2e7..1a74f60 100644
--- a/apioforum/templates/view_thread.html
+++ b/apioforum/templates/view_thread.html
@@ -73,32 +73,37 @@
{% if page != max_pageno %}
{{ pagination_nav(page,max_pageno,'thread.view_thread',thread_id=thread.id,bottom=True) }}
{% elif g.user and has_permission(thread.forum, g.user, "p_reply_threads") %}
-<form class="new-post" action="{{url_for('thread.create_post',thread_id=thread.id)}}" method="POST">
- <textarea class="new-post-box" placeholder="your post here..." name="content"></textarea>
- {% if poll and has_permission(thread.forum, g.user, "p_vote") %}
- <fieldset>
- <legend>poll: {{poll.title}}</legend>
- <p>if you want, you can submit a vote along with this post. if you have previously voted
- on this poll, your previous vote will be changed</p>
+ {% if thread.locked and not has_permission(thread.forum, g.user, "p_manage_threads") %}
+ <p>this thread is locked, and may not recieve further replies</p>
+ {% else %}
+ <form class="new-post" action="{{url_for('thread.create_post',thread_id=thread.id)}}" method="POST">
+ {% if thread.locked %}<p>this thread is locked, but you can reply to it anyway</p>{% endif %}
+ <textarea class="new-post-box" placeholder="your post here..." name="content"></textarea>
+ {% if poll and has_permission(thread.forum, g.user, "p_vote") %}
+ <fieldset>
+ <legend>poll: {{poll.title}}</legend>
+ <p>if you want, you can submit a vote along with this post. if you have previously voted
+ on this poll, your previous vote will be changed</p>
- <input type="radio" id="dontvote" name="poll" value="dontvote" checked>
- <label for="dontvote">do not submit any vote at the moment</label>
+ <input type="radio" id="dontvote" name="poll" value="dontvote" checked>
+ <label for="dontvote">do not submit any vote at the moment</label>
- {% if has_voted %}
- <br>
- <input type="radio" id="retractvote" name="poll" value="retractvote">
- <label for="retractvote">clear current vote</label>
- {% endif %}
+ {% if has_voted %}
+ <br>
+ <input type="radio" id="retractvote" name="poll" value="retractvote">
+ <label for="retractvote">clear current vote</label>
+ {% endif %}
- {% for opt in poll.options %}
- <br>
- <input type="radio" id="option_{{opt.option_idx}}" name="poll" value="{{opt.option_idx}}">
- <label for="option_{{opt.option_idx}}">#{{opt.option_idx}} - {{opt.text}}</label>
- {% endfor %}
- </fieldset>
- {% endif %}
- <input type="submit" value="yes">
-</form>
+ {% for opt in poll.options %}
+ <br>
+ <input type="radio" id="option_{{opt.option_idx}}" name="poll" value="{{opt.option_idx}}">
+ <label for="option_{{opt.option_idx}}">#{{opt.option_idx}} - {{opt.text}}</label>
+ {% endfor %}
+ </fieldset>
+ {% endif %}
+ <input type="submit" value="yes">
+ </form>
+ {%endif%}
{% elif g.user %}
<p>you do not have permission to reply to this thread</p>
{% else %}
diff --git a/apioforum/thread.py b/apioforum/thread.py
index 2457deb..3c4a3a3 100644
--- a/apioforum/thread.py
+++ b/apioforum/thread.py
@@ -241,6 +241,8 @@ def create_post(thread_id):
flash("you cannot post an empty message")
elif not thread:
flash("that thread does not exist")
+ elif thread['locked'] and not has_permission(thread['forum'], g.user, "p_manage_threads"):
+ flash("you may not post to a locked thread")
elif not has_permission(thread['forum'], g.user, "p_reply_threads"):
flash("you do not have permission to do this")
elif not has_permission(thread['forum'], g.user, "p_view_threads"):
@@ -400,6 +402,9 @@ def config_thread(thread_id):
err = "you do not have permission to do that"
elif g.user != thread['creator'] and not has_permission(thread['forum'], g.user, "p_manage_threads"):
err = "you can only configure threads that you own"
+ elif request.method=="POST" and 'lock' in request.form \
+ and not has_permission(thread['forum'], g.user, "p_manage_threads"):
+ err = "you do not have permission to lock threads"
if err is not None:
flash(err)
@@ -413,11 +418,21 @@ def config_thread(thread_id):
err.append("title can't be empty")
else:
db.execute("update threads set title = ? where id = ?;",(title,thread_id))
- flash("title updated successfully")
+ flash("title updated titledly")
db.commit()
+
if apply_selected_tags(thread, request.form):
db.commit()
- flash("tags updated successfully")
+ flash("tags updated tagfully")
+
+ if 'lock' in request.form:
+ lock = int(request.form['lock'])
+ if not (lock == 0 or lock == 1):
+ flash("invalid lock value")
+ elif lock != thread['locked']:
+ db.execute("update threads set locked = ? where id = ?",(lock,thread_id))
+ flash("thread " + ("" if lock else "un") + "locked lockfully")
+ db.commit()
if len(err) > 0:
for e in err:
@@ -425,6 +440,5 @@ def config_thread(thread_id):
else:
return redirect(url_for("thread.view_thread",thread_id=thread_id))
-
return render_template("config_thread.html", thread=thread,thread_tags=thread_tags,avail_tags=avail_tags)