From c84e09da27a34b46623f09ac78aa9c71b4d7d105 Mon Sep 17 00:00:00 2001 From: Christian Hartmann Date: Wed, 29 Nov 2023 20:11:59 +0100 Subject: [PATCH 1/2] enh: use PUT for updating and move to API v2.2 Signed-off-by: Christian Hartmann --- appinfo/routes.php | 100 +++++++++++++----- docs/API.md | 69 ++++++------ lib/Capabilities.php | 2 +- src/Forms.vue | 10 +- src/FormsSettings.vue | 2 +- src/components/AppNavigationForm.vue | 2 +- src/components/Questions/AnswerInput.vue | 4 +- src/components/Questions/QuestionDropdown.vue | 2 +- src/components/Questions/QuestionMultiple.vue | 2 +- .../SidebarTabs/SharingSidebarTab.vue | 8 +- src/mixins/QuestionMixin.js | 2 +- src/mixins/ViewsMixin.js | 4 +- src/views/Create.vue | 6 +- src/views/Results.vue | 10 +- src/views/Submit.vue | 2 +- tests/Integration/Api/ApiV2Test.php | 22 ++-- 16 files changed, 154 insertions(+), 93 deletions(-) diff --git a/appinfo/routes.php b/appinfo/routes.php index 10cb35c8e..627a6dbb1 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -3,6 +3,7 @@ * @copyright Copyright (c] 2017 Vinzenz Rosenkranz * * @author affan98 + * @author Christian Hartmann * @author John Molakvoæ (skjnldsv) * @author Jonas Rittershofer * @@ -31,11 +32,17 @@ 'url' => '/config', 'verb' => 'GET' ], + // TODO: Remove POST in next API release [ 'name' => 'config#updateAppConfig', 'url' => '/config/update', 'verb' => 'POST' ], + [ + 'name' => 'config#updateAppConfig', + 'url' => '/config/update', + 'verb' => 'PATCH' + ], // Public Share Link [ @@ -72,7 +79,7 @@ 'verb' => 'OPTIONS', 'requirements' => [ 'path' => '.+', - 'apiVersion' => 'v2(\.1)?' + 'apiVersion' => 'v2(\.[1-2])?' ] ], @@ -82,7 +89,7 @@ 'url' => '/api/{apiVersion}/forms', 'verb' => 'GET', 'requirements' => [ - 'apiVersion' => 'v2(\.1)?' + 'apiVersion' => 'v2(\.[1-2])?' ] ], [ @@ -90,7 +97,7 @@ 'url' => '/api/{apiVersion}/form', 'verb' => 'POST', 'requirements' => [ - 'apiVersion' => 'v2(\.1)?' + 'apiVersion' => 'v2(\.[1-2])?' ] ], [ @@ -98,7 +105,7 @@ 'url' => '/api/{apiVersion}/form/{id}', 'verb' => 'GET', 'requirements' => [ - 'apiVersion' => 'v2(\.1)?' + 'apiVersion' => 'v2(\.[1-2])?' ] ], [ @@ -106,15 +113,24 @@ 'url' => '/api/{apiVersion}/form/clone/{id}', 'verb' => 'POST', 'requirements' => [ - 'apiVersion' => 'v2(\.1)?' + 'apiVersion' => 'v2(\.[1-2])?' ] ], + // TODO: Remove POST in next API release [ 'name' => 'api#updateForm', 'url' => '/api/{apiVersion}/form/update', 'verb' => 'POST', 'requirements' => [ - 'apiVersion' => 'v2(\.1)?' + 'apiVersion' => 'v2(\.[1-2])?' + ] + ], + [ + 'name' => 'api#updateForm', + 'url' => '/api/{apiVersion}/form/update', + 'verb' => 'PATCH', + 'requirements' => [ + 'apiVersion' => 'v2.2' ] ], [ @@ -122,7 +138,7 @@ 'url' => '/api/{apiVersion}/form/{id}', 'verb' => 'DELETE', 'requirements' => [ - 'apiVersion' => 'v2(\.1)?' + 'apiVersion' => 'v2(\.[1-2])?' ] ], [ @@ -130,7 +146,7 @@ 'url' => '/api/{apiVersion}/partial_form/{hash}', 'verb' => 'GET', 'requirements' => [ - 'apiVersion' => 'v2(\.1)?' + 'apiVersion' => 'v2(\.[1-2])?' ] ], [ @@ -138,7 +154,7 @@ 'url' => '/api/{apiVersion}/shared_forms', 'verb' => 'GET', 'requirements' => [ - 'apiVersion' => 'v2(\.1)?' + 'apiVersion' => 'v2(\.[1-2])?' ] ], @@ -148,23 +164,41 @@ 'url' => '/api/{apiVersion}/question', 'verb' => 'POST', 'requirements' => [ - 'apiVersion' => 'v2(\.1)?' + 'apiVersion' => 'v2(\.[1-2])?' ] ], + // TODO: Remove POST in next API release [ 'name' => 'api#updateQuestion', 'url' => '/api/{apiVersion}/question/update', 'verb' => 'POST', 'requirements' => [ - 'apiVersion' => 'v2(\.1)?' + 'apiVersion' => 'v2(\.[1-2])?' + ] + ], + [ + 'name' => 'api#updateQuestion', + 'url' => '/api/{apiVersion}/question/update', + 'verb' => 'PATCH', + 'requirements' => [ + 'apiVersion' => 'v2.2' ] ], + // TODO: Remove POST in next API release [ 'name' => 'api#reorderQuestions', 'url' => '/api/{apiVersion}/question/reorder', 'verb' => 'POST', 'requirements' => [ - 'apiVersion' => 'v2(\.1)?' + 'apiVersion' => 'v2(\.[1-2])?' + ] + ], + [ + 'name' => 'api#reorderQuestions', + 'url' => '/api/{apiVersion}/question/reorder', + 'verb' => 'PUT', + 'requirements' => [ + 'apiVersion' => 'v2.2' ] ], [ @@ -172,7 +206,7 @@ 'url' => '/api/{apiVersion}/question/{id}', 'verb' => 'DELETE', 'requirements' => [ - 'apiVersion' => 'v2(\.1)?' + 'apiVersion' => 'v2(\.[1-2])?' ] ], @@ -182,15 +216,24 @@ 'url' => '/api/{apiVersion}/option', 'verb' => 'POST', 'requirements' => [ - 'apiVersion' => 'v2(\.1)?' + 'apiVersion' => 'v2(\.[1-2])?' ] ], + // TODO: Remove POST in next API release [ 'name' => 'api#updateOption', 'url' => '/api/{apiVersion}/option/update', 'verb' => 'POST', 'requirements' => [ - 'apiVersion' => 'v2(\.1)?' + 'apiVersion' => 'v2(\.[1-2])?' + ] + ], + [ + 'name' => 'api#updateOption', + 'url' => '/api/{apiVersion}/option/update', + 'verb' => 'PATCH', + 'requirements' => [ + 'apiVersion' => 'v2.2' ] ], [ @@ -198,7 +241,7 @@ 'url' => '/api/{apiVersion}/option/{id}', 'verb' => 'DELETE', 'requirements' => [ - 'apiVersion' => 'v2(\.1)?' + 'apiVersion' => 'v2(\.[1-2])?' ] ], @@ -208,7 +251,7 @@ 'url' => '/api/{apiVersion}/share', 'verb' => 'POST', 'requirements' => [ - 'apiVersion' => 'v2(\.1)?' + 'apiVersion' => 'v2(\.[1-2])?' ] ], [ @@ -216,9 +259,10 @@ 'url' => '/api/{apiVersion}/share/{id}', 'verb' => 'DELETE', 'requirements' => [ - 'apiVersion' => 'v2(\.1)?' + 'apiVersion' => 'v2(\.[1-2])?' ] ], + // TODO: Remove POST in next API release [ 'name' => 'shareApi#updateShare', 'url' => '/api/{apiVersion}/share/update', @@ -227,6 +271,14 @@ 'apiVersion' => 'v2.1' ] ], + [ + 'name' => 'shareApi#updateShare', + 'url' => '/api/{apiVersion}/share/update', + 'verb' => 'PATCH', + 'requirements' => [ + 'apiVersion' => 'v2.2' + ] + ], // Submissions [ @@ -234,7 +286,7 @@ 'url' => '/api/{apiVersion}/submissions/{hash}', 'verb' => 'GET', 'requirements' => [ - 'apiVersion' => 'v2(\.1)?' + 'apiVersion' => 'v2(\.[1-2])?' ] ], [ @@ -242,7 +294,7 @@ 'url' => '/api/{apiVersion}/submissions/export/{hash}', 'verb' => 'GET', 'requirements' => [ - 'apiVersion' => 'v2(\.1)?' + 'apiVersion' => 'v2(\.[1-2])?' ] ], [ @@ -250,7 +302,7 @@ 'url' => '/api/{apiVersion}/submissions/export', 'verb' => 'POST', 'requirements' => [ - 'apiVersion' => 'v2(\.1)?' + 'apiVersion' => 'v2(\.[1-2])?' ] ], [ @@ -258,7 +310,7 @@ 'url' => '/api/{apiVersion}/submissions/{formId}', 'verb' => 'DELETE', 'requirements' => [ - 'apiVersion' => 'v2(\.1)?' + 'apiVersion' => 'v2(\.[1-2])?' ] ], [ @@ -266,7 +318,7 @@ 'url' => '/api/{apiVersion}/submission/insert', 'verb' => 'POST', 'requirements' => [ - 'apiVersion' => 'v2(\.1)?' + 'apiVersion' => 'v2(\.[1-2])?' ] ], [ @@ -274,7 +326,7 @@ 'url' => '/api/{apiVersion}/submission/{id}', 'verb' => 'DELETE', 'requirements' => [ - 'apiVersion' => 'v2(\.1)?' + 'apiVersion' => 'v2(\.[1-2])?' ] ], ] diff --git a/docs/API.md b/docs/API.md index 833e2d6b7..5871dd534 100644 --- a/docs/API.md +++ b/docs/API.md @@ -20,6 +20,9 @@ This file contains the API-Documentation. For more information on the returned D } ``` ## API changes +### Deprecation info +- Starting with API v2.2 all endpoints that update data will use PUT as method. POST is now deprecated and will be removed in API v3 + ### Breaking Changes on API v2 - The `mandatory` property of questions has been removed. It is replaced by `isRequired`. - Completely new way of handling access & shares. @@ -30,7 +33,7 @@ This file contains the API-Documentation. For more information on the returned D ## Form Endpoints ### List owned Forms Returns condensed objects of all Forms beeing owned by the authenticated user. -- Endpoint: `/api/v2.1/forms` +- Endpoint: `/api/v2.2/forms` - Method: `GET` - Parameters: None - Response: Array of condensed Form Objects, sorted as newest first. @@ -65,7 +68,7 @@ Returns condensed objects of all Forms beeing owned by the authenticated user. ### List shared Forms Returns condensed objects of all Forms, that are shared & shown to the authenticated user and that have not expired yet. -- Endpoint: `/api/v2.1/shared_forms` +- Endpoint: `/api/v2.2/shared_forms` - Method: `GET` - Parameters: None - Response: Array of condensed Form Objects, sorted as newest first, similar to [List owned Forms](#list-owned-forms). @@ -75,7 +78,7 @@ See above, 'List owned forms' ### Get a partial Form Returns a single partial form object, corresponding to owned/shared form-listings. -- Endpoint: `/api/v2.1/partial_form/{hash}` +- Endpoint: `/api/v2.2/partial_form/{hash}` - Method: `GET` - Url-Parameter: | Parameter | Type | Description | @@ -96,7 +99,7 @@ Returns a single partial form object, corresponding to owned/shared form-listing ``` ### Create a new Form -- Endpoint: `/api/v2.1/form` +- Endpoint: `/api/v2.2/form` - Method: `POST` - Parameters: None - Response: The new form object, similar to requesting an existing form. @@ -106,7 +109,7 @@ See next section, 'Request full data of a form' ### Request full data of a form Returns the full-depth object of the requested form (without submissions). -- Endpoint: `/api/v2.1/form/{id}` +- Endpoint: `/api/v2.2/form/{id}` - Url-Parameter: | Parameter | Type | Description | |-----------|---------|-------------| @@ -192,7 +195,7 @@ Returns the full-depth object of the requested form (without submissions). ### Clone a form Creates a clone of a form (without submissions). -- Endpoint: `/api/v2.1/form/clone/{id}` +- Endpoint: `/api/v2.2/form/clone/{id}` - Url-Parameter: | Parameter | Type | Description | |-----------|---------|-------------| @@ -205,8 +208,9 @@ See section 'Request full data of a form'. ### Update form properties Update a single or multiple properties of a form-object. Concerns **only** the Form-Object, properties of Questions, Options and Submissions, as well as their creation or deletion, are handled separately. -- Endpoint: `/api/v2.1/form/update` -- Method: `POST` +- Endpoint: `/api/v2.2/form/update` +- Method: `PATCH` +- *Method: `POST` deprecated* - Parameters: | Parameter | Type | Description | |-----------|---------|-------------| @@ -219,7 +223,7 @@ Update a single or multiple properties of a form-object. Concerns **only** the F ``` ### Delete a form -- Endpoint: `/api/v2.1/form/{id}` +- Endpoint: `/api/v2.2/form/{id}` - Url-Parameter: | Parameter | Type | Description | |-----------|---------|-------------| @@ -234,7 +238,7 @@ Update a single or multiple properties of a form-object. Concerns **only** the F Contains only manipulative question-endpoints. To retrieve questions, request the full form data. ### Create a new question -- Endpoint: `/api/v2.1/question` +- Endpoint: `/api/v2.2/question` - Method: `POST` - Parameters: | Parameter | Type | Optional | Description | @@ -259,8 +263,9 @@ Contains only manipulative question-endpoints. To retrieve questions, request th ### Update question properties Update a single or multiple properties of a question-object. -- Endpoint: `/api/v2.1/question/update` -- Method: `POST` +- Endpoint: `/api/v2.2/question/update` +- Method: `PATCH` +- *Method: `POST` deprecated* - Parameters: | Parameter | Type | Description | |-----------|---------|-------------| @@ -274,8 +279,9 @@ Update a single or multiple properties of a question-object. ### Reorder questions Reorders all Questions of a single form -- Endpoint: `/api/v2.1/question/reorder` -- Method: `POST` +- Endpoint: `/api/v2.2/question/reorder` +- Method: `PUT` +- *Method: `POST` deprecated* - Parameters: | Parameter | Type | Description | |-----------|---------|-------------| @@ -298,7 +304,7 @@ Reorders all Questions of a single form ``` ### Delete a question -- Endpoint: `/api/v2.1/question/{id}` +- Endpoint: `/api/v2.2/question/{id}` - Url-Parameter: | Parameter | Type | Description | |-----------|---------|-------------| @@ -313,7 +319,7 @@ Reorders all Questions of a single form Contains only manipulative question-endpoints. To retrieve options, request the full form data. ### Create a new Option -- Endpoint: `/api/v2.1/option` +- Endpoint: `/api/v2.2/option` - Method: `POST` - Parameters: | Parameter | Type | Description | @@ -330,8 +336,10 @@ Contains only manipulative question-endpoints. To retrieve options, request the ``` ### Update option properties -- Endpoint: `/api/v2.1/option/update` -- Method: `POST` +Update a single or all properties of an option-object +- Endpoint: `/api/v2.2/option/update` +- Method: `PATCH` +- *Method: `POST` deprecated* - Parameters: | Parameter | Type | Description | |-----------|---------|-------------| @@ -344,7 +352,7 @@ Contains only manipulative question-endpoints. To retrieve options, request the ``` ### Delete an option -- Endpoint: `/api/v2.1/option/{id}` +- Endpoint: `/api/v2.2/option/{id}` - Url-Parameter: | Parameter | Type | Description | |-----------|---------|-------------| @@ -357,7 +365,7 @@ Contains only manipulative question-endpoints. To retrieve options, request the ## Sharing Endpoints ### Add a new Share -- Endpoint: `/api/v2.1/share` +- Endpoint: `/api/v2.2/share` - Method: `POST` - Parameters: | Parameter | Type | Description | @@ -379,7 +387,7 @@ Contains only manipulative question-endpoints. To retrieve options, request the ``` ### Delete a Share -- Endpoint: `/api/v2.1/share/{id}` +- Endpoint: `/api/v2.2/share/{id}` - Url-Parameter: | Parameter | Type | Description | |-----------|---------|-------------| @@ -391,15 +399,16 @@ Contains only manipulative question-endpoints. To retrieve options, request the ``` ### Update a Share -- Endpoint: `/api/v2.1/share/update` -- Url-Parameter: +- Endpoint: `/api/v2.2/share/update` +- Parameters: | Parameter | Type | Description | |------------------|----------|-------------| | _id_ | Integer | ID of the share to update | | *keyValuePairs*¹ | Array | Array of key-value pairs to update | ¹Currently only the _permissions_ can be updated. -- Method: `POST` +- Method: `PATCH` +- *Method: `POST` deprecated* - Response: **Status-Code OK**, as well as the id of the share object. ``` "data": 5 @@ -408,7 +417,7 @@ Contains only manipulative question-endpoints. To retrieve options, request the ## Submission Endpoints ### Get Form Submissions Get all Submissions to a Form -- Endpoint: `/api/v2.1/submissions/{hash}` +- Endpoint: `/api/v2.2/submissions/{hash}` - Url-Parameter: | Parameter | Type | Description | |-----------|---------|-------------| @@ -504,7 +513,7 @@ Get all Submissions to a Form ### Get Submissions as csv (Download) Returns all submissions to the form in form of a csv-file. -- Endpoint: `/api/v2.1/submissions/export/{hash}` +- Endpoint: `/api/v2.2/submissions/export/{hash}` - Url-Parameter: | Parameter | Type | Description | |-----------|---------|-------------| @@ -519,7 +528,7 @@ Returns all submissions to the form in form of a csv-file. ### Export Submissions to Cloud (Files-App) Creates a csv file and stores it to the cloud, resp. Files-App. -- Endpoint: `/api/v2.1/submissions/export` +- Endpoint: `/api/v2.2/submissions/export` - Method: `POST` - Parameters: | Parameter | Type | Description | @@ -533,7 +542,7 @@ Creates a csv file and stores it to the cloud, resp. Files-App. ### Delete Submissions Delete all Submissions to a form -- Endpoint: `/api/v2.1/submissions/{formId}` +- Endpoint: `/api/v2.2/submissions/{formId}` - Url-Parameter: | Parameter | Type | Description | |-----------|---------|-------------| @@ -546,7 +555,7 @@ Delete all Submissions to a form ### Insert a Submission Store Submission to Database -- Endpoint: `/api/v2.1/submission/insert` +- Endpoint: `/api/v2.2/submission/insert` - Method: `POST` - Parameters: | Parameter | Type | Description | @@ -568,7 +577,7 @@ Store Submission to Database - Response: **Status-Code OK**. ### Delete a single Submission -- Endpoint: `/api/v2.1/submission/{id}` +- Endpoint: `/api/v2.2/submission/{id}` - Url-Parameter: | Parameter | Type | Description | |-----------|---------|-------------| diff --git a/lib/Capabilities.php b/lib/Capabilities.php index 93b42b60f..affdaf587 100644 --- a/lib/Capabilities.php +++ b/lib/Capabilities.php @@ -42,7 +42,7 @@ public function getCapabilities() { return [ 'forms' => [ 'version' => $this->appManager->getAppVersion('forms'), - 'apiVersions' => ['v2','v2.1'] + 'apiVersions' => ['v2','v2.1','v2.2'] ] ]; } diff --git a/src/Forms.vue b/src/Forms.vue index b8eedcce6..e3c400f54 100644 --- a/src/Forms.vue +++ b/src/Forms.vue @@ -267,7 +267,7 @@ export default { // Load Owned forms try { - const response = await axios.get(generateOcsUrl('apps/forms/api/v2.1/forms')) + const response = await axios.get(generateOcsUrl('apps/forms/api/v2.2/forms')) this.forms = OcsResponse2Data(response) } catch (error) { logger.error('Error while loading owned forms list', { error }) @@ -276,7 +276,7 @@ export default { // Load shared forms try { - const response = await axios.get(generateOcsUrl('apps/forms/api/v2.1/shared_forms')) + const response = await axios.get(generateOcsUrl('apps/forms/api/v2.2/shared_forms')) this.sharedForms = OcsResponse2Data(response) } catch (error) { logger.error('Error while loading shared forms list', { error }) @@ -295,7 +295,7 @@ export default { this.loading = true try { - const response = await axios.get(generateOcsUrl('apps/forms/api/v2.1/partial_form/{hash}', { hash })) + const response = await axios.get(generateOcsUrl('apps/forms/api/v2.2/partial_form/{hash}', { hash })) const form = OcsResponse2Data(response) // If the user has (at least) submission-permissions, add it to the shared forms @@ -316,7 +316,7 @@ export default { async onNewForm() { try { // Request a new empty form - const response = await axios.post(generateOcsUrl('apps/forms/api/v2.1/form')) + const response = await axios.post(generateOcsUrl('apps/forms/api/v2.2/form')) const newForm = OcsResponse2Data(response) this.forms.unshift(newForm) this.$router.push({ name: 'edit', params: { hash: newForm.hash } }) @@ -334,7 +334,7 @@ export default { */ async onCloneForm(id) { try { - const response = await axios.post(generateOcsUrl('apps/forms/api/v2.1/form/clone/{id}', { id })) + const response = await axios.post(generateOcsUrl('apps/forms/api/v2.2/form/clone/{id}', { id })) const newForm = OcsResponse2Data(response) this.forms.unshift(newForm) this.$router.push({ name: 'edit', params: { hash: newForm.hash } }) diff --git a/src/FormsSettings.vue b/src/FormsSettings.vue index 5f1a10fd2..dbbd5f4c5 100644 --- a/src/FormsSettings.vue +++ b/src/FormsSettings.vue @@ -126,7 +126,7 @@ export default { */ async saveAppConfig(configKey, configValue) { try { - await axios.post(generateUrl('apps/forms/config/update'), { + await axios.patch(generateUrl('apps/forms/config/update'), { configKey, configValue, }) diff --git a/src/components/AppNavigationForm.vue b/src/components/AppNavigationForm.vue index 9f860990f..43225e099 100644 --- a/src/components/AppNavigationForm.vue +++ b/src/components/AppNavigationForm.vue @@ -223,7 +223,7 @@ export default { // All good, let's delete this.loading = true try { - await axios.delete(generateOcsUrl('apps/forms/api/v2.1/form/{id}', { id: this.form.id })) + await axios.delete(generateOcsUrl('apps/forms/api/v2.2/form/{id}', { id: this.form.id })) this.$emit('delete', this.form.id) } catch (error) { logger.error(`Error while deleting ${this.formTitle}`, { error: error.response }) diff --git a/src/components/Questions/AnswerInput.vue b/src/components/Questions/AnswerInput.vue index 28247a802..6199cbdd0 100644 --- a/src/components/Questions/AnswerInput.vue +++ b/src/components/Questions/AnswerInput.vue @@ -166,7 +166,7 @@ export default { */ async createAnswer(answer) { try { - const response = await axios.post(generateOcsUrl('apps/forms/api/v2.1/option'), { + const response = await axios.post(generateOcsUrl('apps/forms/api/v2.2/option'), { questionId: answer.questionId, text: answer.text, }) @@ -194,7 +194,7 @@ export default { */ async updateAnswer(answer) { try { - await axios.post(generateOcsUrl('apps/forms/api/v2.1/option/update'), { + await axios.patch(generateOcsUrl('apps/forms/api/v2.2/option/update'), { id: this.answer.id, keyValuePairs: { text: answer.text, diff --git a/src/components/Questions/QuestionDropdown.vue b/src/components/Questions/QuestionDropdown.vue index b87243439..fde7b90b1 100644 --- a/src/components/Questions/QuestionDropdown.vue +++ b/src/components/Questions/QuestionDropdown.vue @@ -290,7 +290,7 @@ export default { if (!option.local) { // let's not await, deleting in background - axios.delete(generateOcsUrl('apps/forms/api/v2.1/option/{id}', { id: option.id })) + axios.delete(generateOcsUrl('apps/forms/api/v2.2/option/{id}', { id: option.id })) .catch(error => { logger.error('Error while deleting an option', { option, error }) showError(t('forms', 'There was an issue deleting this option')) diff --git a/src/components/Questions/QuestionMultiple.vue b/src/components/Questions/QuestionMultiple.vue index 735cec1e4..067d6c944 100644 --- a/src/components/Questions/QuestionMultiple.vue +++ b/src/components/Questions/QuestionMultiple.vue @@ -439,7 +439,7 @@ export default { if (!option.local) { // let's not await, deleting in background - axios.delete(generateOcsUrl('apps/forms/api/v2.1/option/{id}', { id: option.id })) + axios.delete(generateOcsUrl('apps/forms/api/v2.2/option/{id}', { id: option.id })) .catch(error => { logger.error('Error while deleting an option', { error, option }) showError(t('forms', 'There was an issue deleting this option')) diff --git a/src/components/SidebarTabs/SharingSidebarTab.vue b/src/components/SidebarTabs/SharingSidebarTab.vue index 2205a4bd1..deb6b67cf 100644 --- a/src/components/SidebarTabs/SharingSidebarTab.vue +++ b/src/components/SidebarTabs/SharingSidebarTab.vue @@ -240,7 +240,7 @@ export default { this.isLoading = true try { - const response = await axios.post(generateOcsUrl('apps/forms/api/v2.1/share'), { + const response = await axios.post(generateOcsUrl('apps/forms/api/v2.2/share'), { formId: this.form.id, shareType: newShare.shareType, shareWith: newShare.shareWith, @@ -262,7 +262,7 @@ export default { this.isLoading = true try { - const response = await axios.post(generateOcsUrl('apps/forms/api/v2.1/share'), { + const response = await axios.post(generateOcsUrl('apps/forms/api/v2.2/share'), { formId: this.form.id, shareType: this.SHARE_TYPES.SHARE_TYPE_LINK, }) @@ -288,7 +288,7 @@ export default { this.isLoading = true try { - const response = await axios.post(generateOcsUrl('apps/forms/api/v2.1/share/update'), { + const response = await axios.patch(generateOcsUrl('apps/forms/api/v2.2/share/update'), { id: updatedShare.id, keyValuePairs: { permissions: updatedShare.permissions, @@ -316,7 +316,7 @@ export default { this.isLoading = true try { - await axios.delete(generateOcsUrl('apps/forms/api/v2.1/share/{id}', { + await axios.delete(generateOcsUrl('apps/forms/api/v2.2/share/{id}', { id: share.id, })) this.$emit('remove-share', share) diff --git a/src/mixins/QuestionMixin.js b/src/mixins/QuestionMixin.js index 6ba28d868..c34d634c0 100644 --- a/src/mixins/QuestionMixin.js +++ b/src/mixins/QuestionMixin.js @@ -332,7 +332,7 @@ export default { async saveQuestionProperty(key, value) { try { // TODO: add loading status feedback ? - await axios.post(generateOcsUrl('apps/forms/api/v2.1/question/update'), { + await axios.patch(generateOcsUrl('apps/forms/api/v2.2/question/update'), { id: this.id, keyValuePairs: { [key]: value, diff --git a/src/mixins/ViewsMixin.js b/src/mixins/ViewsMixin.js index 19855d47b..3c83363e1 100644 --- a/src/mixins/ViewsMixin.js +++ b/src/mixins/ViewsMixin.js @@ -127,7 +127,7 @@ export default { this.cancelFetchFullForm = cancel try { - const response = await request(generateOcsUrl('apps/forms/api/v2.1/form/{id}', { id })) + const response = await request(generateOcsUrl('apps/forms/api/v2.2/form/{id}', { id })) this.$emit('update:form', OcsResponse2Data(response)) this.isLoadingForm = false } catch (error) { @@ -147,7 +147,7 @@ export default { async saveFormProperty(key) { try { // TODO: add loading status feedback ? - await axios.post(generateOcsUrl('apps/forms/api/v2.1/form/update'), { + await axios.patch(generateOcsUrl('apps/forms/api/v2.2/form/update'), { id: this.form.id, keyValuePairs: { [key]: this.form[key], diff --git a/src/views/Create.vue b/src/views/Create.vue index c9c158cff..e2ede5066 100644 --- a/src/views/Create.vue +++ b/src/views/Create.vue @@ -341,7 +341,7 @@ export default { this.isLoadingQuestions = true try { - const response = await axios.post(generateOcsUrl('apps/forms/api/v2.1/question'), { + const response = await axios.post(generateOcsUrl('apps/forms/api/v2.2/question'), { formId: this.form.id, type, text, @@ -381,7 +381,7 @@ export default { this.isLoadingQuestions = true try { - await axios.delete(generateOcsUrl('apps/forms/api/v2.1/question/{id}', { id })) + await axios.delete(generateOcsUrl('apps/forms/api/v2.2/question/{id}', { id })) const index = this.form.questions.findIndex(search => search.id === id) this.form.questions.splice(index, 1) emit('forms:last-updated:set', this.form.id) @@ -401,7 +401,7 @@ export default { const newOrder = this.form.questions.map(question => question.id) try { - await axios.post(generateOcsUrl('apps/forms/api/v2.1/question/reorder'), { + await axios.put(generateOcsUrl('apps/forms/api/v2.2/question/reorder'), { formId: this.form.id, newOrder, }) diff --git a/src/views/Results.vue b/src/views/Results.vue index de7df5dd7..6b333312a 100644 --- a/src/views/Results.vue +++ b/src/views/Results.vue @@ -230,7 +230,7 @@ export default { logger.debug(`Loading results for form ${this.form.hash}`) try { - const response = await axios.get(generateOcsUrl('apps/forms/api/v2.1/submissions/{hash}', { hash: this.form.hash })) + const response = await axios.get(generateOcsUrl('apps/forms/api/v2.2/submissions/{hash}', { hash: this.form.hash })) let loadedSubmissions = OcsResponse2Data(response).submissions const loadedQuestions = OcsResponse2Data(response).questions @@ -249,7 +249,7 @@ export default { }, async onDownloadCsv() { - const exportUrl = generateOcsUrl('apps/forms/api/v2.1/submissions/export/{hash}', { hash: this.form.hash }) + '?requesttoken=' + encodeURIComponent(getRequestToken()) + const exportUrl = generateOcsUrl('apps/forms/api/v2.2/submissions/export/{hash}', { hash: this.form.hash }) + '?requesttoken=' + encodeURIComponent(getRequestToken()) window.open(exportUrl, '_self') }, @@ -259,7 +259,7 @@ export default { picker.pick() .then(async (path) => { try { - const response = await axios.post(generateOcsUrl('apps/forms/api/v2.1/submissions/export'), { + const response = await axios.post(generateOcsUrl('apps/forms/api/v2.2/submissions/export'), { hash: this.form.hash, path, }) @@ -275,7 +275,7 @@ export default { this.loadingResults = true try { - await axios.delete(generateOcsUrl('apps/forms/api/v2.1/submission/{id}', { id })) + await axios.delete(generateOcsUrl('apps/forms/api/v2.2/submission/{id}', { id })) const index = this.form.submissions.findIndex(search => search.id === id) this.form.submissions.splice(index, 1) emit('forms:last-updated:set', this.form.id) @@ -294,7 +294,7 @@ export default { this.loadingResults = true try { - await axios.delete(generateOcsUrl('apps/forms/api/v2.1/submissions/{formId}', { formId: this.form.id })) + await axios.delete(generateOcsUrl('apps/forms/api/v2.2/submissions/{formId}', { formId: this.form.id })) this.form.submissions = [] emit('forms:last-updated:set', this.form.id) } catch (error) { diff --git a/src/views/Submit.vue b/src/views/Submit.vue index ba5b52833..3619a7268 100644 --- a/src/views/Submit.vue +++ b/src/views/Submit.vue @@ -477,7 +477,7 @@ export default { this.loading = true try { - await axios.post(generateOcsUrl('apps/forms/api/v2.1/submission/insert'), { + await axios.post(generateOcsUrl('apps/forms/api/v2.2/submission/insert'), { formId: this.form.id, answers: this.answers, shareHash: this.shareHash, diff --git a/tests/Integration/Api/ApiV2Test.php b/tests/Integration/Api/ApiV2Test.php index 50b937406..ff6569e41 100644 --- a/tests/Integration/Api/ApiV2Test.php +++ b/tests/Integration/Api/ApiV2Test.php @@ -502,7 +502,7 @@ public function dataGetNewForm() { * @param array $expected */ public function testGetNewForm(array $expected): void { - $resp = $this->http->request('POST', 'api/v2.1/form'); + $resp = $this->http->request('POST', 'api/v2.2/form'); $data = $this->OcsResponse2Data($resp); // Store for deletion on tearDown @@ -722,7 +722,7 @@ public function dataUpdateFormProperties() { * @param array $expected */ public function testUpdateFormProperties(array $expected): void { - $resp = $this->http->request('POST', 'api/v2.1/form/update', [ + $resp = $this->http->request('PATCH', 'api/v2.2/form/update', [ 'json' => [ 'id' => $this->testForms[0]['id'], 'keyValuePairs' => [ @@ -797,7 +797,7 @@ public function dataCreateNewQuestion() { * @param array $expected */ public function testCreateNewQuestion(array $expected): void { - $resp = $this->http->request('POST', 'api/v2.1/question', [ + $resp = $this->http->request('POST', 'api/v2.2/question', [ 'json' => [ 'formId' => $this->testForms[0]['id'], 'type' => 'short', @@ -837,7 +837,7 @@ public function dataUpdateQuestionProperties() { * @param array $fullFormExpected */ public function testUpdateQuestionProperties(array $fullFormExpected): void { - $resp = $this->http->request('POST', 'api/v2.1/question/update', [ + $resp = $this->http->request('PATCH', 'api/v2.2/question/update', [ 'json' => [ 'id' => $this->testForms[0]['questions'][0]['id'], 'keyValuePairs' => [ @@ -879,7 +879,7 @@ public function dataReorderQuestions() { * @param array $fullFormExpected */ public function testReorderQuestions(array $fullFormExpected): void { - $resp = $this->http->request('POST', 'api/v2.1/question/reorder', [ + $resp = $this->http->request('PUT', 'api/v2.2/question/reorder', [ 'json' => [ 'formId' => $this->testForms[0]['id'], 'newOrder' => [ @@ -946,7 +946,7 @@ public function dataCreateNewOption() { * @param array $expected */ public function testCreateNewOption(array $expected): void { - $resp = $this->http->request('POST', 'api/v2.1/option', [ + $resp = $this->http->request('POST', 'api/v2.2/option', [ 'json' => [ 'questionId' => $this->testForms[0]['questions'][1]['id'], 'text' => 'A new Option.' @@ -982,7 +982,7 @@ public function dataUpdateOptionProperties() { * @param array $fullFormExpected */ public function testUpdateOptionProperties(array $fullFormExpected): void { - $resp = $this->http->request('POST', 'api/v2.1/option/update', [ + $resp = $this->http->request('PATCH', 'api/v2.2/option/update', [ 'json' => [ 'id' => $this->testForms[0]['questions'][1]['options'][0]['id'], 'keyValuePairs' => [ @@ -1047,7 +1047,7 @@ public function dataAddShare() { * @param array $expected */ public function testAddShare(array $expected) { - $resp = $this->http->request('POST', 'api/v2.1/share', [ + $resp = $this->http->request('POST', 'api/v2.2/share', [ 'json' => [ 'formId' => $this->testForms[0]['id'], 'shareType' => 0, @@ -1083,7 +1083,7 @@ public function dataUpdateShare() { * @param array $fullFormExpected */ public function testUpdateShare(array $fullFormExpected) { - $resp = $this->http->request('POST', 'api/v2.1/share/update', [ + $resp = $this->http->request('PATCH', 'api/v2.2/share/update', [ 'json' => [ 'id' => $this->testForms[0]['shares'][0]['id'], 'keyValuePairs' => [ @@ -1258,7 +1258,7 @@ public function testExportSubmissions(string $expected) { } public function testExportToCloud() { - $resp = $this->http->request('POST', 'api/v2.1/submissions/export', [ + $resp = $this->http->request('POST', 'api/v2.2/submissions/export', [ 'json' => [ 'hash' => $this->testForms[0]['hash'], 'path' => '' @@ -1313,7 +1313,7 @@ public function dataInsertSubmission() { * @param array $submissionsExpected */ public function testInsertSubmission(array $submissionsExpected) { - $resp = $this->http->request('POST', 'api/v2.1/submission/insert', [ + $resp = $this->http->request('POST', 'api/v2.2/submission/insert', [ 'json' => [ 'formId' => $this->testForms[0]['id'], 'answers' => [ From 7a147d9754f285ccb9ade0661e8dd86c7ef6e0f4 Mon Sep 17 00:00:00 2001 From: Chartman123 Date: Mon, 4 Dec 2023 08:41:14 +0100 Subject: [PATCH 2/2] Update appinfo/routes.php Co-authored-by: Ferdinand Thiessen Signed-off-by: Chartman123 --- appinfo/routes.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/appinfo/routes.php b/appinfo/routes.php index 627a6dbb1..269682834 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -32,12 +32,6 @@ 'url' => '/config', 'verb' => 'GET' ], - // TODO: Remove POST in next API release - [ - 'name' => 'config#updateAppConfig', - 'url' => '/config/update', - 'verb' => 'POST' - ], [ 'name' => 'config#updateAppConfig', 'url' => '/config/update',