changeset 8544:e738377b4ffe

feature: add detector that prevents file content changes by Admin and other users. New detector and upgrading announcement. Also example of stripping content editing from the User role.
author John Rouillard <rouilj@ieee.org>
date Tue, 24 Mar 2026 22:11:27 -0400
parents 1ffa1f42e1da
children 695399dea532
files CHANGES.txt detectors/README.txt detectors/immutable_file_contents.py doc/upgrading.txt
diffstat 4 files changed, 73 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGES.txt	Tue Mar 24 21:30:47 2026 -0400
+++ b/CHANGES.txt	Tue Mar 24 22:11:27 2026 -0400
@@ -96,7 +96,15 @@
   plain text. Faster then beautifulsoup4 and it passes the html 5
   standard browser test suite. Beautifulsoup is still supported. (John
   Rouillard)
-
+- add a new detector: immutable_file_contents.py that prevents changes
+  to file contents. By default, the permissions assigned to FileClass
+  based classes (files, msgs) do not prevent editing of file contents.
+  While the usual HTML templates don't provide a way to modify files,
+  the REST interface allows changing file contents without an audit
+  trail. Manually driving the HTML interface (via curl for example)
+  also allows content changes. The new detector prevents changes to
+  file contents via Roundup even by a user with admin rights.
+  
 2025-07-13 2.5.0
 
 Fixed:
--- a/detectors/README.txt	Tue Mar 24 21:30:47 2026 -0400
+++ b/detectors/README.txt	Tue Mar 24 22:11:27 2026 -0400
@@ -19,6 +19,10 @@
 emailauditor.py - Rename .eml files (from email multi-part bodies) to
                   .mht so they can be downloaded/viewed in Internet Explorer.
 
+immutable_file_contents.py - prevent changes to the contents property
+                             of file and msg classes including by
+                             people with the admin role.
+
 irker.py - communicate with irkerd to allow roundtup to send announcements
            to an IRC channel.
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/detectors/immutable_file_contents.py	Tue Mar 24 22:11:27 2026 -0400
@@ -0,0 +1,22 @@
+# HTML pages don't provide a way to change the contents of a file.
+# However REST does allow setting content and the HTML interface can
+# be directed to update the content as well. This detector
+# prevents changes to file content.
+
+from roundup.exceptions import UsageError
+
+def immutable_file_contents(db, cl, nodeid, newvalues):
+    ''' Prevent content changes to a file
+    '''
+    if 'content' in newvalues:
+        raise UsageError("File contents are immutable. "
+                         "Rejecting change to contents.")
+
+
+def init(db):
+    """If you have other FileClass based classes add them here."""
+
+    # fire before changes are made
+    db.file.audit('set', immutable_file_contents)
+    db.msg.audit('set', immutable_file_contents)
+
--- a/doc/upgrading.txt	Tue Mar 24 21:30:47 2026 -0400
+++ b/doc/upgrading.txt	Tue Mar 24 22:11:27 2026 -0400
@@ -303,6 +303,44 @@
 There have been some internal refactorings and improvements in the
 REST code that will make it a bit faster.
 
+Make File Contents Immutable for Everybody (optional)
+-----------------------------------------------------
+
+The HTML based interface for files and messages doesn't provide a way
+to change file content. However it is possible for privileged people
+to modify the content via the web. In most cases, this change will not
+be recorded in the audit log. It can be detected by looking at the
+change time of the file. Then compare it to the change time of files
+before and after it. Since files are created in order, the file
+``msg50`` should have a change timestamp after ``msg49`` and before
+``msg51``.
+
+The 2.6.0 release includes an immutable_file_contents.py
+detector.  If you copy the detector into your tracker's detector
+directory nobody, including users with admin rights, can change
+file/msg contents via Roundup. Changes to files would have to be
+done by logging into the Roundup server and editing the files
+locally.
+
+For non-admin user's the following edit permission for FileClass based
+classes will prevent regular users from changing file content via
+Roundup. Remove the existing ``Edit`` permission from your FileClass
+based classes. Then add your classname to the loop. The permission
+strips ``content`` from the list of editable properties and permits
+editing of the other properties::
+
+  for cl in 'file', 'msg':
+    properties = list(x for x in
+                   db.getclass(cl).getprops(protected=False).keys()
+                   if x != 'content')
+
+    file_edit_perm = db.security.addPermission(
+        name='Edit', klass=cl,
+        properties=properties,
+        description="User is allowed to edit all %s props except content" % cl)
+
+    db.security.addPermissionToRole('User', file_edit_perm)
+
 .. index:: Upgrading; 2.4.0 to 2.5.0
 
 Migrating from 2.4.0 to 2.5.0

Roundup Issue Tracker: http://roundup-tracker.org/