LOC-11 Implementing auto-closure of rooms
LOC-11 Implementing auto-closure of rooms

If a room has no activity for the configured period (currently 6 hours) it should automatically be closed:

- Any messages are scrubbed
- Any user records are scrubbed
- User sessions purged
- Failure messages removed
- Room record removed

Ran a test with the interval configured to 60 seconds. Created room, posted and left. Stdout output (with a print added) was

{noformat}
1526731411.929024 Request start
{u'action': u'schedulerTrigger', u'pass': u'eGET8AfbG9y2BWjDZjg3BoiKuXdyU32CE1dnyJ8FJsuRtxuZ5LvMqoLVIhkQ3gx8'}
127.0.0.1 - - [19/May/2018 13:03:31] "POST / HTTP/1.1" 200 -
1526731471.993863 Request start
{u'action': u'schedulerTrigger', u'pass': u'eGET8AfbG9y2BWjDZjg3BoiKuXdyU32CE1dnyJ8FJsuRtxuZ5LvMqoLVIhkQ3gx8'}
(1, u'BenTest2')
127.0.0.1 - - [19/May/2018 13:04:31] "POST / HTTP/1.1" 200 -
1526731532.039276 Request start
{u'action': u'schedulerTrigger', u'pass': u'eGET8AfbG9y2BWjDZjg3BoiKuXdyU32CE1dnyJ8FJsuRtxuZ5LvMqoLVIhkQ3gx8'}
127.0.0.1 - - [19/May/2018 13:05:32] "POST / HTTP/1.1" 200 -
{noformat}

So I'm happy the purge is running.

This absolutely should not be relied on as an alternative to running {{/room close [pass]}} though. It's meant as a safety net and nothing more.

--- a/server/LocalChat.py
+++ b/server/LocalChat.py
@@ -55,7 +55,7 @@
 class MsgHandler(object):
 
 
-    def __init__(self,cronpass,bindpoint,purgeinterval):
+    def __init__(self,cronpass,bindpoint,purgeinterval,closethresh):
         self.conn = False
         self.cursor = False
         # Generate a key for encryption of SYSTEM messages (LOC-13)
@@ -64,6 +64,7 @@
         self.cronpass = cronpass
         self.bindpoint = bindpoint
         self.purgeInterval = purgeinterval
+        self.roomCloseThresh = closethresh
 
 
 
@@ -671,6 +672,8 @@
         # Tidy messages older than 10 minutes
         self.tidyMsgs(time.time() - self.purgeInterval);
         
+        # Auto-close any rooms beyond the threshold
+        self.autoCloseRooms()
         
         return {'status':'ok'}
         
@@ -691,6 +694,28 @@
 
         # Tidy away any failure messages
         self.cursor.execute("DELETE FROM failuremsgs  where expires < ?",(time.time(),))
+
+
+
+
+    def autoCloseRooms(self):
+        ''' Automatically close any rooms that have been sat idle for too long
+        '''
+        
+        self.cursor.execute("SELECT id,name from rooms where lastactivity < ? and lastactivity > 0",(time.time() - self.roomCloseThresh,))
+        rooms = self.cursor.fetchall()
+        
+        # Messages probably have been auto-purged, but make sure
+        for r in rooms:
+            self.cursor.execute("DELETE FROM messages where room=?",(r[0],))
+            self.cursor.execute("DELETE FROM failuremsgs where room=?",(r[0],))
+            self.cursor.execute("DELETE FROM users where room=?",(r[0],))
+            self.cursor.execute("DELETE FROM sessions where sesskey like ?", (r[1] + '-%',))
+            self.cursor.execute("DELETE FROM rooms where id=?",(r[0],))
+            self.conn.commit()
+            
+            
+        
 
 
 
@@ -817,12 +842,13 @@
     passw = ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits).encode('utf-8') for _ in range(64))
     bindpoint = "https://127.0.0.1:8090" 
     purgeinterval = 600 # Wipe messages older than 10 mins
+    closethresh = 3600 * 6 # Auto-close rooms after 6 hours of inactivity
 
     # Create a global instance of the wrapper so that state can be retained
     #
     # We pass in the password we generated for the scheduler thread to use
     # as well as the URL it should POST to
-    msghandler = MsgHandler(passw,bindpoint,purgeinterval)
+    msghandler = MsgHandler(passw,bindpoint,purgeinterval,closethresh)
 
 
     # Bind to PORT if defined, otherwise default to 8090.