Skip to content
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: Admin setting iframe #4373

Draft
wants to merge 12 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
add delete button and create wopi/setting route to handle wopi file r…
…equest

Signed-off-by: codewithvk <vivek.javiya@collabora.com>
  • Loading branch information
codewithvk committed Jan 11, 2025
commit e1f8021979ee8c178a048f616c60313a8b0744ee
1 change: 1 addition & 0 deletions appinfo/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
['name' => 'settings#uploadUserFile', 'url' => 'settings/user-files', 'verb' => 'POST'],
['name' => 'settings#getUserFileList', 'url' => 'settings/user-files.json', 'verb' => 'GET'],
['name' => 'settings#downloadUserFile', 'url' => 'settings/user-files/{fileName}', 'verb' => 'GET'],
['name' => 'settings#deleteSystemFile', 'url' => 'settings/system-files/{fileName}', 'verb' => 'DELETE'],

// Direct Editing: Webview
['name' => 'directView#show', 'url' => '/direct/{token}', 'verb' => 'GET'],
Expand Down
25 changes: 25 additions & 0 deletions lib/Controller/SettingsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,31 @@ public function getSystemFile(string $fileName) {
return new JSONResponse(['error' => 'Not permitted'], Http::STATUS_FORBIDDEN);
}
}

/**
* Delete a file by name from the "system-settings" directory.
*
* @NoAdminRequired
* @PublicPage
* @NoCSRFRequired
*
* @param string $fileName Name of the file to delete (URL-encoded)
* @return JSONResponse A simple JSON indicating success or error
*/
public function deleteSystemFile(string $fileName): JSONResponse {
try {
$this->settingsService->deleteSystemFile($fileName);
return new JSONResponse(['status' => 'success'], Http::STATUS_OK);
} catch (NotFoundException $e) {
return new JSONResponse(['error' => 'File not found'], Http::STATUS_NOT_FOUND);
} catch (NotPermittedException $e) {
return new JSONResponse(['error' => 'Not permitted'], Http::STATUS_FORBIDDEN);
} catch (\Exception $e) {
$this->logger->error($e->getMessage(), ['exception' => $e]);
return new JSONResponse(['error' => $e->getMessage()], Http::STATUS_INTERNAL_SERVER_ERROR);
}
}


/**
* @return JSONResponse
Expand Down
55 changes: 49 additions & 6 deletions lib/Controller/WopiController.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,11 @@ public function checkFileInfo(string $fileId, string $access_token): JSONRespons

// TODO: condition for $wopi not found?

$userSettingsUri = $this->generateUserSettingsUri($wopi);

if ($fileId == "-1" && $wopi->getTokenType() == WOPI::TOKEN_TYPE_SETTING_AUTH) {
$response = [
"usersettings" => 'DONE',
"UserSettingsUri" => $userSettingsUri,
];

return new JSONResponse($response);
Expand Down Expand Up @@ -171,6 +173,7 @@ public function checkFileInfo(string $fileId, string $access_token): JSONRespons
'IsUserLocked' => $this->permissionManager->userIsFeatureLocked($wopi->getEditorUid()),
'EnableRemoteLinkPicker' => (bool)$wopi->getCanwrite() && !$isPublic && !$wopi->getDirect(),
'HasContentRange' => true,
"UserSettingsUri" => $userSettingsUri,
];

$enableZotero = $this->config->getAppValue(Application::APPNAME, 'zoteroEnabled', 'yes') === 'yes';
Expand Down Expand Up @@ -366,11 +369,48 @@ public function getFile(string $fileId, string $access_token): JSONResponse|Stre
}
}

#[NoAdminRequired]
#[NoCSRFRequired]
#[PublicPage]
#[FrontpageRoute(verb: 'GET', url: 'wopi/settings')]
public function getSettings(string $type, string $access_token): JSONResponse {
if ($type !== 'UserSettingsUri') {
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) {
return new JSONResponse(['error' => 'Invalid token type'], Http::STATUS_FORBIDDEN);
}

// user admin check
$user = $this->userManager->get($wopi->getEditorUid());
if (!$user || !$this->groupManager->isAdmin($user->getUID())) {
return new JSONResponse(['error' => 'Access denied'], Http::STATUS_FORBIDDEN);
}

$systemFiles = $this->settingsService->getSystemFiles();
$formattedList = $this->settingsService->getSystemFileList($systemFiles);

$response = new JSONResponse($formattedList);

return $response;
} catch (UnknownTokenException|ExpiredTokenException $e) {
$this->logger->debug($e->getMessage(), ['exception' => $e]);
return new JSONResponse(['error' => 'Unauthorized'], Http::STATUS_UNAUTHORIZED);
} catch (\Exception $e) {
$this->logger->error($e->getMessage(), ['exception' => $e]);
return new JSONResponse(['error' => 'Internal Server Error'], Http::STATUS_INTERNAL_SERVER_ERROR);
}
}

#[NoAdminRequired]
#[NoCSRFRequired]
#[PublicPage]
#[FrontpageRoute(verb: 'POST', url: 'wopi/settings/upload')]
public function handleSettingsFile(string $access_token): JSONResponse {
public function handleSettingsFile(string $fileId, string $access_token): JSONResponse {
try {
$wopi = $this->wopiMapper->getWopiForToken($access_token);

Expand All @@ -386,10 +426,8 @@ public function handleSettingsFile(string $access_token): JSONResponse {
$fileContent = stream_get_contents($content);
fclose($content);


$newFileName = 'settings-' . uniqid() . '.json';

$result = $this->settingsService->uploadSystemFile($newFileName, $fileContent);
// TODO: JSON based upload
$result = $this->settingsService->uploadSystemFile($fileId, $fileContent);

return new JSONResponse([
'status' => 'success',
Expand Down Expand Up @@ -900,4 +938,9 @@ 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();
}
// todo extract nextcloud url from everything
private function generateUserSettingsUri(Wopi $wopi): string {
$nextcloudUrl = $this->appConfig->getNextcloudUrl() ?: trim($this->urlGenerator->getAbsoluteURL(''), '/');
return $nextcloudUrl . '/index.php/apps/richdocuments/wopi/settings' . '?type=UserSettingsUri' . '&access_token=' . $wopi->getToken();
}
}
30 changes: 30 additions & 0 deletions lib/Service/SettingsService.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,36 @@ public function getSystemFiles(): array {
return $dir->getDirectoryListing();
}

/**
* Get the formatted list of system-settings files.
*
* @param array $systemFiles Array of ISimpleFile objects
* @return array
*/
public function getSystemFileList(array $systemFiles): array {
$urlGenerator = $this->urlGenerator;
$list = array_map(
function (ISimpleFile $f) use ($urlGenerator) {
return [
'uri' => $urlGenerator->linkToRouteAbsolute(
Application::APPNAME . '.settings.getSystemFile',
['fileName' => $f->getName()]
),
'stamp' => $f->getETag(),
];
},
$systemFiles
);

// Combine all ETags into a single ETag for the entire list
$combinedEtag = md5(implode(',', array_map(fn(ISimpleFile $f) => $f->getETag(), $systemFiles)));

return [
'files' => $list,
'etag' => $combinedEtag,
];
}

/**
* Return a list of file objects from the user-specific directory.
*
Expand Down
22 changes: 22 additions & 0 deletions src/components/AdminSettings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@
class="button">
{{ t('richdocuments', 'Download') }}
</a>

<button class="button"
@click="deleteSystemFile(fileName)">
{{ t('richdocuments', 'Delete') }}
</button>
</li>
</ul>
</div>
Expand Down Expand Up @@ -806,6 +811,23 @@ export default {
})
},

deleteSystemFile(fileName) {
if (!window.confirm(`Are you sure you want to delete "${fileName}"?`)) {
return
}

const url = generateUrl('/apps/richdocuments/settings/system-files/' + encodeURIComponent(fileName))

axios.delete(url)
.then((response) => {
this.getSystemFiles()
})
.catch((error) => {
console.error('Delete error', error.response?.data || error)
showError(t('richdocuments', 'Could not delete file') + ': ' + fileName)
})
},

downloadUrl(fileName) {
return generateUrl('/apps/richdocuments/settings/system-files/' + encodeURIComponent(fileName))
},
Expand Down