diff --git a/db/sqlite.py b/db/sqlite.py index 0d72f44..e8d9abc 100644 --- a/db/sqlite.py +++ b/db/sqlite.py @@ -35,24 +35,49 @@ class DB: (forum_id,) ).fetchone() - def get_threads(self, forum_id, offset, limit): + def get_threads(self, forum_id, offset, limit, user_id): return self._db().execute(''' - select t.thread_id, title, t.create_time, t.update_time, t.author_id, name, count(c.thread_id) - from threads t, users - left join comments c on t.thread_id = c.thread_id - where forum_id = ? and user_id = t.author_id + select + t.thread_id, + title, + t.create_time, + t.update_time, + t.author_id, + name, + count(c.thread_id), + t.hidden + from + threads t, + users + left join + comments c + on + t.thread_id = c.thread_id + where forum_id = ? + and user_id = t.author_id + and ( + t.hidden = 0 or ( + select 1 from users + where user_id = ? + and ( + user_id = t.author_id + -- 1 = moderator, 2 = admin + or role in (1, 2) + ) + ) + ) group by t.thread_id order by t.update_time desc limit ? offset ? ''', - (forum_id, limit, offset) + (forum_id, user_id, limit, offset) ) def get_thread(self, thread): db = self._db() - title, text, author, author_id, create_time, modify_time = db.execute(''' - select title, text, name, author_id, create_time, modify_time + title, text, author, author_id, create_time, modify_time, hidden = db.execute(''' + select title, text, name, author_id, create_time, modify_time, hidden from threads, users where thread_id = ? and author_id = user_id ''', @@ -67,7 +92,7 @@ class DB: ''', (thread,) ) - return title, text, author, author_id, create_time, modify_time, comments + return title, text, author, author_id, create_time, modify_time, comments, hidden def get_thread_title(self, thread_id): return self._db().execute(''' @@ -475,6 +500,15 @@ class DB: (role, user_id) ) + def set_thread_hidden(self, thread_id, hide): + return self.change_one(''' + update threads + set hidden = ? + where thread_id = ? + ''', + (hide, thread_id) + ) + def change_one(self, query, values): db = self._db() c = db.cursor() diff --git a/main.py b/main.py index 97ac77d..07a3651 100644 --- a/main.py +++ b/main.py @@ -1,4 +1,4 @@ -VERSION = 'agreper-v0.1' +VERSION = 'agreper-v0.1.1' # TODO put in config table THREADS_PER_PAGE = 50 @@ -42,7 +42,8 @@ def index(): def forum(forum_id): title, description = db.get_forum(forum_id) offset = int(request.args.get('p', 0)) - threads = [*db.get_threads(forum_id, offset, THREADS_PER_PAGE + 1)] + user_id = session.get('user_id', -1) + threads = [*db.get_threads(forum_id, offset, THREADS_PER_PAGE + 1, user_id)] if len(threads) == THREADS_PER_PAGE + 1: threads.pop() next_page = offset + THREADS_PER_PAGE @@ -63,7 +64,7 @@ def forum(forum_id): @app.route('/thread//') def thread(thread_id): user_id = session.get('user_id') - title, text, author, author_id, create_time, modify_time, comments = db.get_thread(thread_id) + title, text, author, author_id, create_time, modify_time, comments, hidden = db.get_thread(thread_id) comments = create_comment_tree(comments) return render_template( 'thread.html', @@ -74,6 +75,7 @@ def thread(thread_id): author = author, author_id = author_id, thread_id = thread_id, + hidden = hidden, create_time = create_time, modify_time = modify_time, comments = comments, @@ -574,6 +576,25 @@ def admin_restart(): restart() return redirect(url_for('admin')) +@app.route('/thread//hide/', methods = ['POST']) +def set_hide_thread(thread_id): + chk, user = _moderator_check() + if not chk: + return user + + try: + print(request.form['hide']) + hide = request.form['hide'] != '0' + hide_str = 'Hidden' if hide else 'Unhidden' + if db.set_thread_hidden(thread_id, hide): + flash(f'{hide_str} thread', 'success') + else: + flash(f'Failed to {hide_str.lower()} thread', 'error') + except Exception as e: + flash(str(e), 'error') + + return redirect(request.form['redirect']) + # TODO can probably be a static-esque page, maybe? @app.route('/help/') def help(): diff --git a/templates/forum.html b/templates/forum.html index 7c4350f..ac7c1f4 100644 --- a/templates/forum.html +++ b/templates/forum.html @@ -1,4 +1,5 @@ {% extends 'base.html' %} +{%- from 'moderator.html' import moderate_thread with context %} {%- macro nav() -%}

@@ -19,14 +20,22 @@ Created Updated Comments + {%- if user is not none and user.is_moderator() -%} + Action + {%- endif -%} - {% for id, title, ctime, utime, author_id, author, comment_count in threads %} + {% for id, title, ctime, utime, author_id, author, comment_count, hidden in threads %} - {{ title }} + {{ '[hidden] ' if hidden else '' }}{{ title }} {{ author }} {{ format_since(ctime) }} {{ format_since(utime) }} {{ comment_count }} + + {%- if user is not none and user.is_moderator() %} + {{- moderate_thread(id, hidden) }} + {%- endif -%} + {%- endfor -%} diff --git a/templates/moderator.html b/templates/moderator.html new file mode 100644 index 0000000..dd9ab2d --- /dev/null +++ b/templates/moderator.html @@ -0,0 +1,7 @@ +{% macro moderate_thread(id, hidden) %} +

+ + + +
+{% endmacro %} diff --git a/templates/thread.html b/templates/thread.html index 80a6c62..049a636 100644 --- a/templates/thread.html +++ b/templates/thread.html @@ -1,8 +1,12 @@ {%- extends 'base.html' %} {%- from 'comment.html' import render_comment, reply, thread_author with context %} +{%- from 'moderator.html' import moderate_thread with context %} {%- block content %} -{{ thread_author(author_id, author, create_time, modify_time) }} +{%- if user is not none and user.is_moderator() -%} +

{{ moderate_thread(thread_id, hidden) }}

+{%- endif -%} +{{- thread_author(author_id, author, create_time, modify_time) }}

{{ minimd(text) | safe }}

{{- reply() }} diff --git a/upgrade/sqlite/v0.1.sh b/upgrade/sqlite/v0.1.sh new file mode 100644 index 0000000..8c1b7f0 --- /dev/null +++ b/upgrade/sqlite/v0.1.sh @@ -0,0 +1,9 @@ +set -ex +test $# == 1 +"$SQLITE" "$1" " +begin exclusive; + alter table threads rename dead to hidden; + alter table comments rename dead to hidden; + update config set version = 'agreper-v0.1.1'; +end; +" diff --git a/upgrade_sqlite.sh b/upgrade_sqlite.sh new file mode 100755 index 0000000..c845868 --- /dev/null +++ b/upgrade_sqlite.sh @@ -0,0 +1,82 @@ +#!/usr/bin/env bash + +# Script to upgrade a database from one version to another by adding columns, +# tables etc. + +LAST_VERSION=agreper-v0.1.1 + +SQLITE=sqlite3 + +export SQLITE + +set -e + +if [ $# -lt 1 ] +then + echo "Usage: $0 [--no-backup]" >&2 + exit 1 +fi + +make_backup=0 + +if [ $# -ge 2 ] +then + case "$2" in + --no-backup) + make_backup=1 + ;; + *) + echo "Unknown option $2" + exit 1 + ;; + esac +fi + +if ! [ -f "$1" ] +then + echo "Database '$1' doesn't exist" >&2 + exit 1 +fi + +version=$(sqlite3 "$1" 'select version from config') + +while true +do + case "$version" in + # Last version, do nothing + agreper-v0.1.1) + echo "$version is the latest version" + exit 0 + ;; + # Try to upgrade + agreper-*) + echo "Upgrading from $version" + + if [ $make_backup ] + then + backup="$1.bak-$version" + if [ -f "$backup" ] + then + echo "Backup '$backup' already exists (did a previous upgrade fail?)" >&2 + exit 1 + fi + echo "Creating backup of $1 at $backup" + cp --reflink=auto "$1" "$backup" + make_backup=1 + fi + + script="./upgrade/sqlite/${version#agreper-}.sh" + if ! bash "$script" "$1" + then + echo "Error while executing $script" + exit 1 + fi + ;; + # Unrecognized version + *) + echo "Unknown version $version" >&2 + exit 1 + ;; + esac + version=$(sqlite3 "$1" 'select version from config') +done