From f88aeb5e402f61f9ede2334bc335f5033ad9c6bd Mon Sep 17 00:00:00 2001 From: Robert Zondervan Date: Wed, 6 Nov 2024 16:37:09 +0100 Subject: [PATCH 01/46] Authentication documentatio --- docs/authentication.md | 80 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 docs/authentication.md diff --git a/docs/authentication.md b/docs/authentication.md new file mode 100644 index 0000000..0f0a4ea --- /dev/null +++ b/docs/authentication.md @@ -0,0 +1,80 @@ +# Authentication on sources + +In order to authenticate on other sources there are possibilities based upon the way the source expects autentication parameters. +These parameters can be set in the source configuration. For example, if the source expects an API key in the headers, we can set the parameter `headers.Authorization` with the API key as value. + +Usually, sources tend to use dynamic authorization parameters in order to prevent the same authentication parameter from being used by adversaries that catch a call and deduce the parameter. + +At the moment, OpenConnector supports two dynamic authentication methods, OAuth and JWT Bearers. + +## OAuth + +To use OAuth we put in our Authorization header the following value: +```twig +Bearer {{ oauthToken(source) }} +``` +This will impose an OAuth 2.0 access token after `Bearer` if the field `authenticationConfig` contains correct values. +OpenConnector supports the OAuth 2.0 protocol with client credentials and password credentials as grant_types. + +>[!NOTE] +> TODO: How to add authenticationConfig parameters in frontend + +When using OAuth, OpenConnector supports the following parameters: + +### Standard parameters +- `grant_type`: The type of grant we have to use at the source. Supported are `client_credentials` and `password` +- `scope`: The scope(s) needed to perform the requests we want to do in the API. +- `tokenUrl`: The URL used to fetch the actual access token. Usually this url can be recognised by its path ending on `/oauth/token` +- `authentication`: Location of the credentials, either `body` for credentials included in the request body, or `basic_auth` when the credentials have to be sent as a basic_auth header. _[!warning] Only used when `grant_type` is `client_credentials`_ +- `client_id`: The client id of the OAuth client _[!note] Only used when `grant_type` is `client_credentials`_ +- `client_secret`: The secret for the OAuth client _[!note] Only used when `grant_type` is `client_credentials`_ +- `username`: The username for the OAuth client _[!note] Only used when `grant_type` is `password`_ +- `password`: The password for the OAuth client _[!note] Only used when `grant_type` is `client_credentials`_ +- +This results in the following example: +```json +{ + "grant_type": "client_credentials", + "scope": "api", + "authentication": "body", + "tokenUrl": "https://example.com/oauth/token", + "client_id": "test-client", + "client_secret": "some secret value" +} +``` +### Custom parameters + +> [!warning] Custom parameters are currently in beta, it is not recommended to use them in production environments. + +At the moment, OpenConnector is tested with the following custom parameters: + +- `client_assertion_type`, only meaningful at the moment when value is set to `urn:ietf:params:oauth:client-assertion-type:jwt-bearer`. When this is set (for Microsoft authentications) the following fields are needed to generate the `client-assertion`-field +- - `private_key`: The base64 encoded private key of the certificate uploaded to Microsoft. +- - `x5t`: The base64 encoded sha1 fingerprint of the uploaded certificate, generated by running the following command: +```bash +echo $(openssl x509 -in certificate.crt -fingerprint -noout) | sed 's/SHA1 Fingerprint=//g' | sed 's/://g' | xxd -r -ps | base64`) +``` +- - `payload`: The payload of the JWT generated as `client_assertion`, this can contain Twig variables to render, for example to set timestamps in the JWT payload. + +## JWT Bearer + +A second supported way of using dynamic authentication is setting a JWT Bearer. This means setting a header or query parameter with a JWT token. + +This can for example be used by setting an Authorization header with the following value: +```twig +Bearer {{ jwtToken(source) }} +``` + +This will impose a JWT token after the bearer. For this, the `authenticationConfig` field of the source needs to contain the following fields: +- `algorithm`: The algorithm that should be used to generate the JWT. Supported are `HS256`, `HS384` and `HS512` for HMAC algorithms, `RS256`, `RS384`, `RS512` and `PS256` for RSA algorithms. +- `secret`: The secret used for the JWT. This can either be a HMAC shared secret, or a RSA private key in base64 encoding. +- `payload`: The payload of your JWT, json_encoded. + +This results in the following example for the `authenticationConfig` parameter in i.e. an OpenZaak source. +```json +{ + "algorithm": "HS256", + "secret": "YOUR_256BIT_(32BYTE)_HMAC_SECRET", + "payload": "{\"iss\":\"my_zgw_client\",\"iat\":{{ 'now'|date('U') }},\"client_id\":\"my_zgw_client\",\"user_id\":\"my_zgw_client\",\"user_representation\":\"me@company.com\",\"aud\":\"my_zgw_client\"}" +} +``` From 07673c412610c5ecfb06d3d4130f08f8fd7d973a Mon Sep 17 00:00:00 2001 From: Robert Zondervan Date: Wed, 6 Nov 2024 16:39:46 +0100 Subject: [PATCH 02/46] MD fix --- docs/authentication.md | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/docs/authentication.md b/docs/authentication.md index 0f0a4ea..243ada2 100644 --- a/docs/authentication.md +++ b/docs/authentication.md @@ -22,15 +22,15 @@ OpenConnector supports the OAuth 2.0 protocol with client credentials and passwo When using OAuth, OpenConnector supports the following parameters: ### Standard parameters -- `grant_type`: The type of grant we have to use at the source. Supported are `client_credentials` and `password` -- `scope`: The scope(s) needed to perform the requests we want to do in the API. -- `tokenUrl`: The URL used to fetch the actual access token. Usually this url can be recognised by its path ending on `/oauth/token` -- `authentication`: Location of the credentials, either `body` for credentials included in the request body, or `basic_auth` when the credentials have to be sent as a basic_auth header. _[!warning] Only used when `grant_type` is `client_credentials`_ -- `client_id`: The client id of the OAuth client _[!note] Only used when `grant_type` is `client_credentials`_ -- `client_secret`: The secret for the OAuth client _[!note] Only used when `grant_type` is `client_credentials`_ -- `username`: The username for the OAuth client _[!note] Only used when `grant_type` is `password`_ -- `password`: The password for the OAuth client _[!note] Only used when `grant_type` is `client_credentials`_ -- +* `grant_type`: The type of grant we have to use at the source. Supported are `client_credentials` and `password` +* `scope`: The scope(s) needed to perform the requests we want to do in the API. +* `tokenUrl`: The URL used to fetch the actual access token. Usually this url can be recognised by its path ending on `/oauth/token` +* `authentication`: Location of the credentials, either `body` for credentials included in the request body, or `basic_auth` when the credentials have to be sent as a basic_auth header. _[!warning] Only used when `grant_type` is `client_credentials`_ +* `client_id`: The client id of the OAuth client _[!note] Only used when `grant_type` is `client_credentials`_ +* `client_secret`: The secret for the OAuth client _[!note] Only used when `grant_type` is `client_credentials`_ +* `username`: The username for the OAuth client _[!note] Only used when `grant_type` is `password`_ +* `password`: The password for the OAuth client _[!note] Only used when `grant_type` is `client_credentials`_ + This results in the following example: ```json { @@ -48,13 +48,15 @@ This results in the following example: At the moment, OpenConnector is tested with the following custom parameters: -- `client_assertion_type`, only meaningful at the moment when value is set to `urn:ietf:params:oauth:client-assertion-type:jwt-bearer`. When this is set (for Microsoft authentications) the following fields are needed to generate the `client-assertion`-field -- - `private_key`: The base64 encoded private key of the certificate uploaded to Microsoft. -- - `x5t`: The base64 encoded sha1 fingerprint of the uploaded certificate, generated by running the following command: -```bash -echo $(openssl x509 -in certificate.crt -fingerprint -noout) | sed 's/SHA1 Fingerprint=//g' | sed 's/://g' | xxd -r -ps | base64`) -``` -- - `payload`: The payload of the JWT generated as `client_assertion`, this can contain Twig variables to render, for example to set timestamps in the JWT payload. +* `client_assertion_type`, only meaningful at the moment when value is set to `urn:ietf:params:oauth:client-assertion-type:jwt-bearer`. When this is set (for Microsoft authentications) the following fields are needed to generate the `client-assertion`-field + - `private_key`: The base64 encoded private key of the certificate uploaded to Microsoft. + - `x5t`: The base64 encoded sha1 fingerprint of the uploaded certificate, generated by running the following command: + + ```bash + echo $(openssl x509 -in certificate.crt -fingerprint -noout) | sed 's/SHA1 Fingerprint=//g' | sed 's/://g' | xxd -r -ps | base64`) + ``` + + - `payload`: The payload of the JWT generated as `client_assertion`, this can contain Twig variables to render, for example to set timestamps in the JWT payload. ## JWT Bearer @@ -66,9 +68,9 @@ Bearer {{ jwtToken(source) }} ``` This will impose a JWT token after the bearer. For this, the `authenticationConfig` field of the source needs to contain the following fields: -- `algorithm`: The algorithm that should be used to generate the JWT. Supported are `HS256`, `HS384` and `HS512` for HMAC algorithms, `RS256`, `RS384`, `RS512` and `PS256` for RSA algorithms. -- `secret`: The secret used for the JWT. This can either be a HMAC shared secret, or a RSA private key in base64 encoding. -- `payload`: The payload of your JWT, json_encoded. +* `algorithm`: The algorithm that should be used to generate the JWT. Supported are `HS256`, `HS384` and `HS512` for HMAC algorithms, `RS256`, `RS384`, `RS512` and `PS256` for RSA algorithms. +* `secret`: The secret used for the JWT. This can either be a HMAC shared secret, or a RSA private key in base64 encoding. +* `payload`: The payload of your JWT, json_encoded. This results in the following example for the `authenticationConfig` parameter in i.e. an OpenZaak source. ```json From 3109c2ab8bc4e6f000cf26dab9fbe493bd965643 Mon Sep 17 00:00:00 2001 From: Robert Zondervan Date: Wed, 6 Nov 2024 16:40:46 +0100 Subject: [PATCH 03/46] Fix MD warnings and notes --- docs/authentication.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/authentication.md b/docs/authentication.md index 243ada2..e1d0639 100644 --- a/docs/authentication.md +++ b/docs/authentication.md @@ -26,10 +26,10 @@ When using OAuth, OpenConnector supports the following parameters: * `scope`: The scope(s) needed to perform the requests we want to do in the API. * `tokenUrl`: The URL used to fetch the actual access token. Usually this url can be recognised by its path ending on `/oauth/token` * `authentication`: Location of the credentials, either `body` for credentials included in the request body, or `basic_auth` when the credentials have to be sent as a basic_auth header. _[!warning] Only used when `grant_type` is `client_credentials`_ -* `client_id`: The client id of the OAuth client _[!note] Only used when `grant_type` is `client_credentials`_ -* `client_secret`: The secret for the OAuth client _[!note] Only used when `grant_type` is `client_credentials`_ -* `username`: The username for the OAuth client _[!note] Only used when `grant_type` is `password`_ -* `password`: The password for the OAuth client _[!note] Only used when `grant_type` is `client_credentials`_ +* `client_id`: The client id of the OAuth client _[!NOTE] Only used when `grant_type` is `client_credentials`_ +* `client_secret`: The secret for the OAuth client _[!NOTE] Only used when `grant_type` is `client_credentials`_ +* `username`: The username for the OAuth client _[!NOTE] Only used when `grant_type` is `password`_ +* `password`: The password for the OAuth client _[!NOTE] Only used when `grant_type` is `client_credentials`_ This results in the following example: ```json @@ -44,7 +44,7 @@ This results in the following example: ``` ### Custom parameters -> [!warning] Custom parameters are currently in beta, it is not recommended to use them in production environments. +> [!WARNING] Custom parameters are currently in beta, it is not recommended to use them in production environments. At the moment, OpenConnector is tested with the following custom parameters: From c46bc7f9fd2ee8001f9d3c7554f54ef2a94bd9bb Mon Sep 17 00:00:00 2001 From: Robert Zondervan Date: Wed, 6 Nov 2024 16:43:49 +0100 Subject: [PATCH 04/46] Some more MD changes --- docs/authentication.md | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/docs/authentication.md b/docs/authentication.md index e1d0639..be0a088 100644 --- a/docs/authentication.md +++ b/docs/authentication.md @@ -26,10 +26,18 @@ When using OAuth, OpenConnector supports the following parameters: * `scope`: The scope(s) needed to perform the requests we want to do in the API. * `tokenUrl`: The URL used to fetch the actual access token. Usually this url can be recognised by its path ending on `/oauth/token` * `authentication`: Location of the credentials, either `body` for credentials included in the request body, or `basic_auth` when the credentials have to be sent as a basic_auth header. _[!warning] Only used when `grant_type` is `client_credentials`_ -* `client_id`: The client id of the OAuth client _[!NOTE] Only used when `grant_type` is `client_credentials`_ -* `client_secret`: The secret for the OAuth client _[!NOTE] Only used when `grant_type` is `client_credentials`_ -* `username`: The username for the OAuth client _[!NOTE] Only used when `grant_type` is `password`_ -* `password`: The password for the OAuth client _[!NOTE] Only used when `grant_type` is `client_credentials`_ +* `client_id`: The client id of the OAuth client + > [!NOTE] + > Only used when `grant_type` is `client_credentials` +* `client_secret`: The secret for the OAuth client + > [!NOTE] + > Only used when `grant_type` is `client_credentials` +* `username`: The username for the OAuth client + > [!NOTE] + > Only used when `grant_type` is `password` +* `password`: The password for the OAuth client + > [!NOTE] + > Only used when `grant_type` is `client_credentials` This results in the following example: ```json @@ -44,7 +52,8 @@ This results in the following example: ``` ### Custom parameters -> [!WARNING] Custom parameters are currently in beta, it is not recommended to use them in production environments. +> [!WARNING] +> Custom parameters are currently in beta, it is not recommended to use them in production environments. At the moment, OpenConnector is tested with the following custom parameters: From 7080c7ef3dbe9e73ed30de662082bdf852a7b409 Mon Sep 17 00:00:00 2001 From: Robert Zondervan Date: Wed, 6 Nov 2024 16:47:19 +0100 Subject: [PATCH 05/46] Remove notes, correct one of the notes --- docs/authentication.md | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/docs/authentication.md b/docs/authentication.md index be0a088..d3bb763 100644 --- a/docs/authentication.md +++ b/docs/authentication.md @@ -25,19 +25,16 @@ When using OAuth, OpenConnector supports the following parameters: * `grant_type`: The type of grant we have to use at the source. Supported are `client_credentials` and `password` * `scope`: The scope(s) needed to perform the requests we want to do in the API. * `tokenUrl`: The URL used to fetch the actual access token. Usually this url can be recognised by its path ending on `/oauth/token` -* `authentication`: Location of the credentials, either `body` for credentials included in the request body, or `basic_auth` when the credentials have to be sent as a basic_auth header. _[!warning] Only used when `grant_type` is `client_credentials`_ -* `client_id`: The client id of the OAuth client - > [!NOTE] +* `authentication`: Location of the credentials, either `body` for credentials included in the request body, or `basic_auth` when the credentials have to be sent as a basic_auth header. + > Only used when `grant_type` is `client_credentials` +* `client_id`: The client id of the OAuth client > Only used when `grant_type` is `client_credentials` * `client_secret`: The secret for the OAuth client - > [!NOTE] > Only used when `grant_type` is `client_credentials` * `username`: The username for the OAuth client - > [!NOTE] > Only used when `grant_type` is `password` * `password`: The password for the OAuth client - > [!NOTE] - > Only used when `grant_type` is `client_credentials` + > Only used when `grant_type` is `password` This results in the following example: ```json From 5e34af373578948beb9dd9400377aa9c440e7535 Mon Sep 17 00:00:00 2001 From: Ruben van der Linde Date: Mon, 11 Nov 2024 23:47:18 +0100 Subject: [PATCH 06/46] Calls for finishing the mapping tester --- appinfo/routes.php | 2 ++ lib/Controller/MappingsController.php | 36 +++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/appinfo/routes.php b/appinfo/routes.php index 27548e5..a0e8b97 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -22,6 +22,8 @@ ['name' => 'synchronizations#test', 'url' => '/api/synchronizations-test/{id}', 'verb' => 'POST'], // Mapping endpoints ['name' => 'mappings#test', 'url' => '/api/mappings/test', 'verb' => 'POST'], + ['name' => 'mappings#objectsSave', 'url' => '/api/mappings/objects', 'verb' => 'POST'], + ['name' => 'mappings#objectsGet', 'url' => '/api/mappings/objects', 'verb' => 'GET'], // Running endpoints ['name' => 'endpoints#run', 'url' => '/api/v1/{endpoint}', 'verb' => 'GET'], ['name' => 'endpoints#run', 'url' => '/api/v1/{endpoint}', 'verb' => 'PUT'], diff --git a/lib/Controller/MappingsController.php b/lib/Controller/MappingsController.php index f3ab903..03394a8 100644 --- a/lib/Controller/MappingsController.php +++ b/lib/Controller/MappingsController.php @@ -291,4 +291,40 @@ public function test(ObjectService $objectService, IURLGenerator $urlGenerator): 'validationErrors' => $validationErrors ]); } + + /** + * Saves a mapping object + * + * This method saves a mapping object based on POST data. + */ + public function objectsSave(): JSONResponse + { + // Check if the OpenRegister service is available + $openRegisters = $this->objectService->getOpenRegisters(); + if ($openRegisters !== null) { + return new JSONResponse($openRegisters->saveObject($this->request->getParams())); + } + } + + /** + * Retrieves a list of objects to map to + * + * This method retrieves a list of objects to map to based on GET data. + */ + public function objectsGet(): JSONResponse + { + // Check if the OpenRegister service is available + $openRegisters = $this->objectService->getOpenRegisters(); + $data = []; + if ($openRegisters !== null) { + $data['openRegisters'] = true; + $data['availableRegisters'] = $openRegisters->getRegisters(); + } + else { + $data['openRegisters'] = false; + } + + return new JSONResponse($data); + + } } From 6fc18c6687b57e7904d6f6a39b9a18a4ff6aff30 Mon Sep 17 00:00:00 2001 From: Thijn Date: Tue, 12 Nov 2024 11:27:37 +0100 Subject: [PATCH 07/46] fixed mapping objects get --- lib/Controller/MappingsController.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/Controller/MappingsController.php b/lib/Controller/MappingsController.php index 03394a8..6fea9d9 100644 --- a/lib/Controller/MappingsController.php +++ b/lib/Controller/MappingsController.php @@ -31,7 +31,8 @@ public function __construct( IRequest $request, private readonly IAppConfig $config, private readonly MappingMapper $mappingMapper, - private readonly MappingService $mappingService + private readonly MappingService $mappingService, + private readonly ObjectService $objectService ) { parent::__construct($appName, $request); @@ -310,6 +311,9 @@ public function objectsSave(): JSONResponse * Retrieves a list of objects to map to * * This method retrieves a list of objects to map to based on GET data. + * + * @NoAdminRequired + * @NoCSRFRequired */ public function objectsGet(): JSONResponse { From a3f3075e8983dc4df47bdcda3548c87465c4a2b2 Mon Sep 17 00:00:00 2001 From: Thijn Date: Tue, 12 Nov 2024 14:12:36 +0100 Subject: [PATCH 08/46] fixed saving objects --- lib/Controller/MappingsController.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/Controller/MappingsController.php b/lib/Controller/MappingsController.php index 6fea9d9..a420a77 100644 --- a/lib/Controller/MappingsController.php +++ b/lib/Controller/MappingsController.php @@ -297,13 +297,17 @@ public function test(ObjectService $objectService, IURLGenerator $urlGenerator): * Saves a mapping object * * This method saves a mapping object based on POST data. + * + * @NoAdminRequired + * @NoCSRFRequired */ public function objectsSave(): JSONResponse { // Check if the OpenRegister service is available $openRegisters = $this->objectService->getOpenRegisters(); if ($openRegisters !== null) { - return new JSONResponse($openRegisters->saveObject($this->request->getParams())); + $data = $this->request->getParams(); + return new JSONResponse($openRegisters->saveObject($data['register'], $data['schema'], $data['object'])); } } @@ -311,7 +315,7 @@ public function objectsSave(): JSONResponse * Retrieves a list of objects to map to * * This method retrieves a list of objects to map to based on GET data. - * + * * @NoAdminRequired * @NoCSRFRequired */ From 30ea9db72c76cdcc6200bedbfeaf3a9fea236021 Mon Sep 17 00:00:00 2001 From: Thijn Date: Tue, 12 Nov 2024 14:15:05 +0100 Subject: [PATCH 09/46] finished frontend saving objects --- src/modals/MappingTest/TestMapping.vue | 5 +- .../components/TestMappingResult.vue | 159 +++++++++++++++++- src/store/modules/mapping.js | 58 +++++++ 3 files changed, 219 insertions(+), 3 deletions(-) diff --git a/src/modals/MappingTest/TestMapping.vue b/src/modals/MappingTest/TestMapping.vue index a3e4fcb..6df11e7 100644 --- a/src/modals/MappingTest/TestMapping.vue +++ b/src/modals/MappingTest/TestMapping.vue @@ -19,7 +19,8 @@ import { navigationStore } from '../../store/store.js' @mapping-selected="receiveMappingSelected" @mapping-test="receiveMappingTest" /> + :mapping-test="mappingTest" + :schema="schema" /> @@ -82,7 +83,7 @@ export default { value.error !== undefined && (this.mappingTest.error = value.error) // boolean / string }, receiveSchemaSelected(value) { - value.selected && (this.schema.selected = value.selected) + value?.selected !== undefined && (this.schema.selected = value.selected) value.schemas && (this.schema.schemas = value.schemas) value.success !== undefined && (this.schema.success = value.success) // boolean value.loading !== undefined && (this.schema.loading = value.loading) // boolean diff --git a/src/modals/MappingTest/components/TestMappingResult.vue b/src/modals/MappingTest/components/TestMappingResult.vue index be06719..5c4b302 100644 --- a/src/modals/MappingTest/components/TestMappingResult.vue +++ b/src/modals/MappingTest/components/TestMappingResult.vue @@ -1,3 +1,7 @@ + + @@ -58,21 +116,37 @@ import { NcNoteCard, NcIconSvgWrapper, + NcSelect, + NcButton, + NcLoadingIcon, } from '@nextcloud/vue' import { mdiCheckCircle, mdiCloseCircle } from '@mdi/js' +import DatabaseOutline from 'vue-material-design-icons/DatabaseOutline.vue' +import ContentSaveOutline from 'vue-material-design-icons/ContentSaveOutline.vue' + export default { name: 'TestMappingResult', components: { NcNoteCard, NcIconSvgWrapper, + NcSelect, + NcButton, + NcLoadingIcon, + // icons + DatabaseOutline, + ContentSaveOutline, }, props: { mappingTest: { type: Object, required: true, }, + schema: { + type: Object, + required: true, + }, }, setup() { return { @@ -82,9 +156,74 @@ export default { }, data() { return { - // data here + openRegisterInstalled: false, + fetchRegistersLoading: false, + rawRegisters: [], + registers: { + options: [], + value: null, + }, + saveObjectLoading: false, + saveObjectSuccess: null, + saveObjectError: '', } }, + mounted() { + this.fetchRegisters() + }, + methods: { + fetchRegisters() { + this.fetchRegistersLoading = true + + mappingStore.getMappingObjects() + .then(({ response, data }) => { + this.openRegisterInstalled = data.openRegisters + if (!data.openRegisters) return // if open register is not installed, we don't need the rest of this code + + this.rawRegisters = data.availableRegisters + + this.registers.options = data.availableRegisters.map((register) => ({ + id: register.id, + label: register.title, + fullRegister: register, + })) + }) + .catch((error) => { + console.error(error) + }) + .finally(() => { + this.fetchRegistersLoading = false + }) + }, + saveObject() { + this.saveObjectLoading = true + this.saveObjectSuccess = null + this.saveObjectError = '' + + mappingStore.saveMappingObject({ + object: this.mappingTest.result.resultObject, + register: this.registers.value.id, + schema: this.schema.selected.id, + }) + .then(({ response }) => { + this.saveObjectSuccess = response.ok + }) + .catch((error) => { + console.error(error) + this.saveObjectSuccess = false + this.saveObjectError = error + }) + .finally(() => { + this.saveObjectLoading = false + + // cleanup after 3 seconds + setTimeout(() => { + this.saveObjectSuccess = null + this.saveObjectError = '' + }, 3000) + }) + }, + }, } @@ -125,4 +264,22 @@ export default { border: 1px solid grey; padding: 8px; } + +.v-select { + min-width: auto; + width: 100%; +} + +/* custom select option */ +.custom-select-option { + display: flex; + align-items: center; + gap: 10px; +} +.custom-select-option > .material-design-icon { + margin-block-start: 2px; +} +.custom-select-option > h6 { + line-height: 0.8; +} diff --git a/src/store/modules/mapping.js b/src/store/modules/mapping.js index 18c11a4..e3358b7 100644 --- a/src/store/modules/mapping.js +++ b/src/store/modules/mapping.js @@ -178,5 +178,63 @@ export const useMappingStore = defineStore('mapping', { return { response, data } }, + /** + * Get objects on a mapping from the endpoint. + * + * This method fetches objects related to a mapping from the specified API endpoint. + * + * @throws Will throw an error if the fetch operation fails. + * @return { Promise<{ response: Response, data: object }> } The response and data from the API. + */ + async getMappingObjects() { + console.log('Fetching mapping objects...') + + // Fetch objects related to a mapping from the API endpoint + const response = await fetch( + '/index.php/apps/openconnector/api/mappings/objects', + { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + }, + ) + + // Parse the response data as JSON + const data = await response.json() + + // Return the response and parsed data + return { response, data } + }, + /** + * Save a mapping object to the endpoint. + * + * This method sends a mapping object to the specified API endpoint to be saved. + * + * @param { object } mappingObject - The mapping object to be saved. + * @return { Promise<{ response: Response, data: object }> } The response and data from the API. + * @throws Will throw an error if the save operation fails. + */ + async saveMappingObject(mappingObject) { + console.log('Saving mapping object...') + + // Send the mapping object to the API endpoint to be saved + const response = await fetch( + '/index.php/apps/openconnector/api/mappings/objects', + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(mappingObject), + }, + ) + + // Parse the response data as JSON + const data = await response.json() + + // Return the response and parsed data + return { response, data } + }, }, }) From 1df05b5a544de36a36550954edc3060773e1500e Mon Sep 17 00:00:00 2001 From: Thijn Date: Tue, 12 Nov 2024 14:32:46 +0100 Subject: [PATCH 10/46] changed function names --- appinfo/routes.php | 4 ++-- lib/Controller/MappingsController.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/appinfo/routes.php b/appinfo/routes.php index a0e8b97..d9de797 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -22,8 +22,8 @@ ['name' => 'synchronizations#test', 'url' => '/api/synchronizations-test/{id}', 'verb' => 'POST'], // Mapping endpoints ['name' => 'mappings#test', 'url' => '/api/mappings/test', 'verb' => 'POST'], - ['name' => 'mappings#objectsSave', 'url' => '/api/mappings/objects', 'verb' => 'POST'], - ['name' => 'mappings#objectsGet', 'url' => '/api/mappings/objects', 'verb' => 'GET'], + ['name' => 'mappings#saveObjects', 'url' => '/api/mappings/objects', 'verb' => 'POST'], + ['name' => 'mappings#getObjects', 'url' => '/api/mappings/objects', 'verb' => 'GET'], // Running endpoints ['name' => 'endpoints#run', 'url' => '/api/v1/{endpoint}', 'verb' => 'GET'], ['name' => 'endpoints#run', 'url' => '/api/v1/{endpoint}', 'verb' => 'PUT'], diff --git a/lib/Controller/MappingsController.php b/lib/Controller/MappingsController.php index a420a77..c3c512e 100644 --- a/lib/Controller/MappingsController.php +++ b/lib/Controller/MappingsController.php @@ -301,7 +301,7 @@ public function test(ObjectService $objectService, IURLGenerator $urlGenerator): * @NoAdminRequired * @NoCSRFRequired */ - public function objectsSave(): JSONResponse + public function saveObjects(): JSONResponse { // Check if the OpenRegister service is available $openRegisters = $this->objectService->getOpenRegisters(); @@ -319,7 +319,7 @@ public function objectsSave(): JSONResponse * @NoAdminRequired * @NoCSRFRequired */ - public function objectsGet(): JSONResponse + public function getObjects(): JSONResponse { // Check if the OpenRegister service is available $openRegisters = $this->objectService->getOpenRegisters(); From be0ea081fae197fbc852e652e671ce3e4570ba80 Mon Sep 17 00:00:00 2001 From: Thijn Date: Tue, 12 Nov 2024 14:40:00 +0100 Subject: [PATCH 11/46] removed a S after save objects --- appinfo/routes.php | 2 +- lib/Controller/MappingsController.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/appinfo/routes.php b/appinfo/routes.php index d9de797..f96805d 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -22,7 +22,7 @@ ['name' => 'synchronizations#test', 'url' => '/api/synchronizations-test/{id}', 'verb' => 'POST'], // Mapping endpoints ['name' => 'mappings#test', 'url' => '/api/mappings/test', 'verb' => 'POST'], - ['name' => 'mappings#saveObjects', 'url' => '/api/mappings/objects', 'verb' => 'POST'], + ['name' => 'mappings#saveObject', 'url' => '/api/mappings/objects', 'verb' => 'POST'], ['name' => 'mappings#getObjects', 'url' => '/api/mappings/objects', 'verb' => 'GET'], // Running endpoints ['name' => 'endpoints#run', 'url' => '/api/v1/{endpoint}', 'verb' => 'GET'], diff --git a/lib/Controller/MappingsController.php b/lib/Controller/MappingsController.php index c3c512e..bc48a2b 100644 --- a/lib/Controller/MappingsController.php +++ b/lib/Controller/MappingsController.php @@ -301,7 +301,7 @@ public function test(ObjectService $objectService, IURLGenerator $urlGenerator): * @NoAdminRequired * @NoCSRFRequired */ - public function saveObjects(): JSONResponse + public function saveObject(): JSONResponse { // Check if the OpenRegister service is available $openRegisters = $this->objectService->getOpenRegisters(); From 8bb3786aa4d9a8a557f2361edc2d021a00cecf5c Mon Sep 17 00:00:00 2001 From: Thijn Date: Tue, 12 Nov 2024 16:23:27 +0100 Subject: [PATCH 12/46] lint fix --- src/components/CreateEndpointDialog.vue | 1 - src/components/CreateWebhookDialog.vue | 1 - src/components/EditEndpointDialog.vue | 1 - src/components/EditWebhookDialog.vue | 1 - src/entities/callLog/index.js | 1 - src/entities/endpoint/index.js | 1 - src/entities/index.js | 2 +- src/entities/jobLog/index.js | 1 - src/modals/Synchronization/EditSynchronization.vue | 6 +++--- src/navigation/MainMenu.vue | 8 +++++++- 10 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/components/CreateEndpointDialog.vue b/src/components/CreateEndpointDialog.vue index 0519ecb..e69de29 100644 --- a/src/components/CreateEndpointDialog.vue +++ b/src/components/CreateEndpointDialog.vue @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/components/CreateWebhookDialog.vue b/src/components/CreateWebhookDialog.vue index 0519ecb..e69de29 100644 --- a/src/components/CreateWebhookDialog.vue +++ b/src/components/CreateWebhookDialog.vue @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/components/EditEndpointDialog.vue b/src/components/EditEndpointDialog.vue index 0519ecb..e69de29 100644 --- a/src/components/EditEndpointDialog.vue +++ b/src/components/EditEndpointDialog.vue @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/components/EditWebhookDialog.vue b/src/components/EditWebhookDialog.vue index 0519ecb..e69de29 100644 --- a/src/components/EditWebhookDialog.vue +++ b/src/components/EditWebhookDialog.vue @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/entities/callLog/index.js b/src/entities/callLog/index.js index 7b97bc1..ec8b447 100644 --- a/src/entities/callLog/index.js +++ b/src/entities/callLog/index.js @@ -1,4 +1,3 @@ export * from './callLog.ts' export * from './callLog.types.ts' export * from './callLog.mock.ts' - diff --git a/src/entities/endpoint/index.js b/src/entities/endpoint/index.js index d9efff0..5689c47 100644 --- a/src/entities/endpoint/index.js +++ b/src/entities/endpoint/index.js @@ -1,4 +1,3 @@ export * from './endpoint.ts' export * from './endpoint.types.ts' export * from './endpoint.mock.ts' - diff --git a/src/entities/index.js b/src/entities/index.js index 9e9bf6e..99d426c 100644 --- a/src/entities/index.js +++ b/src/entities/index.js @@ -8,4 +8,4 @@ export * from './webhook/index.js' export * from './mapping/index.js' export * from './synchronization/index.js' export * from './source/index.js' -export * from './callLog/index.js' +export * from './callLog/index.js' diff --git a/src/entities/jobLog/index.js b/src/entities/jobLog/index.js index df9f468..2596894 100644 --- a/src/entities/jobLog/index.js +++ b/src/entities/jobLog/index.js @@ -1,4 +1,3 @@ export * from './jobLog.types.ts' export * from './jobLog.types.ts' export * from './jobLog.mock.ts' - diff --git a/src/modals/Synchronization/EditSynchronization.vue b/src/modals/Synchronization/EditSynchronization.vue index bf1aa3e..3c28da6 100644 --- a/src/modals/Synchronization/EditSynchronization.vue +++ b/src/modals/Synchronization/EditSynchronization.vue @@ -1,5 +1,5 @@ - + @@ -39,6 +43,8 @@ import { navigationStore } from '../store/store.js' + +