-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WIP] Issue #27: Fix permissions #29
base: main
Are you sure you want to change the base?
Changes from all commits
b28b42d
dcaf2e8
6d0f91c
67f330a
48e64d5
864381b
958e303
97dae81
b388a45
54f92b9
7f3eb61
8f144b6
f1ca49f
71c2c47
8e39e10
d424b78
46b5b5f
ca80fee
805efa2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
administer collabora instance: | ||
title: 'Administer the Collabora instance' | ||
restrict access: true | ||
|
||
permission_callbacks: | ||
- \Drupal\collabora_online\CollaboraMediaPermissions::mediaTypePermissions |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,6 +11,7 @@ | |
} | ||
], | ||
"require": { | ||
"php": ">=8.1", | ||
"drupal/jwt": "^2.0" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
collabora_online.settings: | ||
type: config_object | ||
label: 'Settings' | ||
mapping: | ||
cool: | ||
type: config_object | ||
label: 'Cool' | ||
mapping: | ||
server: | ||
type: uri | ||
label: 'The address of the COOL server.' | ||
wopi_base: | ||
type: uri | ||
label: 'The WOPI base' | ||
key_id: | ||
type: string | ||
label: 'The JWT key id' | ||
access_token_ttl: | ||
type: integer | ||
label: 'Access Token TTL' | ||
disable_cert_check: | ||
type: boolean | ||
label: 'Disable cert checks.' |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
<?php | ||
hfiguiere marked this conversation as resolved.
Show resolved
Hide resolved
|
||
/* | ||
* Copyright the Collabora Online contributors. | ||
* | ||
* SPDX-License-Identifier: MPL-2.0 | ||
* | ||
* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
*/ | ||
|
||
namespace Drupal\collabora_online; | ||
|
||
use Drupal\Core\DependencyInjection\AutowireTrait; | ||
use Drupal\Core\DependencyInjection\ContainerInjectionInterface; | ||
use Drupal\Core\Entity\BundlePermissionHandlerTrait; | ||
use Drupal\Core\Entity\EntityTypeManagerInterface; | ||
use Drupal\Core\StringTranslation\StringTranslationTrait; | ||
use Drupal\media\MediaTypeInterface; | ||
use Symfony\Component\DependencyInjection\ContainerInterface; | ||
|
||
/** | ||
* Provides permissions for Collabora per media type. | ||
* | ||
* @see \Drupal\media\MediaPermissions | ||
*/ | ||
class CollaboraMediaPermissions implements ContainerInjectionInterface { | ||
|
||
use AutowireTrait; | ||
use BundlePermissionHandlerTrait; | ||
use StringTranslationTrait; | ||
|
||
/** | ||
* Constructor. | ||
* | ||
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager | ||
* The entity type manager service. | ||
*/ | ||
public function __construct( | ||
protected readonly EntityTypeManagerInterface $entityTypeManager, | ||
) {} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public static function create(ContainerInterface $container) { | ||
return new static($container->get('entity_type.manager')); | ||
} | ||
|
||
/** | ||
* Returns an array of media type permissions. | ||
* | ||
* @return array | ||
* The media type permissions. | ||
* | ||
* @see \Drupal\user\PermissionHandlerInterface::getPermissions() | ||
*/ | ||
public function mediaTypePermissions(): array { | ||
// Generate media permissions for all media types. | ||
$media_types = $this->entityTypeManager->getStorage('media_type')->loadMultiple(); | ||
return $this->generatePermissions($media_types, [$this, 'buildPermissions']); | ||
} | ||
|
||
/** | ||
* Returns a list of permissions for a given media type. | ||
* | ||
* @param \Drupal\media\MediaTypeInterface $type | ||
* The media type. | ||
* | ||
* @return array | ||
* An associative array of permission names and descriptions. | ||
*/ | ||
protected function buildPermissions(MediaTypeInterface $type) { | ||
$type_id = $type->id(); | ||
$type_params = ['%type_name' => $type->label()]; | ||
|
||
return [ | ||
"preview $type_id in collabora" => [ | ||
'title' => $this->t('%type_name: Preview 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), | ||
], | ||
"edit any $type_id in collabora" => [ | ||
'title' => $this->t('%type_name: Edit any media file in Collabora', $type_params), | ||
], | ||
]; | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,14 +11,12 @@ | |
|
||
namespace Drupal\collabora_online\Controller; | ||
|
||
use Drupal\collabora_online\Cool\CoolUtils; | ||
use Drupal\Core\Controller\ControllerBase; | ||
use Drupal\Core\Render\RendererInterface; | ||
use Drupal\collabora_online\Cool\CoolUtils; | ||
use Drupal\file\Entity\File; | ||
use Drupal\media\Entity\Media; | ||
use Symfony\Component\DependencyInjection\ContainerInterface; | ||
use Symfony\Component\HttpFoundation\Response; | ||
use Symfony\Component\HttpFoundation\Request; | ||
|
||
/** | ||
* Provides route responses for the Collabora module. | ||
|
@@ -55,22 +53,6 @@ public function editor(Media $media, $edit = false) { | |
'closebutton' => 'true', | ||
]; | ||
|
||
$user = \Drupal::currentUser(); | ||
$permissions = CoolUtils::getUserPermissions($user); | ||
|
||
if (!$permissions['is_viewer']) { | ||
$error_msg = 'Authentication failed.'; | ||
\Drupal::logger('cool')->error($error_msg); | ||
return new Response( | ||
$error_msg, | ||
Response::HTTP_FORBIDDEN, | ||
['content-type' => 'text/plain'] | ||
); | ||
} | ||
|
||
/* Make sure that the user is a collaborator if edit is true */ | ||
$edit = $edit && $permissions['is_collaborator']; | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How do we check about the write permission? The code above make sure that if you get an "editor" but don't have write permission as per drupal, then you get bounced back to a read-only. It also reject if you don't have viewing permission. This is better than WOPI errors in Collabora online. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Permissions are set at the entity level and can be found in the collabora_online.module. They handle actions like viewing and editing documents. These permissions are not tied to specific roles, allowing sites to configure which roles can access or modify documents. |
||
$render_array = CoolUtils::getViewerRender($media, $edit, $options); | ||
|
||
if (!$render_array || array_key_exists('error', $render_array)) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,22 +11,27 @@ | |
|
||
namespace Drupal\collabora_online\Controller; | ||
|
||
use Drupal\collabora_online\Cool\CoolUtils; | ||
use Drupal\Core\Controller\ControllerBase; | ||
use Drupal\Core\File\FileSystemInterface; | ||
use Drupal\collabora_online\Cool\CoolUtils; | ||
use Drupal\file\Entity\File; | ||
use Drupal\media\Entity\Media; | ||
use Drupal\user\Entity\User; | ||
use Symfony\Component\HttpFoundation\BinaryFileResponse; | ||
use Symfony\Component\HttpFoundation\Response; | ||
use Symfony\Component\HttpFoundation\Request; | ||
use Symfony\Component\HttpFoundation\Response; | ||
|
||
/** | ||
* Provides WOPI route responses for the Collabora module. | ||
*/ | ||
class WopiController extends ControllerBase { | ||
|
||
static function permissionDenied() { | ||
/** | ||
* Creates a failure response that is understood by Collabora. | ||
* | ||
* @return \Symfony\Component\HttpFoundation\Response | ||
* Response object. | ||
*/ | ||
static function permissionDenied(): Response { | ||
return new Response( | ||
'Authentication failed.', | ||
Response::HTTP_FORBIDDEN, | ||
|
@@ -42,13 +47,20 @@ function wopiCheckFileInfo(string $id, Request $request) { | |
return static::permissionDenied(); | ||
} | ||
|
||
/** @var \Drupal\media\MediaInterface|null $media */ | ||
$media = \Drupal::entityTypeManager()->getStorage('media')->load($id); | ||
if (!$media) { | ||
return static::permissionDenied(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Comment should be changed. |
||
} | ||
|
||
$file = CoolUtils::getFileById($id); | ||
$mtime = date_create_immutable_from_format('U', $file->getChangedTime()); | ||
// @todo What if the uid in the payload is not set? | ||
// @todo What if $user is NULL? | ||
$user = User::load($jwt_payload->uid); | ||
$permissions = CoolUtils::getUserPermissions($user); | ||
$can_write = $jwt_payload->wri; | ||
|
||
if ($can_write && $can_write != $permissions['is_collaborator']) { | ||
if ($can_write && !$media->access('edit in collabora', $user)) { | ||
\Drupal::logger('cool')->error('Token and user permissions do not match.'); | ||
return static::permissionDenied(); | ||
} | ||
|
@@ -69,8 +81,8 @@ function wopiCheckFileInfo(string $id, Request $request) { | |
'mail' => $user->getEmail(), | ||
], | ||
'UserCanWrite' => $can_write, | ||
'IsAdminUser' => $permissions['is_admin'], | ||
'IsAnonymousUser' => $permissions['is_anonymous'] | ||
'IsAdminUser' => $user->hasPermission('administer collabora instance'), | ||
'IsAnonymousUser' => $user->isAnonymous(), | ||
]; | ||
|
||
$jsonPayload = json_encode($payload); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can rethink this section. For now I just removed it to avoid confusion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right now it is unclear how these new permissions work. Is it possible to have a short write up here?