From: <r2...@mi...> - 2024-03-09 13:37:13
|
Hello Everyone, I would like to restrict the unlinking (and relinking) of issues / messages / files for "user" roles and only allow it for "admin" roles. Is this possible with some access control rules, or should I just purge the "remove" button from the html template? Thanks in advance! -- Have a nice day! r2d2 |
From: John R. <ro...@ie...> - 2024-03-17 03:04:05
|
Hi all: It appears that my main email site can't send anything to sourceforge lists. sorry if this becomes a repeat. Hi r2d2: In message <41480b6e88f1bebfbb89e364b7108d119b633b3a@mirakel.one>, r2d2@mirakel.one writes: >I would like to restrict the unlinking (and relinking) of issues / >messages / files for "user" roles and only allow it for "admin" >roles. Adding/removing an item from the messages multilink is audited. So you will have a record of what happened in any case. Setting the whole messages multilink will be recorded as well but I am not sure if the history shows multiple add/remove or a single set in the history. Ralf any idea? >Is this possible with some access control rules, Unlinking can be stopped by an auditor. The idea is (untested and probably uninterpretable Python like code below): audit(db, cl, itemid, newdata) # Is the user changing messages if 'messages' not in newdata: return # Is the user removing or replacing a message? current_messages = cl.get(itemid, 'messages') new_messages = newdata['messages'] removed = [message for message in current_messages if message not in new_messages] if not removed: return # If the user is an Admin hasPermission always passes, but # let's say we wanted to add a user who can edit messages # if they have the moderator permission. # # See: https://roundup-tracker.org/docs/customizing.html#restricting-the-list-of-users-that-are-assignable-to-a-task if not db.security.hasPermission('moderator', userid, cl.classname): raise ValueError('User %s does not have moderator role, ' 'and can not remove messages from an issue') Note that this code doesn't quite do what you think it would: if len(newdata['messages'] > len(cl.get(itemid, 'messages')): # user made a comment and is adding to the messages (NOT!) return While @remove can only remove, not replace, items in the messages list, a set/edit operation can. So I could remove item id 10 and replace it with item id 55 in one transaction. This preserves the length of the list. This could be done using the Rest interface as well. If I am wrong, somebody can correct me. Detecting re-adding is a bit trickier. Adding (by commenting) and re-adding look kind of identical from the auditor's viewpoint. There is no database method to report if a message id was previously assigned to the issue. However for new messages/comments the message id being added will either: be missing from the db as the transaction to create the msg and update the db isn't committed yet. So cl.db.msg(added_message_id, 'creation') will raise an exception. I think this is the correct case. have its creation date within a second or two of now() and the creator will be the current user. To detect re-adding, you can create a "removed_messages" property and look to see if your added message: added = [message for message in new_messages if message not in current_messages] is in the "removed_messages" property. An auditor would have to keep the removed_messages property list up to date. Another way is to grovel through the issue's history and look for entries that remove/unlink or set (possibly replacing one or more message ids) the messages property. You would start from the current values of messages and walk backward through history recording any unlinked items and calculating any removed items when a set operation happens. Can it be done, yes. Is checking for re-adding worth it? Probably not. If a user tries to add a currently existing message, it won't do anything as you can't have duplicates in the messages list. >or should I just purge the "remove" button from the html template? Removing the button will stop people from accidentally unlinking a message. But they can still unlink the message by sending the correct URL request to the server. Depending on your threat profile, removing the button could be fine. You can show the "remove" button only to Admin users. This bit of TAL (edited from one of my trackers) shows the remove form/button only if the user has the Admin role. <form method="POST" tal:condition="python:request.user.hasRole('Admin')"" tal:attributes="action string:issue${context/id}"> <input type="hidden" name="@remove@messages" tal:attributes="value msg/id"> <input type="hidden" name="@action" value="edit"> <input name="@csrf" type="hidden" tal:attributes="value python:utils.anti_csrf_nonce()"> <input type="submit" name="remove" value="remove" i18n:attributes="value"> </form> Hope this helps. -- rouilj |