Skip to content

Commit

Permalink
set acls for videos, playlists and series
Browse files Browse the repository at this point in the history
  • Loading branch information
tgloeggl committed Jun 24, 2024
1 parent 6abd1ac commit 4a569eb
Show file tree
Hide file tree
Showing 9 changed files with 265 additions and 76 deletions.
79 changes: 79 additions & 0 deletions cronjobs/opencast_sync_acls.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?php
require_once __DIR__.'/../bootstrap.php';
require_once __DIR__.'/../vendor/autoload.php';

use Opencast\Models\Config;
use Opencast\Models\VideoSync;
use Opencast\Models\Videos;
use Opencast\Models\ScheduleHelper;
use Opencast\Models\REST\ApiEventsClient;
use Opencast\Models\REST\ApiPlaylistsClient;
use Opencast\Models\REST\Config as OCConfig;

class OpencastSyncAcls extends CronJob
{

public static function getName()
{
return _('Opencast - Synchronisiert ACLs für Events');
}

public static function getDescription()
{
return _('Opencast: Synchronisiert ACLs für Events');
}

/**
* Iterate over all videos andf playlists from opencast known to Stud.IP
* and set the correct ACLs accordingly
*
* @param string $last_result
* @param array $parameters
*
* @return void
*/
public function execute($last_result, $parameters = array())
{
$db = DBManager::get();

// iterate over all active configured oc instances
$configs = Config::findBySql('active = 1');

foreach ($configs as $config) {
// check, if this opencast instance is accessible
$version = false;

echo 'working on config '. $config->id ."\n";
$version = OCConfig::getOCBaseVersion($config->id);

if (!$version) {
echo 'cannot connect to opencast, skipping!' ."\n";
continue;
} else {
echo "found opencast with version $version, continuing\n";
}

// update endpoints, just to make sure
$config->updateEndpoints();

// call opencast to get all event ids
$api_client = ApiEventsClient::getInstance($config['id']);

foreach ($api_client->getAll() as $event) {
// only add videos / reinspect videos if they are readily processed
if ($event->status == 'EVENTS.EVENTS.STATUS.PROCESSED') {
// check if video exists in Stud.IP
$video = Videos::findByEpisode($event->identifier);

if ($video->config_id != $config->id) {
echo 'config id mismatch for Video with id: '. $video->id .", $config->id <> {$video->config_id}\n";
continue;
}

Videos::checkEventACL(null, null, $video);
}
}
}
}

}
63 changes: 63 additions & 0 deletions lib/Models/Helpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -264,4 +264,67 @@ public static function ensureCourseHasOneDefaultPlaylist($course_id, $default_pl
$stmt->execute([$course_id, $default_playlist_id]);
return $stmt->rowCount();
}

/**
* Create list of LTI ACLs for the passed courses. Returns an array with the read
* and write ACLs for Instructor and Learner
*
* @param array $course_ids
*
* @return array
*/
public static function createACLsForCourses($course_ids)
{
$acl = [];

foreach ($course_ids as $course_id) {
$acl[] = [
'allow' => true,
'role' => 'STUDIP_'. $course_id . '_Instructor',
'action' => 'read'
];

$acl[] = [
'allow' => true,
'role' => 'STUDIP_'. $course_id . '_Instructor',
'action' => 'write'
];

$acl[] = [
'allow' => true,
'role' => 'STUDIP_'. $course_id . '_Learner',
'action' => 'read'
];
}

return $acl;
}

/**
* Get all ACL entries Stud.IP is responsible for
*
* @param array $acls
*
* @return array
*/
public static function filterACLs($acls)
{
$possible_roles = [
'ROLE_ANONYMOUS'
];

$result = [];
foreach ($acl as $entry) {
if (in_array($entry['role'], $possible_roles) !== false
|| strpos($entry['role'], 'STUDP_') === 0
) {
$result[$entry['role'] .'_'. $entry['action']] = $entry;
}
}

$result = array_values($result);
sort($result);

return $result;
}
}
14 changes: 13 additions & 1 deletion lib/Models/Playlists.php
Original file line number Diff line number Diff line change
Expand Up @@ -407,10 +407,18 @@ public static function checkPlaylistACL($oc_playlist, $playlist)
unset($entry['id']);
});

$old_acl = Helpers::filterACLs($old_acl);

$current_acl = $old_acl;

$acl = self::getPlaylistACL($oc_playlist->id);


$courses = [];
$courses = array_merge($courses, $playlist->courses->pluck('id'));

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

foreach ($acl as $entry) {
$found = false;
foreach ($current_acl as $current_key => &$current_entry) {
Expand All @@ -429,14 +437,18 @@ public static function checkPlaylistACL($oc_playlist, $playlist)
}

if (!$found) {
$current_acl[] = $entry;
$current_acl[$entry['role'] . '_'. $entry['action']] = $entry;
}
}

// Reindex keys
$current_acl = array_values($current_acl);

sort($current_acl);
sort($old_acl);

if ($old_acl <> $current_acl) {
print_r($old_acl <> $current_acl);
$api_client = ApiPlaylistsClient::getInstance($playlist->config_id);
$api_client->updatePlaylist($oc_playlist->id, [
'title' => $oc_playlist->title,
Expand Down
62 changes: 34 additions & 28 deletions lib/Models/REST/SeriesClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public function __construct($config_id = 1)
}

/**
* Retrieves seriesmetadata for a given series identifier from conntected Opencast
* Retrieve series metadata for a given series identifier from Opencast
*
* @param string series_id Identifier for a Series
*
Expand All @@ -39,25 +39,15 @@ public function getSeries($series_id)


/**
* createSeriesForSeminar - creates an new Series for a given course in OC Matterhorn
* Create an new series for a given course in Opencast
*
* @param string $course_id - course identifier
*
* @return bool success or not
*/
public function createSeriesForSeminar($course_id)
{
$acl = [
[
'allow' => true,
'role' => 'ROLE_ADMIN',
'action' => 'read'
],

[
'allow' => true,
'role' => 'ROLE_ADMIN',
'action' => 'write'
],

[
'allow' => true,
'role' => $course_id . '_Instructor',
Expand All @@ -82,9 +72,10 @@ public function createSeriesForSeminar($course_id)
}

/**
* createSeriesDC - creates an xml representation for a new OC-Series
* Create an xml representation for a new OC-series
*
* @param string $course_id
*
* @return string xml - the xml representation of the string
*/
private static function getSeriesDC($course_id)
Expand Down Expand Up @@ -126,25 +117,15 @@ private static function getSeriesDC($course_id)
}

/**
* createSeriesForUser - creates an new Series for a given user in OC Matterhorn
* Create an new Series for a given user in Opencast
*
* @param string $user_id - user identifier
*
* @return bool success or not
*/
public function createSeriesForUser($user_id)
{
$acl = [
[
'allow' => true,
'role' => 'ROLE_ADMIN',
'action' => 'read'
],

[
'allow' => true,
'role' => 'ROLE_ADMIN',
'action' => 'write'
],

[
'allow' => true,
'role' => 'STUDIP_' . $user_id,
Expand Down Expand Up @@ -204,4 +185,29 @@ private static function getSeriesUserDC($user_id)
'fields' => $fields
]];
}

/**
* Return current ACL for passed series
*
* @param string $series_id
*
* @return mixed
*/
public function getACL($series_id)
{
return $this->opencastApi->seriesApi->getACL($series_id);
}

/**
* Replace ACL for passed series
*
* @param string $series_id
* @param array $acl
*
* @return mixed
*/
public function setACL($series_id, $acl)
{
return $this->opencastApi->seriesApi->updateACL($series_id, $acl);
}
}
2 changes: 1 addition & 1 deletion lib/Models/REST/ServicesClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public function __construct($config_id = 1)
}

/**
* Retrieves episode system components from conntected Opencast-Matterhorn Core
* Retrieves episode system components from conntected Opencast Core
*
* @return array|boolean response of components, or false if unable to get
*/
Expand Down
20 changes: 20 additions & 0 deletions lib/Models/SeminarSeries.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,20 @@
namespace Opencast\Models;

use Opencast\Models\REST\SeriesClient;
use \Course;

class SeminarSeries extends \SimpleORMap
{
protected static function configure($config = [])
{
$config['db_table'] = 'oc_seminar_series';

$config['has_many']['courses'] = [
'class_name' => Course::class,
'foreign_key' => 'seminar_id',
'assoc_foreign_key' => 'Seminar_id'
];

parent::configure($config);
}

Expand All @@ -26,6 +34,18 @@ private static function checkSeries($course_id, $series_id)
? true : false;
}

// make sure all ACLs are correctly set
$series = self::findBySeries_id($series_id);

$courses = \SimpleCollection::createFromArray($series)->pluck('seminar_id');

$acl = Helpers::createACLsForCourses($courses);
$oc_acl = Helpers::filterACLs($series_client->getACL($series_id));

if ($acl <> $oc_acl) {
$series_client->setACL($series_id, $acl);
}

return $series[$series_id];
}

Expand Down
Loading

0 comments on commit 4a569eb

Please sign in to comment.