From 68b19204c96724c87c334446d3f0acdb2e056d90 Mon Sep 17 00:00:00 2001 From: Christian Hartmann Date: Sat, 5 Oct 2024 15:03:16 +0200 Subject: [PATCH] chore: use attributes to define routes Signed-off-by: Christian Hartmann --- appinfo/routes.php | 73 +------------- lib/Constants.php | 13 +++ lib/Controller/ApiController.php | 131 ++++++++++++++------------ lib/Controller/ConfigController.php | 2 + lib/Controller/PageController.php | 37 ++++---- lib/Controller/ShareApiController.php | 18 ++-- src/FormsSettings.vue | 2 +- 7 files changed, 117 insertions(+), 159 deletions(-) diff --git a/appinfo/routes.php b/appinfo/routes.php index aaa60596a..504261edd 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -25,83 +25,14 @@ * */ -$apiBase = '/api/{apiVersion}/'; -$requirements_v3 = [ - 'apiVersion' => 'v3', - 'formId' => '\d+', - 'questionId' => '\d+', - 'optionId' => '\d+', - 'shareId' => '\d+', - 'submissionId' => '\d+' -]; +use OCA\Forms\Constants; return [ - 'routes' => [ - // Internal AppConfig routes - ['name' => 'config#getAppConfig', 'url' => '/config', 'verb' => 'GET'], - ['name' => 'config#updateAppConfig', 'url' => '/config/update', 'verb' => 'PATCH'], - - // Public Share Link - ['name' => 'page#public_link_view', 'url' => '/s/{hash}', 'verb' => 'GET'], - - // Embedded View - ['name' => 'page#embedded_form_view', 'url' => '/embed/{hash}', 'verb' => 'GET'], - - // Internal views - ['name' => 'page#views', 'url' => '/{hash}/{view}', 'verb' => 'GET'], - // Internal Form Link - ['name' => 'page#internal_link_view', 'url' => '/{hash}', 'verb' => 'GET'], - // App Root - ['name' => 'page#index', 'url' => '/', 'verb' => 'GET'], - ], - 'ocs' => [ // CORS Preflight - ['name' => 'api#preflightedCors', 'url' => $apiBase . '{path}', 'verb' => 'OPTIONS', 'requirements' => [ + ['name' => 'api#preflightedCors', 'url' => Constants::API_BASE . '{path}', 'verb' => 'OPTIONS', 'requirements' => [ 'path' => '.+', 'apiVersion' => 'v3' ]], - - // API routes v3 - // Forms - ['name' => 'api#getForms', 'url' => $apiBase . 'forms', 'verb' => 'GET', 'requirements' => $requirements_v3], - ['name' => 'api#newForm', 'url' => $apiBase . 'forms', 'verb' => 'POST', 'requirements' => $requirements_v3], - ['name' => 'api#getForm', 'url' => $apiBase . 'forms/{formId}', 'verb' => 'GET', 'requirements' => $requirements_v3], - ['name' => 'api#updateForm', 'url' => $apiBase . 'forms/{formId}', 'verb' => 'PATCH', 'requirements' => $requirements_v3], - ['name' => 'api#deleteForm', 'url' => $apiBase . 'forms/{formId}', 'verb' => 'DELETE', 'requirements' => $requirements_v3], - - // Questions - ['name' => 'api#getQuestions', 'url' => $apiBase . 'forms/{formId}/questions', 'verb' => 'GET', 'requirements' => $requirements_v3], - ['name' => 'api#newQuestion', 'url' => $apiBase . 'forms/{formId}/questions', 'verb' => 'POST', 'requirements' => $requirements_v3], - ['name' => 'api#getQuestion', 'url' => $apiBase . 'forms/{formId}/questions/{questionId}', 'verb' => 'GET', 'requirements' => $requirements_v3], - ['name' => 'api#updateQuestion', 'url' => $apiBase . 'forms/{formId}/questions/{questionId}', 'verb' => 'PATCH', 'requirements' => $requirements_v3], - ['name' => 'api#deleteQuestion', 'url' => $apiBase . 'forms/{formId}/questions/{questionId}', 'verb' => 'DELETE', 'requirements' => $requirements_v3], - ['name' => 'api#reorderQuestions', 'url' => $apiBase . 'forms/{formId}/questions', 'verb' => 'PATCH', 'requirements' => $requirements_v3], - - // Options - // ['name' => 'api#getOptions', 'url' => $apiBase . 'forms/{formId}/questions/{questionId}/options', 'verb' => 'GET', 'requirements' => $requirements_v3], - ['name' => 'api#newOption', 'url' => $apiBase . 'forms/{formId}/questions/{questionId}/options', 'verb' => 'POST', 'requirements' => $requirements_v3], - // ['name' => 'api#getOption', 'url' => $apiBase . 'forms/{formId}/questions/{questionId}/options/{optionId}', 'verb' => 'GET', 'requirements' => $requirements_v3], - ['name' => 'api#updateOption', 'url' => $apiBase . 'forms/{formId}/questions/{questionId}/options/{optionId}', 'verb' => 'PATCH', 'requirements' => $requirements_v3], - ['name' => 'api#deleteOption', 'url' => $apiBase . 'forms/{formId}/questions/{questionId}/options/{optionId}', 'verb' => 'DELETE', 'requirements' => $requirements_v3], - ['name' => 'api#reorderOptions', 'url' => $apiBase . 'forms/{formId}/questions/{questionId}/options', 'verb' => 'PATCH', 'requirements' => $requirements_v3], - - // Shares - // ['name' => 'shareApi#getUserShares', 'url' => $apiBase . 'shares', 'verb' => 'GET', 'requirements' => $requirements_v3], - // ['name' => 'shareApi#getShares', 'url' => $apiBase . 'forms/{formId}/shares', 'verb' => 'GET', 'requirements' => $requirements_v3], - ['name' => 'shareApi#newShare', 'url' => $apiBase . 'forms/{formId}/shares', 'verb' => 'POST', 'requirements' => $requirements_v3], - // ['name' => 'shareApi#getShare', 'url' => $apiBase . 'forms/{formId}/shares/{shareId}', 'verb' => 'GET', 'requirements' => $requirements_v3], - ['name' => 'shareApi#updateShare', 'url' => $apiBase . 'forms/{formId}/shares/{shareId}', 'verb' => 'PATCH', 'requirements' => $requirements_v3], - ['name' => 'shareApi#deleteShare', 'url' => $apiBase . 'forms/{formId}/shares/{shareId}', 'verb' => 'DELETE', 'requirements' => $requirements_v3], - - // Submissions - ['name' => 'api#getSubmissions', 'url' => $apiBase . 'forms/{formId}/submissions', 'verb' => 'GET', 'requirements' => $requirements_v3], - ['name' => 'api#newSubmission', 'url' => $apiBase . 'forms/{formId}/submissions', 'verb' => 'POST', 'requirements' => $requirements_v3], - ['name' => 'api#deleteAllSubmissions', 'url' => $apiBase . 'forms/{formId}/submissions', 'verb' => 'DELETE', 'requirements' => $requirements_v3], - //['name' => 'api#getSubmission', 'url' => $apiBase . 'forms/{formId}/submissions/{submissionId}', 'verb' => 'GET', 'requirements' => $requirements_v3], - //['name' => 'api#updateSubmission', 'url' => $apiBase . 'forms/{formId}/submissions/{submissionId}', 'verb' => 'PATCH', 'requirements' => $requirements_v3], - ['name' => 'api#deleteSubmission', 'url' => $apiBase . 'forms/{formId}/submissions/{submissionId}', 'verb' => 'DELETE', 'requirements' => $requirements_v3], - ['name' => 'api#exportSubmissionsToCloud', 'url' => $apiBase . 'forms/{formId}/submissions/export', 'verb' => 'POST', 'requirements' => $requirements_v3], - ['name' => 'api#uploadFiles', 'url' => $apiBase . 'forms/{formId}/submissions/files/{questionId}', 'verb' => 'POST', 'requirements' => $requirements_v3], ] ]; diff --git a/lib/Constants.php b/lib/Constants.php index 44ce72a1d..54cd24074 100644 --- a/lib/Constants.php +++ b/lib/Constants.php @@ -26,6 +26,19 @@ use OCP\Share\IShare; class Constants { + /** + * Constants for API Controllers + */ + public const API_BASE = '/api/{apiVersion}/'; + public const API_V3_REQUIREMENTS = [ + 'apiVersion' => 'v3', + 'formId' => '\d+', + 'questionId' => '\d+', + 'optionId' => '\d+', + 'shareId' => '\d+', + 'submissionId' => '\d+' + ]; + /** * Used AppConfig Keys */ diff --git a/lib/Controller/ApiController.php b/lib/Controller/ApiController.php index fcec61636..f629236ee 100644 --- a/lib/Controller/ApiController.php +++ b/lib/Controller/ApiController.php @@ -50,6 +50,9 @@ use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Db\IMapperException; +use OCP\AppFramework\Http\Attribute\NoAdminRequired; +use OCP\AppFramework\Http\Attribute\NoCSRFRequired; +use OCP\AppFramework\Http\Attribute\PublicPage; use OCP\AppFramework\Http\DataDownloadResponse; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\Http\Response; @@ -98,13 +101,13 @@ public function __construct( // API v3 methods // Forms /** - * @CORS - * @NoAdminRequired - * * Read Form-List of owned forms * Return only with necessary information for Listing. * @return DataResponse */ + #[CORS()] + #[NoAdminRequired()] + #[ApiRoute(verb: 'GET', url: Constants::API_BASE . 'forms', requirements: Constants::API_V3_REQUIREMENTS)] public function getForms(string $type = 'owned'): DataResponse { if ($type === 'owned') { $forms = $this->formMapper->findAllByOwnerId($this->currentUser->getUID()); @@ -123,9 +126,6 @@ public function getForms(string $type = 'owned'): DataResponse { } /** - * @CORS - * @NoAdminRequired - * * Create a new Form and return the Form to edit. * Return a cloned Form if the parameter $fromId is set * @@ -134,6 +134,9 @@ public function getForms(string $type = 'owned'): DataResponse { * @throws OCSBadRequestException * @throws OCSForbiddenException */ + #[CORS()] + #[NoAdminRequired()] + #[ApiRoute(verb: 'POST', url: Constants::API_BASE . 'forms', requirements: Constants::API_V3_REQUIREMENTS)] public function newForm(?int $fromId = null): DataResponse { // Check if user is allowed if (!$this->configService->canCreateForms()) { @@ -199,9 +202,6 @@ public function newForm(?int $fromId = null): DataResponse { } /** - * @CORS - * @NoAdminRequired - * * Read all information to edit a Form (form, questions, options, except submissions/answers). * * @param int $formId Id of the form @@ -209,6 +209,9 @@ public function newForm(?int $fromId = null): DataResponse { * @throws OCSBadRequestException * @throws OCSForbiddenException */ + #[CORS()] + #[NoAdminRequired()] + #[ApiRoute(verb: 'GET', url: Constants::API_BASE . 'forms/{formId}', requirements: Constants::API_V3_REQUIREMENTS)] public function getForm(int $formId): DataResponse { try { $form = $this->formMapper->findById($formId); @@ -228,9 +231,6 @@ public function getForm(int $formId): DataResponse { } /** - * @CORS - * @NoAdminRequired - * * Writes the given key-value pairs into Database. * * @param int $formId FormId of form to update @@ -239,6 +239,9 @@ public function getForm(int $formId): DataResponse { * @throws OCSBadRequestException * @throws OCSForbiddenException */ + #[CORS()] + #[NoAdminRequired()] + #[ApiRoute(verb: 'PATCH', url: Constants::API_BASE . 'forms/{formId}', requirements: Constants::API_V3_REQUIREMENTS)] public function updateForm(int $formId, array $keyValuePairs): DataResponse { $this->logger->debug('Updating form: formId: {formId}, values: {keyValuePairs}', [ 'formId' => $formId, @@ -316,9 +319,6 @@ public function updateForm(int $formId, array $keyValuePairs): DataResponse { } /** - * @CORS - * @NoAdminRequired - * * Delete a form * * @param int $formId the form id @@ -326,6 +326,9 @@ public function updateForm(int $formId, array $keyValuePairs): DataResponse { * @throws OCSBadRequestException * @throws OCSForbiddenException */ + #[CORS()] + #[NoAdminRequired()] + #[ApiRoute(verb: 'DELETE', url: Constants::API_BASE . 'forms/{formId}', requirements: Constants::API_V3_REQUIREMENTS)] public function deleteForm(int $formId): DataResponse { $this->logger->debug('Delete Form: {formId}', [ 'formId' => $formId, @@ -339,9 +342,6 @@ public function deleteForm(int $formId): DataResponse { // Questions /** - * @CORS - * @NoAdminRequired - * * Read all questions (including options) * * @param int $formId FormId @@ -349,6 +349,9 @@ public function deleteForm(int $formId): DataResponse { * @throws OCSBadRequestException * @throws OCSForbiddenException */ + #[CORS()] + #[NoAdminRequired()] + #[ApiRoute(verb: 'GET', url: Constants::API_BASE . 'forms/{formId}/questions', requirements: Constants::API_V3_REQUIREMENTS)] public function getQuestions(int $formId): DataResponse { try { $form = $this->formMapper->findById($formId); @@ -368,9 +371,6 @@ public function getQuestions(int $formId): DataResponse { } /** - * @CORS - * @NoAdminRequired - * * Read a specific question (including options) * * @param int $formId FormId @@ -379,6 +379,9 @@ public function getQuestions(int $formId): DataResponse { * @throws OCSBadRequestException * @throws OCSForbiddenException */ + #[CORS()] + #[NoAdminRequired()] + #[ApiRoute(verb: 'POST', url: Constants::API_BASE . 'forms/{formId}/questions', requirements: Constants::API_V3_REQUIREMENTS)] public function getQuestion(int $formId, int $questionId): DataResponse { try { $form = $this->formMapper->findById($formId); @@ -402,9 +405,6 @@ public function getQuestion(int $formId, int $questionId): DataResponse { } /** - * @CORS - * @NoAdminRequired - * * Add a new question * * @param int $formId the form id @@ -415,6 +415,9 @@ public function getQuestion(int $formId, int $questionId): DataResponse { * @throws OCSBadRequestException * @throws OCSForbiddenException */ + #[CORS()] + #[NoAdminRequired()] + #[ApiRoute(verb: 'GET', url: Constants::API_BASE . 'forms/{formId}/questions/{questionId}', requirements: Constants::API_V3_REQUIREMENTS)] public function newQuestion(int $formId, ?string $type = null, string $text = '', ?int $fromId = null): DataResponse { $form = $this->getFormIfAllowed($formId); if ($this->formsService->isFormArchived($form)) { @@ -508,9 +511,6 @@ public function newQuestion(int $formId, ?string $type = null, string $text = '' } /** - * @CORS - * @NoAdminRequired - * * Writes the given key-value pairs into Database. * Key 'order' should only be changed by reorderQuestions() and is not allowed here. * @@ -521,6 +521,9 @@ public function newQuestion(int $formId, ?string $type = null, string $text = '' * @throws OCSBadRequestException * @throws OCSForbiddenException */ + #[CORS()] + #[NoAdminRequired()] + #[ApiRoute(verb: 'PATCH', url: Constants::API_BASE . 'forms/{formId}/questions/{questionId}', requirements: Constants::API_V3_REQUIREMENTS)] public function updateQuestion(int $formId, int $questionId, array $keyValuePairs): DataResponse { $this->logger->debug('Updating question: formId: {formId}, questionId: {questionId}, values: {keyValuePairs}', [ 'formId' => $formId, @@ -579,9 +582,6 @@ public function updateQuestion(int $formId, int $questionId, array $keyValuePair } /** - * @CORS - * @NoAdminRequired - * * Delete a question * * @param int $formId the form id @@ -590,6 +590,9 @@ public function updateQuestion(int $formId, int $questionId, array $keyValuePair * @throws OCSBadRequestException * @throws OCSForbiddenException */ + #[CORS()] + #[NoAdminRequired()] + #[ApiRoute(verb: 'DELETE', url: Constants::API_BASE . 'forms/{formId}/questions/{questionId}', requirements: Constants::API_V3_REQUIREMENTS)] public function deleteQuestion(int $formId, int $questionId): DataResponse { $this->logger->debug('Mark question as deleted: {questionId}', [ 'questionId' => $questionId, @@ -635,9 +638,6 @@ public function deleteQuestion(int $formId, int $questionId): DataResponse { } /** - * @CORS - * @NoAdminRequired - * * Updates the Order of all Questions of a Form. * * @param int $formId Id of the form to reorder @@ -646,6 +646,9 @@ public function deleteQuestion(int $formId, int $questionId): DataResponse { * @throws OCSBadRequestException * @throws OCSForbiddenException */ + #[CORS()] + #[NoAdminRequired()] + #[ApiRoute(verb: 'PATCH', url: Constants::API_BASE . 'forms/{formId}/questions', requirements: Constants::API_V3_REQUIREMENTS)] public function reorderQuestions(int $formId, array $newOrder): DataResponse { $this->logger->debug('Reordering Questions on Form {formId} as Question-Ids {newOrder}', [ 'formId' => $formId, @@ -726,8 +729,6 @@ public function reorderQuestions(int $formId, array $newOrder): DataResponse { // Options /** - * @NoAdminRequired - * * Add a new option to a question * * @param int $formId id of the form @@ -737,6 +738,9 @@ public function reorderQuestions(int $formId, array $newOrder): DataResponse { * @throws OCSBadRequestException * @throws OCSForbiddenException */ + #[CORS()] + #[NoAdminRequired()] + #[ApiRoute(verb: 'POST', url: Constants::API_BASE . 'forms/{formId}/questions/{questionId}/options', requirements: Constants::API_V3_REQUIREMENTS)] public function newOption(int $formId, int $questionId, array $optionTexts): DataResponse { $this->logger->debug('Adding new options: formId: {formId}, questionId: {questionId}, text: {text}', [ 'formId' => $formId, @@ -797,9 +801,6 @@ public function newOption(int $formId, int $questionId, array $optionTexts): Dat } /** - * @CORS - * @NoAdminRequired - * * Writes the given key-value pairs into Database. * * @param int $formId id of form @@ -810,6 +811,9 @@ public function newOption(int $formId, int $questionId, array $optionTexts): Dat * @throws OCSBadRequestException * @throws OCSForbiddenException */ + #[CORS()] + #[NoAdminRequired()] + #[ApiRoute(verb: 'PATCH', url: Constants::API_BASE . 'forms/{formId}/questions/{questionId}/options/{optionId}', requirements: Constants::API_V3_REQUIREMENTS)] public function updateOption(int $formId, int $questionId, int $optionId, array $keyValuePairs): DataResponse { $this->logger->debug('Updating option: form: {formId}, question: {questionId}, option: {optionId}, values: {keyValuePairs}', [ 'formId' => $formId, @@ -862,9 +866,6 @@ public function updateOption(int $formId, int $questionId, int $optionId, array } /** - * @CORS - * @NoAdminRequired - * * Delete an option * * @param int $formId id of form @@ -874,6 +875,9 @@ public function updateOption(int $formId, int $questionId, int $optionId, array * @throws OCSBadRequestException * @throws OCSForbiddenException */ + #[CORS()] + #[NoAdminRequired()] + #[ApiRoute(verb: 'DELETE', url: Constants::API_BASE . 'forms/{formId}/questions/{questionId}/options/{optionId}', requirements: Constants::API_V3_REQUIREMENTS)] public function deleteOption(int $formId, int $questionId, int $optionId): DataResponse { $this->logger->debug('Deleting option: {optionId}', [ 'optionId' => $optionId @@ -919,6 +923,9 @@ public function deleteOption(int $formId, int $questionId, int $optionId): DataR * @param int $questionId id of question * @param Array $newOrder Order to use */ + #[CORS()] + #[NoAdminRequired()] + #[ApiRoute(verb: 'PATCH', url: Constants::API_BASE . 'forms/{formId}/questions/{questionId}/options', requirements: Constants::API_V3_REQUIREMENTS)] public function reorderOptions(int $formId, int $questionId, array $newOrder) { $form = $this->getFormIfAllowed($formId); if ($this->formsService->isFormArchived($form)) { @@ -1000,9 +1007,6 @@ public function reorderOptions(int $formId, int $questionId, array $newOrder) { // Submissions /** - * @CORS - * @NoAdminRequired - * * Get all the submissions of a given form * * @param int $formId of the form @@ -1010,6 +1014,9 @@ public function reorderOptions(int $formId, int $questionId, array $newOrder) { * @throws OCSNotFoundException * @throws OCSForbiddenException */ + #[CORS()] + #[NoAdminRequired()] + #[ApiRoute(verb: 'GET', url: Constants::API_BASE . 'forms/{formId}/submissions', requirements: Constants::API_V3_REQUIREMENTS)] public function getSubmissions(int $formId, ?string $fileFormat = null): DataResponse|DataDownloadResponse { try { $form = $this->formMapper->findById($formId); @@ -1061,9 +1068,6 @@ public function getSubmissions(int $formId, ?string $fileFormat = null): DataRes } /** - * @CORS - * @NoAdminRequired - * * Delete all submissions of a specified form * * @param int $formId the form id @@ -1071,6 +1075,9 @@ public function getSubmissions(int $formId, ?string $fileFormat = null): DataRes * @throws OCSBadRequestException * @throws OCSForbiddenException */ + #[CORS()] + #[NoAdminRequired()] + #[ApiRoute(verb: 'DELETE', url: Constants::API_BASE . 'forms/{formId}/submissions', requirements: Constants::API_V3_REQUIREMENTS)] public function deleteAllSubmissions(int $formId): DataResponse { $this->logger->debug('Delete all submissions to form: {formId}', [ 'formId' => $formId, @@ -1097,11 +1104,6 @@ public function deleteAllSubmissions(int $formId): DataResponse { } /** - * @CORS - * @NoAdminRequired - * @NoCSRFRequired - * @PublicPage - * * Process a new submission * * @param int $formId the form id @@ -1111,6 +1113,11 @@ public function deleteAllSubmissions(int $formId): DataResponse { * @throws OCSBadRequestException * @throws OCSForbiddenException */ + #[CORS()] + #[NoAdminRequired()] + #[NoCSRFRequired()] + #[PublicPage()] + #[ApiRoute(verb: 'POST', url: Constants::API_BASE . 'forms/{formId}/submissions', requirements: Constants::API_V3_REQUIREMENTS)] public function newSubmission(int $formId, array $answers, string $shareHash = ''): DataResponse { $this->logger->debug('Inserting submission: formId: {formId}, answers: {answers}, shareHash: {shareHash}', [ 'formId' => $formId, @@ -1193,9 +1200,6 @@ public function newSubmission(int $formId, array $answers, string $shareHash = ' } /** - * @CORS - * @NoAdminRequired - * * Delete a specific submission * * @param int $formId the form id @@ -1204,6 +1208,9 @@ public function newSubmission(int $formId, array $answers, string $shareHash = ' * @throws OCSBadRequestException * @throws OCSForbiddenException */ + #[CORS()] + #[NoAdminRequired()] + #[ApiRoute(verb: 'DELETE', url: Constants::API_BASE . 'forms/{formId}/submissions/{submissionId}', requirements: Constants::API_V3_REQUIREMENTS)] public function deleteSubmission(int $formId, int $submissionId): DataResponse { $this->logger->debug('Delete Submission: {submissionId}', [ 'submissionId' => $submissionId, @@ -1236,9 +1243,6 @@ public function deleteSubmission(int $formId, int $submissionId): DataResponse { } /** - * @CORS - * @NoAdminRequired - * * Export Submissions to the Cloud * * @param int $formId of the form @@ -1248,6 +1252,9 @@ public function deleteSubmission(int $formId, int $submissionId): DataResponse { * @throws OCSBadRequestException * @throws OCSForbiddenException */ + #[CORS()] + #[NoAdminRequired()] + #[ApiRoute(verb: 'POST', url: Constants::API_BASE . 'forms/{formId}/submissions/export', requirements: Constants::API_V3_REQUIREMENTS)] public function exportSubmissionsToCloud(int $formId, string $path, string $fileFormat = Constants::DEFAULT_FILE_FORMAT) { try { $form = $this->formMapper->findById($formId); @@ -1267,10 +1274,6 @@ public function exportSubmissionsToCloud(int $formId, string $path, string $file } /** - * @CORS - * @NoAdminRequired - * @PublicPage - * * Uploads a temporary files to the server during form filling * * @param int $formId id of the form @@ -1278,6 +1281,10 @@ public function exportSubmissionsToCloud(int $formId, string $path, string $file * @param string $shareHash hash of the form share * @return Response */ + #[CORS()] + #[NoAdminRequired()] + #[PublicPage()] + #[ApiRoute(verb: 'POST', url: Constants::API_BASE . 'forms/{formId}/submissions/files/{questionId}', requirements: Constants::API_V3_REQUIREMENTS)] public function uploadFiles(int $formId, int $questionId, string $shareHash = ''): Response { $this->logger->debug('Uploading files for formId: {formId}, questionId: {questionId}', [ 'formId' => $formId, diff --git a/lib/Controller/ConfigController.php b/lib/Controller/ConfigController.php index eb5487270..ea5598a36 100644 --- a/lib/Controller/ConfigController.php +++ b/lib/Controller/ConfigController.php @@ -50,6 +50,7 @@ public function __construct( * Get the current AppConfig * @return DataResponse */ + #[FrontpageRoute(verb: 'GET', url: '/config')] public function getAppConfig(): DataResponse { return new DataResponse($this->configService->getAppConfig()); } @@ -62,6 +63,7 @@ public function getAppConfig(): DataResponse { * @param mixed $configValues Corresponding AppConfig Value * */ + #[FrontpageRoute(verb: 'PATCH', url: '/config')] public function updateAppConfig(string $configKey, $configValue): DataResponse { $this->logger->debug('Updating AppConfig: {configKey} => {configValue}', [ 'configKey' => $configKey, diff --git a/lib/Controller/PageController.php b/lib/Controller/PageController.php index 75e431b15..6c29d66ad 100644 --- a/lib/Controller/PageController.php +++ b/lib/Controller/PageController.php @@ -36,6 +36,9 @@ use OCP\Accounts\IAccountManager; use OCP\AppFramework\Controller; use OCP\AppFramework\Db\DoesNotExistException; +use OCP\AppFramework\Http\Attribute\NoAdminRequired; +use OCP\AppFramework\Http\Attribute\NoCSRFRequired; +use OCP\AppFramework\Http\Attribute\PublicPage; use OCP\AppFramework\Http\ContentSecurityPolicy; use OCP\AppFramework\Http\RedirectResponse; use OCP\AppFramework\Http\Response; @@ -71,11 +74,11 @@ public function __construct( } /** - * @NoAdminRequired - * @NoCSRFRequired - * * @return TemplateResponse */ + #[NoAdminRequired()] + #[NoCSRFRequired()] + #[FrontpageRoute(verb: 'GET', url: '/')] public function index(?string $hash = null): TemplateResponse { Util::addScript($this->appName, 'forms-main'); Util::addStyle($this->appName, 'forms'); @@ -93,22 +96,23 @@ public function index(?string $hash = null): TemplateResponse { } /** - * @NoAdminRequired - * @NoCSRFRequired - * * @return TemplateResponse */ + #[NoAdminRequired()] + #[NoCSRFRequired()] + #[FrontpageRoute(verb: 'GET', url: '/{hash}/{view}')] public function views(string $hash): TemplateResponse { return $this->index($hash); } /** - * @NoAdminRequired - * @NoCSRFRequired - * @PublicPage * @param string $hash * @return RedirectResponse|TemplateResponse Redirect to login or internal view. */ + #[NoAdminRequired()] + #[NoCSRFRequired()] + #[PublicPage()] + #[FrontpageRoute(verb: 'GET', url: '/{hash}')] public function internalLinkView(string $hash): Response { $internalView = $this->urlGenerator->linkToRoute('forms.page.views', ['hash' => $hash, 'view' => 'submit']); @@ -147,12 +151,13 @@ public function internalLinkView(string $hash): Response { } /** - * @NoAdminRequired - * @NoCSRFRequired - * @PublicPage * @param string $hash Public sharing hash. * @return TemplateResponse Public template. */ + #[NoAdminRequired()] + #[NoCSRFRequired()] + #[PublicPage()] + #[FrontpageRoute(verb: 'GET', url: '/s/{hash}')] public function publicLinkView(string $hash): Response { try { $share = $this->shareMapper->findPublicShareByHash($hash); @@ -165,13 +170,13 @@ public function publicLinkView(string $hash): Response { } /** - * @NoAdminRequired - * @PublicPage - * @NoCSRFRequired - * * @param string $hash * @return Response */ + #[NoAdminRequired()] + #[NoCSRFRequired()] + #[PublicPage()] + #[FrontpageRoute(verb: 'GET', url: '/embed/{hash}')] public function embeddedFormView(string $hash): Response { try { $share = $this->shareMapper->findPublicShareByHash($hash); diff --git a/lib/Controller/ShareApiController.php b/lib/Controller/ShareApiController.php index e3ee72478..eab3adf7e 100644 --- a/lib/Controller/ShareApiController.php +++ b/lib/Controller/ShareApiController.php @@ -77,9 +77,6 @@ public function __construct( } /** - * @CORS - * @NoAdminRequired - * * Add a new share * * @param int $formId The form to share @@ -89,6 +86,9 @@ public function __construct( * @throws OCSBadRequestException * @throws OCSForbiddenException */ + #[CORS()] + #[NoAdminRequired()] + #[ApiRoute(verb: 'POST', url: Constants::API_BASE . 'forms/{formId}/shares', requirements: Constants::API_V3_REQUIREMENTS)] public function newShare(int $formId, int $shareType, string $shareWith = '', array $permissions = [Constants::PERMISSION_SUBMIT]): DataResponse { $this->logger->debug('Adding new share: formId: {formId}, shareType: {shareType}, shareWith: {shareWith}, permissions: {permissions}', [ 'formId' => $formId, @@ -203,9 +203,6 @@ public function newShare(int $formId, int $shareType, string $shareWith = '', ar } /** - * @CORS - * @NoAdminRequired - * * Update permissions of a share * * @param int $formId of the form @@ -215,6 +212,9 @@ public function newShare(int $formId, int $shareType, string $shareWith = '', ar * @throws OCSBadRequestException * @throws OCSForbiddenException */ + #[CORS()] + #[NoAdminRequired()] + #[ApiRoute(verb: 'PATCH', url: Constants::API_BASE . 'forms/{formId}/shares/{shareId}', requirements: Constants::API_V3_REQUIREMENTS)] public function updateShare(int $formId, int $shareId, array $keyValuePairs): DataResponse { $this->logger->debug('Updating share: {shareId} of form {formId}, permissions: {permissions}', [ 'formId' => $formId, @@ -295,9 +295,6 @@ public function updateShare(int $formId, int $shareId, array $keyValuePairs): Da } /** - * @CORS - * @NoAdminRequired - * * Delete a share * * @param int $formId of the form @@ -306,6 +303,9 @@ public function updateShare(int $formId, int $shareId, array $keyValuePairs): Da * @throws OCSBadRequestException * @throws OCSForbiddenException */ + #[CORS()] + #[NoAdminRequired()] + #[ApiRoute(verb: 'DELETE', url: Constants::API_BASE . 'forms/{formId}/shares/{shareId}', requirements: Constants::API_V3_REQUIREMENTS)] public function deleteShare(int $formId, int $shareId): DataResponse { $this->logger->debug('Deleting share: {shareId} of form {formId}', [ 'formId' => $formId, diff --git a/src/FormsSettings.vue b/src/FormsSettings.vue index a21e39423..08f1cbc89 100644 --- a/src/FormsSettings.vue +++ b/src/FormsSettings.vue @@ -151,7 +151,7 @@ export default { */ async saveAppConfig(configKey, configValue) { try { - await axios.patch(generateUrl('apps/forms/config/update'), { + await axios.patch(generateUrl('apps/forms/config'), { configKey, configValue, })