From f5bfc988ec26f596cbb735225ee196f2b8398767 Mon Sep 17 00:00:00 2001
From: Rainer Rillke <rillke@wikipedia.de>
Date: Mon, 25 Nov 2024 11:30:46 +0100
Subject: [PATCH] Only touch ACLs managed by Stud.IP plugin (#1054)

Some time ago, Till told me the Stud.IP Opencast plugin
would only manage episode's ACLs relevant to Stud.IP
where in fact, the plugin would remove ACLs from events
granting permissions in secondary LMSes or other uses.

This approach checks if an existing Opencast ACL is
managed by Stud.IP (hex_Learner/hex_Instructor/
ROLE_ADMIN/ROLE_ANONYMOUS), and if not, it would add
those again to the list of ACLs and check again,
if the list of ACLs sent by Opencast differs from
the list of ACLs to be set.
---
 classes/lti/OpencastLTI.php | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/classes/lti/OpencastLTI.php b/classes/lti/OpencastLTI.php
index 4d914a9d..fdf69f30 100644
--- a/classes/lti/OpencastLTI.php
+++ b/classes/lti/OpencastLTI.php
@@ -352,7 +352,17 @@ class OpencastLTI
 
         // check, if the calculated and actual acls differ and update if so
         if ($oc_acl <> $acl->toArray()) {
-            $client->setACL($target_id, $acl);
+            // To only touch ACLs set by the Stud.IP plugin,
+            // copy over existing ACLs which aren't handled by Stud.IP.
+            foreach ($oc_acl as $oc_acl_entry) {
+                if (!preg_match('~(?:[0-9a-f]{32}_(?:Instructor|Learner)|ROLE_ANONYMOUS|ROLE_ADMIN)~', $oc_acl_entry['role'])) {
+                    $e = new \AccessControlEntity($oc_acl_entry['role'], $oc_acl_entry['action'], $oc_acl_entry['allow']);
+                    $acl->add_ace($e);
+                }
+            }
+            if ($oc_acl <> $acl->toArray()) {
+                $client->setACL($target_id, $acl);
+            }
         }
     }
 
-- 
GitLab