Skip to content

Commit 8b7d69c

Browse files
tgloeggldennis531
andauthored
Only change ROLE_ANONYMOUS in Opencast if explicitly set by user (#1290)
* check if a workflow can run before setting acls * fix typo * only change ROLE_ANONYMOUS if user decided to do so * fix typo * Set visibility in Stud.IP to the one in Opencast * Update lib/Routes/Video/VideoWorldwideShareUpdate.php Co-authored-by: Dennis Benz <[email protected]> * respond with error code 500 in case of error --------- Co-authored-by: Dennis Benz <[email protected]>
1 parent 7be2551 commit 8b7d69c

13 files changed

+218
-161
lines changed

composer.lock

+12-11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/Models/Helpers.php

+45-6
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,10 @@
44

55
use \DBManager;
66
use \PDO;
7-
use \Configuration as StudipConfiguration;
87

9-
use Opencast\LTI\OpencastLTI;
108
use Opencast\VersionHelper;
119
use Opencast\Providers\Perm;
10+
use Opencast\Models\Videos;
1211

1312
class Helpers
1413
{
@@ -302,10 +301,6 @@ public static function filterACLs($acls, $studip_acls)
302301

303302
$possible_roles = array_column($studip_acls, 'role');
304303

305-
if (\Config::get()->OPENCAST_ALLOW_PUBLIC_SHARING) {
306-
$possible_roles[] = 'ROLE_ANONYMOUS';
307-
}
308-
309304
sort($acls);
310305

311306
$result = [];
@@ -372,4 +367,48 @@ public static function notifyUsers($eventType, $event, $video)
372367
);
373368
}
374369
}
370+
371+
/**
372+
* Determines if an event can run a workflow.
373+
*
374+
* This function checks if the given event meets the criteria for running a republish workflow.
375+
* It ensures that:
376+
* 1. The event is not empty
377+
* 2. The event has an 'engage-player' publication status
378+
* 3. The associated video is not in a 'running' or 'failed' state
379+
*
380+
* @param object $event The Opencast event object to check
381+
* @param object $video The associated video object from the Stud.IP system
382+
*
383+
* @return boolean Returns true if the event can run a workflow, false otherwise
384+
*/
385+
public static function canEventRunWorkflow($event, Videos $video)
386+
{
387+
if (empty($event)
388+
|| in_array('engage-player', (array)$event->publication_status) === false
389+
|| $video->state == 'running' || $video->state == 'failed')
390+
{
391+
return false;
392+
}
393+
394+
return true;
395+
}
396+
397+
398+
public static function isWorldReadable($oc_acls)
399+
{
400+
// check if ACL contains ROLE_ANONYMOUS
401+
$has_anonymous_role = false;
402+
foreach ($oc_acls as $acl_entry) {
403+
if ($acl_entry['role'] === 'ROLE_ANONYMOUS'
404+
&& $acl_entry['action'] === 'read'
405+
&& $acl_entry['allow'] === true
406+
) {
407+
$has_anonymous_role = true;
408+
break;
409+
}
410+
}
411+
412+
return $has_anonymous_role;
413+
}
375414
}

lib/Models/REST/ApiEventsClient.php

+12-3
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public function getACL($episode_id)
6161
}
6262

6363
/**
64-
* Sets ACL for an episode in connected Opencast
64+
* Sets ACL for an episode in connected Opencast and republishes metadata
6565
*
6666
* @param string $episode_id id of episode
6767
* @param object $acl the acl object
@@ -70,8 +70,17 @@ public function getACL($episode_id)
7070
*/
7171
public function setACL($episode_id, $acl)
7272
{
73-
$response = $this->opencastApi->eventsApi->updateAcl($episode_id, $acl);
74-
return $response;
73+
$workflow_client = ApiWorkflowsClient::getInstance($this->config_id);
74+
75+
$response = $this->opencastApi->eventsApi->updateAcl($episode_id, array_values($acl));
76+
77+
// republish metadata, if updating the ACL was succesful
78+
if (in_array($response['code'], ['200', '204']) === true) {
79+
$workflow_client->republish($episode_id);
80+
return true;
81+
}
82+
83+
return false;
7584
}
7685

7786
/**

lib/Models/REST/RestClient.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,8 @@ public function fileRequest($file_url)
8383
{
8484
$response = $this->ocRestClient->get($file_url, [
8585
'auth' => [$this->username, $this->password],
86-
'timeout' => 60,
87-
'connect_timeout' => 60,
86+
'timeout' => 2,
87+
'connect_timeout' => 2,
8888
]);
8989

9090
$result = [];

lib/Models/Videos.php

+70-63
Original file line numberDiff line numberDiff line change
@@ -715,7 +715,7 @@ public function updateMetadata($event)
715715
// Only allow updating of metadata if event has publications
716716
$oc_event = $api_event_client->getEpisode($this->episode);
717717

718-
if (empty($oc_event) || in_array('engage-player', (array)$oc_event->publication_status) === false) {
718+
if (!Helpers::canEventRunWorkflow($oc_event, $this)) {
719719
return false;
720720
}
721721

@@ -751,23 +751,6 @@ public function updateMetadata($event)
751751
$response = $api_event_client->updateMetadata($this->episode, $metadata);
752752
$republish = in_array($response['code'], [200, 204]) === true;
753753

754-
$result = null;
755-
756-
if (\Config::get()->OPENCAST_ALLOW_PUBLIC_SHARING
757-
&& $this->visibility != $event['visibility']
758-
) {
759-
$result = $this->updateAcl($event['visibility']);
760-
761-
if ($result['republish']) {
762-
$republish = true;
763-
}
764-
765-
if ($result['update']) {
766-
$this->visibility = $event['visibility'];
767-
$this->store();
768-
}
769-
}
770-
771754
if ($republish) {
772755
$api_wf_client = ApiWorkflowsClient::getInstance($this->config_id);
773756

@@ -817,6 +800,62 @@ public function removeVideo()
817800
return $this->delete();
818801
}
819802

803+
public function setWorldVisibility($visibility)
804+
{
805+
// get current ACL for event in Opencast
806+
$api_client = ApiEventsClient::getInstance($this->config_id);
807+
$current_acl = $api_client->getAcl($this->episode);
808+
809+
if (empty($current_acl)) {
810+
return false;
811+
}
812+
813+
// check if ACL contains ROLE_ANONYMOUS
814+
$has_anonymous_role = Helpers::isWorldReadable($current_acl);
815+
816+
if ($visibility === 'public' && $this->visibility !== 'public') {
817+
if (!$has_anonymous_role) {
818+
// Add ROLE_ANONYMOUS to the ACL
819+
$current_acl[] = [
820+
'allow' => true,
821+
'role' => 'ROLE_ANONYMOUS',
822+
'action' => 'read'
823+
];
824+
825+
// Update the ACL in Opencast
826+
if ($api_client->setACL($this->episode, $current_acl)) {
827+
// Update local visibility
828+
$this->visibility = 'public';
829+
$this->store();
830+
831+
return true;
832+
}
833+
834+
return false;
835+
}
836+
} else if ($visibility !== 'public' && $this->visibility === 'public') {
837+
if ($has_anonymous_role) {
838+
// Remove ROLE_ANONYMOUS from the ACL
839+
$current_acl = array_filter($current_acl, function($acl_entry) {
840+
return $acl_entry['role'] !== 'ROLE_ANONYMOUS';
841+
});
842+
843+
// Update the ACL in Opencast
844+
if ($api_client->setACL($this->episode, $current_acl)) {
845+
// Update local visibility
846+
$this->visibility = $visibility;
847+
$this->store();
848+
849+
return true;
850+
}
851+
852+
return false;
853+
}
854+
}
855+
856+
return true;
857+
}
858+
820859
/**
821860
* Check that the episode has its unique ACL and set it if necessary
822861
*
@@ -831,32 +870,21 @@ public function removeVideo()
831870
public static function checkEventACL($eventType, $episode, $video)
832871
{
833872
// Only allow updating of metadata if event has publications
834-
if (empty($episode) || in_array('engage-player', (array)$episode->publication_status) === false) {
873+
if (!Helpers::canEventRunWorkflow($episode, $video)) {
835874
return;
836875
}
837876

838-
$workflow_client = ApiWorkflowsClient::getInstance($video->config_id);
839-
840-
$results = $video->updateAcl(null, json_decode(json_encode($episode->acl), true));
841-
842-
if ($results['republish'] == true) {
843-
$workflow_client->republish($video->episode);
844-
}
877+
return $video->updateAcl(json_decode(json_encode($episode->acl), true));
845878
}
846879

847880
/**
848881
* Update the ACL in Opencast if necessary
849882
*
850-
* @param string $new_vis The targeted new visibility. If empty, use the current on to check
883+
* @param string $current_acl The current ACL in Opencast
851884
*
852-
* @return array Returns an array of the following form, stating if a republish is necessary and if the
853-
* update in was succesful:
854-
* [
855-
* republish' => boolean
856-
* 'update' => boolean
857-
* ]
885+
* @return bool whether ACL was updated or not
858886
*/
859-
public function updateAcl($new_vis = null, $current_acl = null)
887+
public function updateAcl($current_acl = null)
860888
{
861889
$api_client = ApiEventsClient::getInstance($this->config_id);
862890
if (empty($current_acl)) {
@@ -869,6 +897,12 @@ public function updateAcl($new_vis = null, $current_acl = null)
869897
}
870898

871899
$acl = [];
900+
if (Helpers::isWorldReadable($current_acl)) {
901+
$this->visibility = 'public';
902+
} else {
903+
$this->visibility = 'internal';
904+
}
905+
$this->store();
872906

873907
// Don't set event id roles if episode id role access is activated by user
874908
if (!$this->config->settings['episode_id_role_access'] ?? true) {
@@ -905,44 +939,17 @@ public function updateAcl($new_vis = null, $current_acl = null)
905939

906940
$acl = array_merge($acl, Helpers::createACLsForCourses($courses));
907941

908-
// add anonymous role if video is world visible
909-
if (\Config::get()->OPENCAST_ALLOW_PUBLIC_SHARING && (
910-
($new_vis && $new_vis == 'public')
911-
|| (!$new_vis && $this->visibility == 'public')
912-
)) {
913-
$acl[] = [
914-
'allow' => true,
915-
'role' => 'ROLE_ANONYMOUS',
916-
'action' => 'read'
917-
];
918-
}
919-
920942
sort($acl);
921943

922944
$oc_acls = Helpers::filterACLs($current_acl, $acl);
923945

924946
if ($acl <> $oc_acls['studip']) {
925947
$new_acl = array_merge($oc_acls['other'], $acl);
926948

927-
$result = $api_client->setACL($this->episode, $new_acl);
928-
929-
if (in_array($result['code'], ['200', '204']) === false) {
930-
return [
931-
'republish' => false,
932-
'update' => false
933-
];
934-
}
935-
936-
return [
937-
'republish' => true,
938-
'update' => true
939-
];
949+
return $api_client->setACL($this->episode, $new_acl);
940950
}
941951

942-
return [
943-
'republish' => false,
944-
'update' => true
945-
];
952+
return false;
946953
}
947954

948955
/**

lib/RouteMap.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ public function authenticatedRoutes(RouteCollectorProxy $group)
6565
$group->put("/videos/{token}/shares", Routes\Video\VideoSharesUpdate::class);
6666
$group->post("/videos/{course_id}/copy", Routes\Video\VideoCopyToCourse::class);
6767

68+
$group->put("/videos/{token}/worldwide_share", Routes\Video\VideoWorldwideShareUpdate::class);
69+
6870
// Courseware routes
6971
$group->get("/courseware/videos", Routes\Courseware\CoursewareVideoList::class);
7072

@@ -123,7 +125,6 @@ public function authenticatedRoutes(RouteCollectorProxy $group)
123125
$group->get("/tags/videos/course/{course_id}", Routes\Tags\TagListForCourseVideos::class);
124126

125127
$group->get("/config/simple", Routes\Config\SimpleConfigList::class);
126-
$group->post("/log", Routes\Log\LogEntryCreate::class);
127128

128129
$group->get("/discovery", Routes\DiscoveryIndex::class);
129130
}

0 commit comments

Comments
 (0)