Bubble [main]

Admin can lock threads permanently; bumped version to 9.24

cea9cd38945130b4def1f13ec768f6a22ce39912
diff --git a/50_bubble.py b/50_bubble.py
index 080e552..b0fa21e 100644
--- a/50_bubble.py
+++ b/50_bubble.py
@@ -18,7 +18,7 @@ from utils import *
 from worker import *
 
 
-__version__ = '9.23'
+__version__ = '9.24'
 
 
 class Bubble:
@@ -211,7 +211,7 @@ Bubble is open source:
                 return False
             if self.user.role == User.ADMIN:
                 return True
-            if post.flags & Post.LOCKED_FLAG:
+            if post.flags & (Post.LOCKED_FLAG | Post.ADMIN_LOCKED_FLAG):
                 return False
             return True
 
diff --git a/composer.py b/composer.py
index 629b305..95ed3ee 100644
--- a/composer.py
+++ b/composer.py
@@ -531,7 +531,8 @@ def make_comment(session):
     post = db.get_post(post_id)
     if not post:
         return 51, 'Not found'
-    if post.flags & Post.LOCKED_FLAG and session.user.role != User.ADMIN:
+    if post.flags & (Post.LOCKED_FLAG | Post.ADMIN_LOCKED_FLAG) and \
+            session.user.role != User.ADMIN:
         return 61, 'Post is locked'
 
     special = None
diff --git a/feeds.py b/feeds.py
index ca37b6b..0cd7e7e 100644
--- a/feeds.py
+++ b/feeds.py
@@ -243,10 +243,13 @@ def make_post_page_or_configure_feed(session):
                 actions.append(f'=> /edit-tags/{post.id} ๐Ÿท๏ธ Add/remove tags\n')
             actions.append(f'=> /remind/{post.id} ๐Ÿ”” Remind me\n')
             if session.is_lockable(post):
-                if post.flags & Post.LOCKED_FLAG:
-                    actions.append(f'=> /unlock/{post.id} ๐Ÿ”“ Unlock comments\n')
-                else:
-                    actions.append(f'=> /lock/{post.id} ๐Ÿ”’ Lock comments\n')
+                lock_flags = post.flags & (Post.LOCKED_FLAG | Post.ADMIN_LOCKED_FLAG)
+                if session.user.role == User.ADMIN or (session.user.role == User.BASIC and
+                                                       not lock_flags & Post.ADMIN_LOCKED_FLAG):
+                    if lock_flags:
+                        actions.append(f'=> /unlock/{post.id} ๐Ÿ”“ Unlock comments\n')
+                    else:
+                        actions.append(f'=> /lock/{post.id} ๐Ÿ”’ Lock comments\n')
             if session.is_moderated(post) and post.user != session.user.id:
                 if session.user.role == User.ADMIN:
                     actions.append(f'=> /settings/flair/{post.poster_name}/add/ ๐Ÿ“› Set flair on {post.poster_name}\n')
@@ -490,7 +493,9 @@ def make_post_page(session, post):
                 listed.append(f'{r} {reactions[r]}')
             if listed:
                 page += ' ยท ' + ' '.join(listed)
-        if post.flags & Post.LOCKED_FLAG:
+        if post.flags & Post.ADMIN_LOCKED_FLAG:
+            page += '\n๐Ÿ”’ Locked by Admin'
+        elif post.flags & Post.LOCKED_FLAG:
             page += '\n๐Ÿ”’ Locked'
         page += '\n'
 
diff --git a/model.py b/model.py
index 23f0232..ea2dfa6 100644
--- a/model.py
+++ b/model.py
@@ -505,6 +505,7 @@ class Post:
     OMIT_FROM_ALL_FLAG         = 0x2
     DISABLE_FEATURED_LINK_FLAG = 0x4
     LOCKED_FLAG                = 0x8
+    ADMIN_LOCKED_FLAG          = 0x10 # Admin only
 
     SORT_CREATED, SORT_ACTIVE, SORT_HOTNESS = range(3)
 
diff --git a/user.py b/user.py
index bb4ac3c..fa7f005 100644
--- a/user.py
+++ b/user.py
@@ -42,7 +42,14 @@ def user_actions(session):
             return 51, 'Not found'
         if not session.is_lockable(post):
             return 60, 'Not authorized'
-        db.update_post(post, flags=post.flags ^ Post.LOCKED_FLAG)
+        flags = post.flags
+        # Admin sets both lock flags, while normal users can only set the normal lock flag.
+        lock_flag = Post.LOCKED_FLAG | (Post.ADMIN_LOCKED_FLAG if user.role == User.ADMIN else 0)
+        if action == 'lock':
+            flags |= lock_flag
+        else:
+            flags &= ~lock_flag
+        db.update_post(post, flags=flags)
         return 30, post.page_url() + '/more'
 
     elif req.path.startswith(session.path + 'react/') or \