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 @@
@@ -25,8 +25,8 @@ import { synchronizationStore, navigationStore, sourceStore } from '../../store/
-
+
diff --git a/src/navigation/MainMenu.vue b/src/navigation/MainMenu.vue
index d2c0957..51cfb59 100644
--- a/src/navigation/MainMenu.vue
+++ b/src/navigation/MainMenu.vue
@@ -30,7 +30,11 @@ import { navigationStore } from '../store/store.js'
-
+
@@ -39,6 +43,8 @@ import { navigationStore } from '../store/store.js'
+
+
From c8d76863cecf71026d8f2f8e3109cc4fa333f197 Mon Sep 17 00:00:00 2001
From: Thijn
Date: Tue, 12 Nov 2024 16:48:48 +0100
Subject: [PATCH 13/46] added a clear timeout when closing modal
---
src/modals/JobArgument/DeleteJobArgument.vue | 8 ++------
src/modals/mappingCast/DeleteMappingCast.vue | 14 ++++++++------
src/modals/mappingCast/EditMappingCast.vue | 6 +++---
3 files changed, 13 insertions(+), 15 deletions(-)
diff --git a/src/modals/JobArgument/DeleteJobArgument.vue b/src/modals/JobArgument/DeleteJobArgument.vue
index 75b779f..b41001e 100644
--- a/src/modals/JobArgument/DeleteJobArgument.vue
+++ b/src/modals/JobArgument/DeleteJobArgument.vue
@@ -22,7 +22,7 @@ import { navigationStore, jobStore } from '../../store/store.js'
Do you want to delete {{ jobStore.jobArgumentKey }}? This action cannot be undone.
-
+
@@ -94,11 +94,7 @@ export default {
this.success = true
// Wait for the user to read the feedback then close the model
- const self = this
- this.closeTimeoutFunc = setTimeout(function() {
- self.success = null
- navigationStore.setModal(false)
- }, 2000)
+ this.closeTimeoutFunc = setTimeout(this.closeModal, 2000)
})
.catch((err) => {
this.error = err
diff --git a/src/modals/mappingCast/DeleteMappingCast.vue b/src/modals/mappingCast/DeleteMappingCast.vue
index adb12eb..12c4c61 100644
--- a/src/modals/mappingCast/DeleteMappingCast.vue
+++ b/src/modals/mappingCast/DeleteMappingCast.vue
@@ -22,7 +22,7 @@ import { navigationStore, mappingStore } from '../../store/store.js'
Do you want to delete {{ mappingStore.mappingCastKey }}? This action cannot be undone.
-
+
@@ -66,9 +66,15 @@ export default {
loading: false,
success: null,
error: false,
+ closeTimeoutFunc: null,
}
},
methods: {
+ closeModal() {
+ navigationStore.setModal(false)
+ clearTimeout(this.closeTimeoutFunc)
+ this.success = null
+ },
deleteMappingCast() {
this.loading = true
@@ -85,11 +91,7 @@ export default {
this.success = true
// Wait for the user to read the feedback then close the model
- const self = this
- setTimeout(function() {
- self.success = null
- navigationStore.setModal(false)
- }, 2000)
+ this.closeTimeoutFunc = setTimeout(this.closeModal, 2000)
})
.catch((err) => {
this.error = err
diff --git a/src/modals/mappingCast/EditMappingCast.vue b/src/modals/mappingCast/EditMappingCast.vue
index 190a823..8481236 100644
--- a/src/modals/mappingCast/EditMappingCast.vue
+++ b/src/modals/mappingCast/EditMappingCast.vue
@@ -80,6 +80,7 @@ export default {
hasUpdated: false,
oldKey: '',
isEdit: false,
+ closeTimeoutFunc: null,
}
},
mounted() {
@@ -115,6 +116,7 @@ export default {
},
closeModal() {
navigationStore.setModal(false)
+ clearTimeout(this.closeTimeoutFunc)
this.success = false
this.loading = false
this.error = false
@@ -146,9 +148,7 @@ export default {
// Close modal or show success message
this.success = true
this.loading = false
- setTimeout(() => {
- this.closeModal()
- }, 2000)
+ this.closeTimeoutFunc = setTimeout(this.closeModal, 2000)
} catch (error) {
this.loading = false
this.success = false
From c356d5659e86360bce216a8ad36a1c7b2217e257 Mon Sep 17 00:00:00 2001
From: Thijn
Date: Wed, 13 Nov 2024 10:57:36 +0100
Subject: [PATCH 14/46] fixed console error when deleting endpoint
---
src/modals/Endpoint/DeleteEndpoint.vue | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/modals/Endpoint/DeleteEndpoint.vue b/src/modals/Endpoint/DeleteEndpoint.vue
index 130e212..77691a5 100644
--- a/src/modals/Endpoint/DeleteEndpoint.vue
+++ b/src/modals/Endpoint/DeleteEndpoint.vue
@@ -8,7 +8,7 @@ import { endpointStore, navigationStore } from '../../store/store.js'
size="normal"
:can-close="false">
- Do you want to delete {{ endpointStore.endpointItem.name }}? This action cannot be undone.
+ Do you want to delete {{ endpointStore.endpointItem?.name }}? This action cannot be undone.
The connection to the synchronization was successful.
-
-
An error occurred while testing the connection: {{ synchronizationStore.synchronizationTest ? synchronizationStore.synchronizationTest.response.statusMessage : error }}
Date: Fri, 15 Nov 2024 16:09:26 +0100
Subject: [PATCH 25/46] fixed jobs next/last run view
---
src/services/getValidISOstring.js | 2 ++
src/views/Job/JobDetails.vue | 6 ++++--
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/src/services/getValidISOstring.js b/src/services/getValidISOstring.js
index 34e937a..231912e 100644
--- a/src/services/getValidISOstring.js
+++ b/src/services/getValidISOstring.js
@@ -1,6 +1,8 @@
/**
* Converts a given date string or Date object to a valid ISO string.
*
+ * this function can double as a validator for ISO / date strings
+ *
* If the dateString is valid it will return the ISO string,
* if it is not a valid dateString it will return null.
*
diff --git a/src/views/Job/JobDetails.vue b/src/views/Job/JobDetails.vue
index be8e8dc..8797f68 100644
--- a/src/views/Job/JobDetails.vue
+++ b/src/views/Job/JobDetails.vue
@@ -90,13 +90,13 @@ import { jobStore, navigationStore, logStore } from '../../store/store.js'
Next Run:
- {{ new Date(jobStore.jobItem.nextRun).toLocaleString() || 'N/A' }}
+ {{ getValidISOstring(jobStore.jobItem.nextRun) ? new Date(jobStore.jobItem.nextRun).toLocaleString() : 'N/A' }}
Last Run:
- {{ new Date(jobStore.jobItem.lastRun).toLocaleString() || 'N/A' }}
+ {{ getValidISOstring(jobStore.jobItem.lastRun) ? new Date(jobStore.jobItem.lastRun).toLocaleString() : 'N/A' }}
+ {{ openRegisterIsAvailable
+ ? 'Some features require Open Register to be installed'
+ : 'This either means that Open Register is not available on this server or you need to confirm your password' }}
+