Allow fetching the initiator user data if needed
Signed-off-by: Julius Härtl <jus@bitgrid.net>
This commit is contained in:
Родитель
a9b794a971
Коммит
49fd9ac1d6
|
@ -75,5 +75,6 @@ return [
|
|||
|
||||
['name' => 'Federation#index', 'url' => '/api/v1/federation', 'verb' => 'GET'],
|
||||
['name' => 'Federation#remoteWopiToken', 'url' => '/api/v1/federation', 'verb' => 'POST'],
|
||||
['name' => 'Federation#initiatorUser', 'url' => '/api/v1/federation/user', 'verb' => 'POST'],
|
||||
],
|
||||
];
|
||||
|
|
|
@ -30,6 +30,8 @@ use OCP\AppFramework\Http\DataResponse;
|
|||
use OCP\IConfig;
|
||||
use OCP\ILogger;
|
||||
use OCP\IRequest;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\IUserManager;
|
||||
|
||||
class FederationController extends OCSController {
|
||||
|
||||
|
@ -42,17 +44,27 @@ class FederationController extends OCSController {
|
|||
/** @var WopiMapper */
|
||||
private $wopiMapper;
|
||||
|
||||
/** @var IUserManager */
|
||||
private $userManager;
|
||||
|
||||
/** @var IURLGenerator */
|
||||
private $urlGenerator;
|
||||
|
||||
public function __construct(
|
||||
string $appName,
|
||||
IRequest $request,
|
||||
IConfig $config,
|
||||
ILogger $logger,
|
||||
WopiMapper $wopiMapper
|
||||
WopiMapper $wopiMapper,
|
||||
IUserManager $userManager,
|
||||
IURLGenerator $urlGenerator
|
||||
) {
|
||||
parent::__construct($appName, $request);
|
||||
$this->config = $config;
|
||||
$this->logger = $logger;
|
||||
$this->wopiMapper = $wopiMapper;
|
||||
$this->userManager = $userManager;
|
||||
$this->urlGenerator = $urlGenerator;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -84,32 +96,54 @@ class FederationController extends OCSController {
|
|||
*/
|
||||
public function remoteWopiToken($token): DataResponse {
|
||||
try {
|
||||
$wopi = $this->wopiMapper->getWopiForToken($token);
|
||||
$user = \OC::$server->getUserManager()->get($wopi->getEditorUid());
|
||||
if($user !== null) {
|
||||
$wopi->setGuestDisplayname($user->getDisplayName());
|
||||
$initiatorWopi = $this->wopiMapper->getWopiForToken($token);
|
||||
if (empty($initiatorWopi->getEditorUid()) && !empty($initiatorWopi->getRemoteServer()) && !empty($initiatorWopi->getRemoteServerToken())) {
|
||||
$client = \OC::$server->getHTTPClientService()->newClient();
|
||||
$response = $client->post(
|
||||
rtrim($initiatorWopi->getRemoteServer(), '/') . '/ocs/v2.php/apps/richdocuments/api/v1/federation/user?format=json',
|
||||
[ 'body' => [ 'token' => $initiatorWopi->getRemoteServerToken() ], 'timeout' => 10 ]
|
||||
);
|
||||
$initiatorUser = \json_decode($response->getBody(), true)['ocs']['data'];
|
||||
$initiatorWopi->setGuestDisplayname($initiatorUser['displayName']);
|
||||
} else {
|
||||
$user = $this->userManager->get($initiatorWopi->getEditorUid());
|
||||
if($user !== null) {
|
||||
$initiatorWopi->setGuestDisplayname($user->getDisplayName());
|
||||
}
|
||||
}
|
||||
$this->logger->debug('COOL-Federation-Initiator: Token ' . $token . ' returned');
|
||||
return new DataResponse($wopi);
|
||||
return new DataResponse($initiatorWopi);
|
||||
} catch (DoesNotExistException $e) {
|
||||
$this->logger->debug('COOL-Federation-Initiator: Token ' . $token . 'not found');
|
||||
throw new OCSNotFoundException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @PublicPage
|
||||
* @NoCSRFRequired
|
||||
* @OCSRoute POST /api/v1/federation/user
|
||||
*
|
||||
* Return user details for a initiator user that will be used by remote instances
|
||||
* to provide Collabora with the users avatar/displayname for guests on share links
|
||||
* if the session was created through a direct link of a public share
|
||||
*
|
||||
* @param $token
|
||||
* @return DataResponse
|
||||
* @throws DoesNotExistException
|
||||
*/
|
||||
public function initiatorUser($token): DataResponse {
|
||||
try {
|
||||
$wopi = $this->wopiMapper->getWopiForToken($token);
|
||||
$user = \OC::$server->getUserManager()->get($wopi->getEditorUid());
|
||||
$user = $this->userManager->get($wopi->getEditorUid());
|
||||
if($user !== null) {
|
||||
$wopi->setGuestDisplayname($user->getDisplayName());
|
||||
}
|
||||
$this->logger->debug('COOL-Federation-Initiator-User: Token ' . $token . ' returned');
|
||||
return new DataResponse([
|
||||
'initiatorHost' => '',
|
||||
'userId' => '',
|
||||
'displayName' => '',
|
||||
'avatar' => ''
|
||||
'userId' => $user->getUID(),
|
||||
'displayName' => $user->getDisplayName(),
|
||||
'avatar' => $this->urlGenerator->linkToRouteAbsolute('core.avatar.getAvatar', ['userId' => $wopi->getEditorUid(), 'size' => WopiController::WOPI_AVATAR_SIZE])
|
||||
]);
|
||||
} catch (DoesNotExistException $e) {
|
||||
$this->logger->debug('COOL-Federation-Initiator-User: Token ' . $token . 'not found');
|
||||
|
|
|
@ -156,7 +156,7 @@ class OCSController extends \OCP\AppFramework\OCSController {
|
|||
'path' => $path,
|
||||
'password' => $password
|
||||
],
|
||||
'timeout' => 5
|
||||
'timeout' => 30
|
||||
]);
|
||||
$url = \json_decode($response->getBody(), true)['ocs']['data']['url'];
|
||||
|
||||
|
|
|
@ -85,6 +85,8 @@ class WopiController extends Controller {
|
|||
// Signifies LOOL that document has been changed externally in this storage
|
||||
const LOOL_STATUS_DOC_CHANGED = 1010;
|
||||
|
||||
const WOPI_AVATAR_SIZE = 32;
|
||||
|
||||
/**
|
||||
* @param string $appName
|
||||
* @param IRequest $request
|
||||
|
@ -230,7 +232,7 @@ class WopiController extends Controller {
|
|||
|
||||
$user = $this->userManager->get($wopi->getEditorUid());
|
||||
if($user !== null) {
|
||||
$response['UserExtraInfo']['avatar'] = $this->urlGenerator->linkToRouteAbsolute('core.avatar.getAvatar', ['userId' => $wopi->getEditorUid(), 'size' => 32]);
|
||||
$response['UserExtraInfo']['avatar'] = $this->urlGenerator->linkToRouteAbsolute('core.avatar.getAvatar', ['userId' => $wopi->getEditorUid(), 'size' => self::WOPI_AVATAR_SIZE]);
|
||||
}
|
||||
|
||||
if ($wopi->isRemoteToken()) {
|
||||
|
@ -242,12 +244,14 @@ class WopiController extends Controller {
|
|||
|
||||
|
||||
private function setFederationFileInfo(Wopi $wopi, $response) {
|
||||
$response['UserId'] = 'Guest-' . \OC::$server->getSecureRandom()->generate(8);
|
||||
|
||||
if ($wopi->getTokenType() === Wopi::TOKEN_TYPE_REMOTE_USER) {
|
||||
$remoteUserId = $wopi->getGuestDisplayname();
|
||||
$cloudID = \OC::$server->getCloudIdManager()->resolveCloudId($remoteUserId);
|
||||
$response['UserId'] = $cloudID->getDisplayId();
|
||||
$response['UserFriendlyName'] = $cloudID->getDisplayId();
|
||||
$response['UserExtraInfo']['avatar'] = $this->urlGenerator->linkToRouteAbsolute('core.avatar.getAvatar', ['userId' => explode('@', $remoteUserId)[0], 'size' => 32]);
|
||||
$response['UserExtraInfo']['avatar'] = $this->urlGenerator->linkToRouteAbsolute('core.avatar.getAvatar', ['userId' => explode('@', $remoteUserId)[0], 'size' => self::WOPI_AVATAR_SIZE]);
|
||||
$cleanCloudId = str_replace(['http://', 'https://'], '', $cloudID->getId());
|
||||
$addressBookEntries = \OC::$server->getContactsManager()->search($cleanCloudId, ['CLOUD']);
|
||||
foreach ($addressBookEntries as $entry) {
|
||||
|
@ -260,24 +264,20 @@ class WopiController extends Controller {
|
|||
}
|
||||
}
|
||||
}
|
||||
} else if ($wopi->getTokenType() === Wopi::TOKEN_TYPE_REMOTE_GUEST) {
|
||||
$response['UserId'] = 'Guest-' . \OC::$server->getSecureRandom()->generate(8);
|
||||
}
|
||||
|
||||
|
||||
$initiator = $this->federationService->getRemoteFileDetails($wopi->getRemoteServer(), $wopi->getRemoteServerToken());
|
||||
if ($initiator !== null) {
|
||||
if ($initiator->hasTemplateId()) {
|
||||
$templateUrl = $wopi->getRemoteServer() . '/index.php/apps/richdocuments/wopi/template/' . $initiator->getTemplateId() . '?access_token=' . $initiator->getToken();
|
||||
$response['TemplateSource'] = $templateUrl;
|
||||
}
|
||||
if ($wopi->getTokenType() === Wopi::TOKEN_TYPE_REMOTE_USER) {
|
||||
$response['UserExtraInfo']['avatar'] = $wopi->getRemoteServer() . '/index.php/avatar/' . $initiator->getEditorUid() . '/32';
|
||||
}
|
||||
if ($wopi->getTokenType() === Wopi::TOKEN_TYPE_REMOTE_GUEST && $initiator->getEditorUid()) {
|
||||
$response['UserFriendlyName'] = $initiator->getGuestDisplayname() . ' (Guest)';
|
||||
$response['UserExtraInfo']['avatar'] = $wopi->getRemoteServer() . '/index.php/avatar/' . $initiator->getEditorUid() . '/32';
|
||||
}
|
||||
if ($initiator === null) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$response['UserFriendlyName'] = $initiator->getGuestDisplayname() . ' (Guest)';
|
||||
if ($initiator->hasTemplateId()) {
|
||||
$templateUrl = $wopi->getRemoteServer() . '/index.php/apps/richdocuments/wopi/template/' . $initiator->getTemplateId() . '?access_token=' . $initiator->getToken();
|
||||
$response['TemplateSource'] = $templateUrl;
|
||||
}
|
||||
if ($wopi->getTokenType() === Wopi::TOKEN_TYPE_REMOTE_USER || ($wopi->getTokenType() === Wopi::TOKEN_TYPE_REMOTE_GUEST && $initiator->getEditorUid())) {
|
||||
$response['UserExtraInfo']['avatar'] = $wopi->getRemoteServer() . '/index.php/avatar/' . $initiator->getEditorUid() . '/'. self::WOPI_AVATAR_SIZE;
|
||||
}
|
||||
|
||||
return $response;
|
||||
|
|
|
@ -28,6 +28,7 @@ use OCA\Federation\TrustedServers;
|
|||
use OCA\Files_Sharing\External\Storage as SharingExternalStorage;
|
||||
use OCA\Richdocuments\Db\Direct;
|
||||
use OCA\Richdocuments\Db\Wopi;
|
||||
use OCA\Richdocuments\Db\WopiMapper;
|
||||
use OCA\Richdocuments\TokenManager;
|
||||
use OCP\AppFramework\Http\RedirectResponse;
|
||||
use OCP\AppFramework\QueryException;
|
||||
|
@ -91,7 +92,7 @@ class FederationService {
|
|||
}
|
||||
try {
|
||||
$client = $this->clientService->newClient();
|
||||
$response = $client->get($remote . '/ocs/v2.php/apps/richdocuments/api/v1/federation?format=json', ['timeout' => 5]);
|
||||
$response = $client->get($remote . '/ocs/v2.php/apps/richdocuments/api/v1/federation?format=json', ['timeout' => 30]);
|
||||
$data = \json_decode($response->getBody(), true);
|
||||
$remoteCollabora = $data['ocs']['data']['wopi_url'];
|
||||
$this->cache->set('richdocuments_remote/' . $remote, $remoteCollabora, 3600);
|
||||
|
@ -168,7 +169,7 @@ class FederationService {
|
|||
$this->logger->debug('COOL-Federation-Source: Fetching remote file details from ' . $remote . ' for token ' . $remoteToken);
|
||||
$client = $this->clientService->newClient();
|
||||
$response = $client->post($remote . '/ocs/v2.php/apps/richdocuments/api/v1/federation?format=json', [
|
||||
'timeout' => 5,
|
||||
'timeout' => 30,
|
||||
'body' => [
|
||||
'token' => $remoteToken
|
||||
]
|
||||
|
@ -179,7 +180,7 @@ class FederationService {
|
|||
$this->cache->set($cacheKey, $data['ocs']['data']);
|
||||
return Wopi::fromParams($data['ocs']['data']);
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->error('COOL-Federation-Source: Unable to fetch remote file details for ' . $remoteToken . ' from ' . $remote, ['exception' => $e]);
|
||||
$this->logger->logException($e, ['message' => 'COOL-Federation-Source: Unable to fetch remote file details for ' . $remoteToken . ' from ' . $remote ]);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -204,12 +205,12 @@ class FederationService {
|
|||
$initiatorServer = $wopi->getServerHost();
|
||||
$initiatorToken = $wopi->getToken();
|
||||
|
||||
if ($direct) {
|
||||
//$wopi->setRemoteServer($direct->getInitiatorHost());
|
||||
//$wopi->setRemoteServerToken($direct->getInitiatorToken());
|
||||
// FIXME: the direct token might have a different originator when a share link originating on a federated stoarge is opened
|
||||
// editor uid is null since we don't fetch it from the initiator of direct so @{link remoteWopiToken()} fails
|
||||
// Currently there is no mapping from the initiator user data to the source then
|
||||
/**
|
||||
* If the request to open a file originates from a direct token we might need to fetch the initiator user details when the initiator wopi token is accessed
|
||||
* as the user might origin on a 3rd instance
|
||||
*/
|
||||
if ($direct && !empty($direct->getInitiatorHost()) && !empty($direct->getInitiatorToken())) {
|
||||
$this->tokenManager->extendWithInitiatorUserToken($wopi, $direct->getInitiatorHost(), $direct->getInitiatorToken());
|
||||
}
|
||||
|
||||
$url = rtrim($remote, '/') . '/index.php/apps/richdocuments/remote?shareToken=' . $item->getStorage()->getToken() .
|
||||
|
|
|
@ -225,9 +225,11 @@ class TokenManager {
|
|||
|
||||
$remoteTokenType = $remoteWopi->getEditorUid() !== null ? Wopi::TOKEN_TYPE_REMOTE_USER : Wopi::TOKEN_TYPE_REMOTE_GUEST;
|
||||
$wopi->setTokenType($remoteTokenType);
|
||||
if ($remoteTokenType === Wopi::TOKEN_TYPE_REMOTE_USER) {
|
||||
$wopi->setGuestDisplayname($remoteWopi->getEditorUid() . '@' . $remoteServer);
|
||||
}
|
||||
$wopi->setGuestDisplayname(
|
||||
$remoteTokenType === Wopi::TOKEN_TYPE_REMOTE_USER ?
|
||||
$remoteWopi->getEditorUid() . '@' . $remoteServer :
|
||||
$remoteWopi->getGuestDisplayname()
|
||||
);
|
||||
$wopi->setShare($shareToken);
|
||||
$wopi->setCanwrite($wopi->getCanwrite() && $remoteWopi->getCanwrite());
|
||||
$wopi->setHideDownload($wopi->getHideDownload() || $remoteWopi->getHideDownload());
|
||||
|
@ -302,4 +304,11 @@ class TokenManager {
|
|||
return $this->wopiMapper->generateInitiatorToken($this->userId, $sourceServer);
|
||||
}
|
||||
|
||||
public function extendWithInitiatorUserToken(Wopi $wopi, string $initiatorUserHost, string $initiatorUserToken): Wopi {
|
||||
$wopi->setRemoteServer($initiatorUserHost);
|
||||
$wopi->setRemoteServerToken($initiatorUserToken);
|
||||
$this->wopiMapper->update($wopi);
|
||||
return $wopi;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -207,9 +207,7 @@ Feature: Direct editing
|
|||
And Collabora fetches checkFileInfo
|
||||
And Collabora fetches and receives the following in the checkFileInfo response
|
||||
| BaseFileName | document-reshare-fed-link.odt |
|
||||
| UserFriendlyName | Anonymous guest |
|
||||
# FIXME: Known issue as of right now as we do not fetch the initiator user yet
|
||||
# | UserFriendlyName | user3-displayname (Guest) |
|
||||
| UserFriendlyName | user3-displayname (Guest) |
|
||||
And checkFileInfo "UserId" matches "/Guest-/"
|
||||
And checkFileInfo "UserCanWrite" is false
|
||||
And both Collabora files used the same file id
|
||||
|
|
Загрузка…
Ссылка в новой задаче