Skip to content

Commit

Permalink
feat: wip: send templates with SharedSetting
Browse files Browse the repository at this point in the history
  • Loading branch information
Rash419 committed Feb 25, 2025
1 parent ada75a5 commit e7bfb8e
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 17 deletions.
10 changes: 10 additions & 0 deletions appinfo/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,16 @@
'name' => '.+',
],
],
[
'name' => 'settings#getTemplateFile',
'url' => 'settings/{identifier}/{category}/{name}',
'verb' => 'GET',
'requirements' => [
'identifier' => '[a-zA-Z0-9_\-]+',
'category' => '[a-zA-Z0-9_\-]+',
'name' => '.+',
],
],
['name' => 'settings#generateIframeToken', 'url' => 'settings/generateToken/{type}', 'verb' => 'GET'],

// Direct Editing: Webview
Expand Down
37 changes: 36 additions & 1 deletion lib/Controller/SettingsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@
use OCA\Richdocuments\Service\FontService;
use OCA\Richdocuments\Service\SettingsService;
use OCA\Richdocuments\UploadException;
use OCP\AppFramework\Http\DataDownloadResponse;
use OCP\App\IAppManager;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
use OCP\AppFramework\Http\DataDisplayResponse;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Http\JSONResponse;
use OCP\Files\File;
use OCP\Files\NotFoundException;
use OCP\Files\NotPermittedException;
use OCP\Files\SimpleFS\ISimpleFile;
Expand All @@ -33,6 +35,7 @@
use OCP\Util;
use Psr\Log\LoggerInterface;
use Symfony\Component\Console\Output\NullOutput;
use OCA\Richdocuments\TemplateManager;

class SettingsController extends Controller {
// TODO adapt overview generation if we add more font mimetypes
Expand Down Expand Up @@ -61,6 +64,7 @@ public function __construct(
private IURLGenerator $urlGenerator,
private WopiMapper $wopiMapper,
private ?string $userId,
private TemplateManager $templateManager,
) {
parent::__construct($appName, $request);
}
Expand Down Expand Up @@ -504,7 +508,38 @@ public function getSettingsFile(string $type, string $token, string $category, s
return new DataDisplayResponse('Something went wrong', 500);
}
}


/**
* @param string $identifier
* @param string $category
* @param string $name
*
* @return DataDisplayResponse
*
* @NoAdminRequired
* @PublicPage
* @NoCSRFRequired
**/
public function getTemplateFile(string $identifier, string $category, string $name): DataDisplayResponse {
try {
$file = $this->templateManager->get((int)$identifier);
} catch (NotFoundException) {
return new DataDisplayResponse('', Http::STATUS_NOT_FOUND);
}

if ($file instanceof File || $file instanceof ISimpleFile) {
$response = new DataDisplayResponse(
$file->getContent(),
Http::STATUS_OK,
[
'Content-Type' => $file->getMimeType() ?: 'application/octet-stream'
]
);
return $response;
}
return new DataDisplayResponse('', Http::STATUS_NOT_FOUND);
}


/**
* @param string $key
Expand Down
14 changes: 7 additions & 7 deletions lib/Controller/WopiController.php
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,7 @@ public function getSettings(string $type, string $access_token): JSONResponse {
if (empty($type)) {
return new JSONResponse(['error' => 'Invalid type parameter'], Http::STATUS_BAD_REQUEST);
}

try {
$wopi = $this->wopiMapper->getWopiForToken($access_token);
if ($wopi->getTokenType() !== Wopi::TOKEN_TYPE_SETTING_AUTH) {
Expand All @@ -415,7 +415,7 @@ public function getSettings(string $type, string $access_token): JSONResponse {
$isPublic = empty($wopi->getEditorUid());
$guestUserId = 'Guest-' . \OC::$server->getSecureRandom()->generate(8);
$userId = !$isPublic ? $wopi->getEditorUid() : $guestUserId;

$userConfig = $this->settingsService->generateSettingsConfig($type, $userId);
return new JSONResponse($userConfig, Http::STATUS_OK);
} catch (UnknownTokenException|ExpiredTokenException $e) {
Expand All @@ -426,7 +426,7 @@ public function getSettings(string $type, string $access_token): JSONResponse {
return new JSONResponse(['error' => 'Internal Server Error'], Http::STATUS_INTERNAL_SERVER_ERROR);
}
}

#[NoAdminRequired]
#[NoCSRFRequired]
#[PublicPage]
Expand All @@ -444,11 +444,11 @@ public function uploadSettingsFile(string $fileId, string $access_token): JSONRe

$fileContent = stream_get_contents($content);
fclose($content);

// Use the fileId as a file path URL (e.g., "/settings/systemconfig/wordbook/en_US%20(1).dic")
$settingsUrl = new SettingsUrl($fileId);
$result = $this->settingsService->uploadFile($settingsUrl, $fileContent, $userId);

return new JSONResponse([
'status' => 'success',
'filename' => $settingsUrl->getFileName(),
Expand Down Expand Up @@ -501,7 +501,7 @@ public function deleteSettingsFile(string $fileId, string $access_token): JSONRe
}
}


/**
* Given an access token and a fileId, replaces the files with the request body.
* Expects a valid token in access_token parameter.
Expand Down Expand Up @@ -984,7 +984,7 @@ private function getWopiUrlForTemplate(Wopi $wopi): string {
$nextcloudUrl = $this->appConfig->getNextcloudUrl() ?: trim($this->urlGenerator->getAbsoluteURL(''), '/');
return $nextcloudUrl . '/index.php/apps/richdocuments/wopi/template/' . $wopi->getTemplateId() . '?access_token=' . $wopi->getToken();
}

private function generateSettingToken(string $userId): string {
return $this->settingsService->generateIframeToken('user', $userId)['token'];
}
Expand Down
63 changes: 54 additions & 9 deletions lib/Service/SettingsService.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

use OCA\Richdocuments\AppInfo\Application;
use OCA\Richdocuments\Db\WopiMapper;
use OCA\Richdocuments\TemplateManager;
use OCA\Richdocuments\WOPI\SettingsUrl;
use OCP\Files\Folder;
use OCP\Files\IAppData;
Expand Down Expand Up @@ -44,6 +45,7 @@ public function __construct(
private WopiMapper $wopiMapper,
private IGroupManager $groupManager,
private IRootFolder $rootFolder,
private TemplateManager $templateManager,
) {
// Create a distributed cache for caching file lists
$this->cache = $cacheFactory->createDistributed(Application::APPNAME);
Expand Down Expand Up @@ -141,12 +143,12 @@ public function generateIframeToken(string $type, string $userId): array {
if ($type === 'admin' && !$this->groupManager->isAdmin($userId)) {
throw new NotPermittedException('Permission denied');
}

$serverHost = $this->urlGenerator->getAbsoluteURL('/');
$version = $this->capabilitiesService->getProductVersion();

$wopi = $this->wopiMapper->generateUserSettingsToken(-1, $userId, $version, $serverHost);

return [
'token' => $wopi->getToken(),
'token_ttl' => $wopi->getExpiry(),
Expand All @@ -164,7 +166,48 @@ public function generateIframeToken(string $type, string $userId): array {
public function getFolderEtag($type) : string {
return $this->getTypeFolder($type)->getEtag();
}


public const SUPPORTED_PRESENTATION_MIMES = [
'application/vnd.oasis.opendocument.presentation',
'application/vnd.oasis.opendocument.presentation-template',
];

/**
*
* get presentation templates
* @return array
*/
public function getPresentationTemplates(string $type): array {
$templates = array_filter(
$this->templateManager->getSystem('presentation'),
function ($template) {
return in_array(
$template->getMimeType(),
self::SUPPORTED_PRESENTATION_MIMES,
true
);
}
);

$result = [];

foreach ($templates as $template) {
$uri = $this->urlGenerator->linkToRouteAbsolute(
'richdocuments.settings.getTemplateFile',
[
'identifier' => $template->getId(),
'category' => 'template',
'name' => $template->getName(),
]
);
$result[] = [
'uri' => $uri,
'stamp' => $template->getEtag(),
];
}
return $result;
}

/**
* generate setting config
*
Expand All @@ -189,6 +232,8 @@ public function generateSettingsConfig(string $type, string $userId): array {
$config[$category] = $files;
}

$config['template'] = self::getPresentationTemplates($type);

return $config;
}

Expand Down Expand Up @@ -269,14 +314,14 @@ private function refreshFolderEtag($type) {
* @return string
*/
private function generateFileUri(string $type, string $category, string $fileName, string $userId): string {

// Passing userId is dangerous so we have to trim from url...
if (strpos($type, '/') !== false) {
$type = explode('/', $type)[0];
}

$token = $this->generateIframeToken($type, $userId);

return $this->urlGenerator->linkToRouteAbsolute(
'richdocuments.settings.getSettingsFile',
[
Expand All @@ -302,13 +347,13 @@ public function getSettingsFile(string $type, string $category, string $name): I
} catch (NotFoundException $e) {
throw new NotFoundException("Type folder '{$type}' not found.");
}

try {
$categoryFolder = $baseFolder->getFolder($category);
} catch (NotFoundException $e) {
throw new NotFoundException("Category folder '{$category}' not found in type '{$type}'.");
}

try {
return $categoryFolder->getFile($name);
} catch (NotFoundException $e) {
Expand Down Expand Up @@ -337,7 +382,7 @@ public function deleteSettingsFile(string $type, string $category, string $name,
throw new NotFoundException("User folder '{$userId}' not found.");
}
}

try {
$categoryFolder = $baseFolder->getFolder($category);
} catch (NotFoundException $e) {
Expand Down

0 comments on commit e7bfb8e

Please sign in to comment.