Skip to content

Commit

Permalink
Issue CollaboraOnline#49: Introduce new 'preview own unpublished ...'…
Browse files Browse the repository at this point in the history
… permission.
  • Loading branch information
donquixote committed Nov 12, 2024
1 parent 8acb70d commit 590c560
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 49 deletions.
42 changes: 24 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,24 +197,30 @@ Collabora is used within Drupal. Most of the time this permission is
not needed, if the Collabora instance is configured from outside of
Drupal.

For each media type, the module introduces two permissions:
- (media type): Edit any media file in Collabora Users with this
permission are allowed to edit documents attached to a media entity
of the given type, using the Collabora Online editor.
- (media type): Preview media file in Collabora Users with this
permission are allowed to preview documents attached to a media
entity of the given type, using the Collabora Online editor in
preview/readonly mode.

In the current version, preview and edit access with the Collabora
Online editor are checked independently of the publishing status of
the respective media, and independently of the regular view or edit
access on that media entity.

For a consistent experience, it is recommended that a role with the
edit permission should also be granted the preview permission, and
that a user with any of the Collabora media permissions should also be
granted permissions to view the respective media entity in Drupal.
For each media type, the module introduces four permissions:
- "(media type): Edit any media file in Collabora"
Users with this permission are allowed to edit documents attached
to a media entity of the given type, using the Collabora Online
editor.
- "(media type): Edit own media file in Collabora"
Users with this permission are allowed to edit documents attached
to a media entity of the given type, using the Collabora Online
editor, if they are the owner/author of that media entity.
- "(media type): Preview published media file in Collabora"
Users with this permission are allowed to preview documents attached
to a published media entity of the given type, using the Collabora
Online editor in preview/readonly mode.
- "(media type): Preview own unpublished media file in Collabora"
Users with this permission are allowed to preview documents attached
to an unpublished media entity of the given type, using the Collabora Online
editor in preview/readonly mode.

In the current version of this module, the 'administer media' permission
from Drupal core grants access to all media operations, including the use
of the Collabora Online editor for preview and edit.

For a consistent experience, it is recommended that a role with edit
permissions should also be granted respective preview permissions.

Developers can use entity access hooks to alter which users may edit
or preview media files in Collabora. This would allow to grant access
Expand Down
55 changes: 45 additions & 10 deletions collabora_online.module
Original file line number Diff line number Diff line change
Expand Up @@ -123,24 +123,59 @@ function collabora_online_entity_operation(EntityInterface $entity) {
* Checks access for the new media operations provided by this module.
*/
function collabora_online_media_access(MediaInterface $media, string $operation, AccountInterface $account): AccessResultInterface {
$type = $media->bundle();
switch ($operation) {
case 'preview in collabora':
return AccessResult::allowedIfHasPermission($account, "preview $type in collabora");
$type = $media->bundle();
if ($media->isPublished()) {
return AccessResult::allowedIfHasPermission($account, "preview $type in collabora")
->addCacheableDependency($media);
}
$preview_own_permission = "preview own unpublished $type in collabora";
if (!$account->hasPermission($preview_own_permission)) {
return AccessResult::neutral()
->cachePerPermissions()
->addCacheableDependency($media)
->setReason("The user does not have the '$preview_own_permission' permission.");
}
// Use '==' because Drupal sometimes loads integers as strings.
$is_owner = ($account->id() && $account->id() == $media->getOwnerId());
if ($is_owner) {
$access_result = AccessResult::allowed();
}
else {
$access_result = AccessResult::neutral()
->setReason("The user has the '$preview_own_permission' permission, but is not the owner of the media item.");
}
return $access_result
->cachePerPermissions()
->cachePerUser()
->addCacheableDependency($media);

case 'edit in collabora':
$type = $media->bundle();
if ($account->hasPermission("edit any $type in collabora")) {
return AccessResult::allowed()->cachePerPermissions();
return AccessResult::allowed()
->cachePerPermissions();
}
if ($account->hasPermission("edit own $type in collabora")) {
// Use '==' because Drupal sometimes loads integers as strings.
$is_owner = ($account->id() && $account->id() == $media->getOwnerId());
return AccessResult::allowedIf($is_owner)
$edit_own_permission = "edit own $type in collabora";
if (!$account->hasPermission($edit_own_permission)) {
return AccessResult::neutral()
->cachePerPermissions()
->cachePerUser()
->addCacheableDependency($media);
->setReason("The user does not have the '$edit_own_permission' permission.");
}
// Use '==' because Drupal sometimes loads integers as strings.
$is_owner = ($account->id() && $account->id() == $media->getOwnerId());
if (!$is_owner) {
$access_result = AccessResult::neutral()
->setReason("The user has the '$edit_own_permission' permission, but is not the owner of the media item.");
}
else {
$access_result = AccessResult::allowed();
}
return AccessResult::neutral()->cachePerPermissions();
return $access_result
->cachePerPermissions()
->cachePerUser()
->addCacheableDependency($media);

default:
return AccessResult::neutral();
Expand Down
5 changes: 4 additions & 1 deletion src/CollaboraMediaPermissions.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,10 @@ protected function buildPermissions(MediaTypeInterface $type) {

return [
"preview $type_id in collabora" => [
'title' => $this->t('%type_name: Preview media file in Collabora', $type_params),
'title' => $this->t('%type_name: Preview published media file in Collabora', $type_params),
],
"preview own unpublished $type_id in collabora" => [
'title' => $this->t('%type_name: Preview own unpublished media file in Collabora', $type_params),
],
"edit own $type_id in collabora" => [
'title' => $this->t('%type_name: Edit own media file in Collabora', $type_params),
Expand Down
6 changes: 5 additions & 1 deletion tests/src/Functional/PermissionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,12 @@ static function (array $permission) {
'title' => '<em class="placeholder">Public wiki</em>: Edit own media file in Collabora',
'dependencies' => ['config' => ['media.type.public_wiki']],
],
'preview own unpublished public_wiki in collabora' => [
'title' => '<em class="placeholder">Public wiki</em>: Preview own unpublished media file in Collabora',
'dependencies' => ['config' => ['media.type.public_wiki']],
],
'preview public_wiki in collabora' => [
'title' => '<em class="placeholder">Public wiki</em>: Preview media file in Collabora',
'title' => '<em class="placeholder">Public wiki</em>: Preview published media file in Collabora',
'dependencies' => ['config' => ['media.type.public_wiki']],
],
], $permissions);
Expand Down
46 changes: 28 additions & 18 deletions tests/src/Kernel/CollaboraMediaAccessTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,16 @@ public function testCollaboraMediaAccess(): void {
// Permissions for 'book' do not grant access to 'document'.
'Bookworm' => $this->createUser([
'preview book in collabora',
'preview own unpublished book in collabora',
'edit any book in collabora',
'edit own book in collabora',
]),
'Previewer' => $this->createUser([
'preview document in collabora',
]),
'Sean (preview own)' => $this->createUser([
'preview own unpublished document in collabora',
]),
'Editor' => $this->createUser([
'edit any document in collabora',
]),
Expand All @@ -105,8 +109,11 @@ public function testCollaboraMediaAccess(): void {

/** @var \Drupal\media\MediaInterface[] $media_entities */
$media_entities = [
'published document' => $this->createMediaEntity('document'),
'unpublished document' => $this->createMediaEntity('document', [
"Sean's published document" => $this->createMediaEntity('document', [
'uid' => $accounts['Sean (preview own)']->id(),
]),
"Sean's unpublished document" => $this->createMediaEntity('document', [
'uid' => $accounts['Sean (preview own)']->id(),
'status' => 0,
]),
"Kelly's published document" => $this->createMediaEntity('document', [
Expand All @@ -125,14 +132,15 @@ public function testCollaboraMediaAccess(): void {
'media permissions only' => [],
'Bookworm' => [],
'Previewer' => [
"published document" => ['preview in collabora'],
"unpublished document" => ['preview in collabora'],
"Sean's published document" => ['preview in collabora'],
"Kelly's published document" => ['preview in collabora'],
"Kelly's unpublished document" => ['preview in collabora'],
],
'Sean (preview own)' => [
"Sean's unpublished document" => ['preview in collabora'],
],
'Editor' => [
"published document" => ['edit in collabora'],
"unpublished document" => ['edit in collabora'],
"Sean's published document" => ['edit in collabora'],
"Sean's unpublished document" => ['edit in collabora'],
"Kelly's published document" => ['edit in collabora'],
"Kelly's unpublished document" => ['edit in collabora'],
],
Expand All @@ -141,8 +149,8 @@ public function testCollaboraMediaAccess(): void {
"Kelly's unpublished document" => ['edit in collabora'],
],
'Media admin' => [
"published document" => ['preview in collabora', 'edit in collabora'],
"unpublished document" => ['preview in collabora', 'edit in collabora'],
"Sean's published document" => ['preview in collabora', 'edit in collabora'],
"Sean's unpublished document" => ['preview in collabora', 'edit in collabora'],
"Kelly's published document" => ['preview in collabora', 'edit in collabora'],
"Kelly's unpublished document" => ['preview in collabora', 'edit in collabora'],
],
Expand All @@ -162,14 +170,15 @@ public function testCollaboraMediaAccess(): void {
'media permissions only' => [],
'Bookworm' => [],
'Previewer' => [
"/cool/view/<published document>",
"/cool/view/<unpublished document>",
"/cool/view/<Sean's published document>",
"/cool/view/<Kelly's published document>",
"/cool/view/<Kelly's unpublished document>",
],
'Sean (preview own)' => [
"/cool/view/<Sean's unpublished document>",
],
'Editor' => [
"/cool/edit/<published document>",
"/cool/edit/<unpublished document>",
"/cool/edit/<Sean's published document>",
"/cool/edit/<Sean's unpublished document>",
"/cool/edit/<Kelly's published document>",
"/cool/edit/<Kelly's unpublished document>",
],
Expand All @@ -178,10 +187,10 @@ public function testCollaboraMediaAccess(): void {
"/cool/edit/<Kelly's unpublished document>",
],
'Media admin' => [
"/cool/view/<published document>",
"/cool/edit/<published document>",
"/cool/view/<unpublished document>",
"/cool/edit/<unpublished document>",
"/cool/view/<Sean's published document>",
"/cool/edit/<Sean's published document>",
"/cool/view/<Sean's unpublished document>",
"/cool/edit/<Sean's unpublished document>",
"/cool/view/<Kelly's published document>",
"/cool/edit/<Kelly's published document>",
"/cool/view/<Kelly's unpublished document>",
Expand All @@ -202,6 +211,7 @@ public function testCollaboraMediaAccess(): void {
*/
public function testAnonymousOwnAccess(): void {
user_role_grant_permissions(RoleInterface::ANONYMOUS_ID, [
'preview own unpublished document in collabora',
'edit own document in collabora',
]);

Expand Down
6 changes: 5 additions & 1 deletion tests/src/Kernel/PermissionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,12 @@ static function (array $permission) {
'title' => '<em class="placeholder">Public wiki</em>: Edit own media file in Collabora',
'dependencies' => ['config' => ['media.type.public_wiki']],
],
'preview own unpublished public_wiki in collabora' => [
'title' => '<em class="placeholder">Public wiki</em>: Preview own unpublished media file in Collabora',
'dependencies' => ['config' => ['media.type.public_wiki']],
],
'preview public_wiki in collabora' => [
'title' => '<em class="placeholder">Public wiki</em>: Preview media file in Collabora',
'title' => '<em class="placeholder">Public wiki</em>: Preview published media file in Collabora',
'dependencies' => ['config' => ['media.type.public_wiki']],
],
], $permissions);
Expand Down

0 comments on commit 590c560

Please sign in to comment.