Add support for hiding messages in the archives
authorMagnus Hagander <magnus@hagander.net>
Thu, 13 Jun 2013 13:17:44 +0000 (15:17 +0200)
committerMagnus Hagander <magnus@hagander.net>
Thu, 13 Jun 2013 13:17:44 +0000 (15:17 +0200)
Messages are hidden by setting hiddenstatus to one of the values documented
in models.py. We don't currently have a foreign key tracking them, just the
numbers to make things easy.

A secondary table named message_hide_reasons with a log of operations is also
created, but this is maintained completely manually.

We should probably consider creating functions to do the hiding as well as a
nicer API, but that's for another commit.

django/archives/mailarchives/models.py
django/archives/mailarchives/templates/message.html
django/archives/mailarchives/templates/message_flat.html
django/archives/mailarchives/views.py
loader/sql/schema.sql

index 4ce69e2ae44003047e53facebfc69c82a7013011..aaa7d61c3e52452fdb0c96d1ec3e85824f6ffbd9 100644 (file)
@@ -1,5 +1,16 @@
 from django.db import models
 
+# Reason a message was hidden.
+# We're intentionally putting the prefix text in the array here, since
+# we might need that flexibility in the future.
+hide_reasons = [
+       None,                                # placeholder for 0
+       'This message has been hidden because a virus was found in the message.', # 1
+       'This message has been hidden because the message violated policies.',    # 2
+       'This message has been hidden because for privacy reasons.',              # 3
+       ]
+
+
 class Message(models.Model):
        threadid = models.IntegerField(null=False, blank=False)
        mailfrom = models.TextField(null=False, db_column='_from')
@@ -12,6 +23,7 @@ class Message(models.Model):
        # rawtxt is a bytea field, which django doesn't support (easily)
        parentid = models.IntegerField(null=False, blank=False)
        has_attachment = models.BooleanField(null=False, default=False)
+       hiddenstatus = models.IntegerField(null=True)
        # fti is a tsvector field, which django doesn't support (easily)
 
        class Meta:
@@ -35,6 +47,15 @@ class Message(models.Model):
                        self._attachments = self.attachment_set.extra(select={'len': 'length(attachment)'}).all()
                return self._attachments
 
+       @property
+       def hiddenreason(self):
+               if not self.hiddenstatus: return None
+               try:
+                       return hide_reasons[self.hiddenstatus]
+               except:
+                       # Weird value
+                       return 'This message has been hidden.'
+
 class ListGroup(models.Model):
        groupid = models.IntegerField(null=False, primary_key=True)
        groupname = models.CharField(max_length=200, null=False, blank=False)
index 6fda4b14bbb21882728ca420ff9aa941bfba2f37..3e9edbd6e54e6020752e5bae0d3c8eddac73ff32 100644 (file)
@@ -62,6 +62,9 @@ $(function(){
  </tr>
 </table>
 <div class="bodywrapper">
+{%if msg.hiddenstatus%}
+<pre>{{msg.hiddenreason}}</pre>
+{%else%}
 <pre>{{msg.bodytxt|hideallemail|urlize}}</pre>
 
 {%if msg.has_attachment%}
@@ -109,5 +112,6 @@ Description: {{a.contenttype}} ({{a.len|filesizeformat}}) {%if a.inlineable%}(in
 {%endfor%}
 {%endif%}
 
+{%endif%}{%comment%}hidden{%endcomment%}
 </div>
 {%endblock%}
index 7dff03c2c8353d4d548107e68e6ca73011289db0..d1357d57111ed1865226447ee3c57a8e9752b6d1 100644 (file)
@@ -46,6 +46,9 @@ window.onload = load;
  </tr>
 </table>
 <div class="bodywrapper">
+{%if m.hiddenstatus%}
+<pre>{{m.hiddenreason}}</pre>
+{%else%}
 <pre>{{m.bodytxt|hideallemail|urlize}}</pre>
 
 {%if m.has_attachment%}
@@ -58,6 +61,7 @@ Description: {{a.contenttype}} ({{a.len|filesizeformat}})
 {%endif%}
 </div>
 
+{%endif%}{%comment%}hidden{%endcomment%}
 </div>
 {%endfor%}
 {%endblock%}
index 699938bb5af82d47d95f19a6f02224ec40a68ee5..e97240fce6e1218b11570d4c46e314af7555ff78 100644 (file)
@@ -354,14 +354,17 @@ def message_raw(request, msgid):
                        user, pwd = base64.b64decode(auth[1]).split(':')
                        if user == 'archives' and pwd == 'antispam':
                                curs = connection.cursor()
-                               curs.execute("SELECT threadid, rawtxt FROM messages WHERE messageid=%(messageid)s", {
+                               curs.execute("SELECT threadid, hiddenstatus, rawtxt FROM messages WHERE messageid=%(messageid)s", {
                                                'messageid': msgid,
                                                })
                                row = curs.fetchall()
                                if len(row) != 1:
                                        raise Http404('Message does not exist')
 
-                               r = HttpResponse(row[0][1], content_type='text/plain')
+                               if row[0][1]:
+                                       r = HttpResponse('This message has been hidden.', content_type='text/plain')
+                               else:
+                                       r = HttpResponse(row[0][2], content_type='text/plain')
                                r['X-pgthread'] = ":%s:" % row[0][0]
                                return r
                        # Invalid password falls through
index e2d9b1926a6ea1a7ab86d54ae79a9943f41350ab..97585f0160eb445300b13f44d0d79c2077b9d460 100644 (file)
@@ -12,6 +12,7 @@ CREATE TABLE messages (
    subject text NOT NULL,
    date timestamptz NOT NULL,
    has_attachment boolean NOT NULL,
+   hiddenstatus int NULL,
    messageid text NOT NULL,
    bodytxt text NOT NULL,
    rawtxt bytea NOT NULL,
@@ -21,6 +22,13 @@ CREATE INDEX idx_messages_threadid ON messages(threadid);
 CREATE UNIQUE INDEX idx_messages_msgid ON messages(messageid);
 CREATE INDEX idx_messages_date ON messages(date);
 
+CREATE TABLE message_hide_reasons (
+   message int NOT NULL PRIMARY KEY REFERENCES messages,
+   dt timestamptz,
+   reason text,
+   by text
+);
+
 CREATE SEQUENCE threadid_seq;
 
 CREATE TABLE unresolved_messages(