From 77747f8455fdc135abdd79ca2cd16349dea581f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Ovejero?= Date: Wed, 4 May 2022 14:59:06 +0200 Subject: [PATCH 1/4] :zap: Set up request --- packages/editor-ui/src/Interface.ts | 1 + packages/editor-ui/src/components/mixins/restApi.ts | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/packages/editor-ui/src/Interface.ts b/packages/editor-ui/src/Interface.ts index 10457c8c41..b0b7ef2e79 100644 --- a/packages/editor-ui/src/Interface.ts +++ b/packages/editor-ui/src/Interface.ts @@ -184,6 +184,7 @@ export interface IRestApi { retryExecution(id: string, loadWorkflow?: boolean): Promise; getTimezones(): Promise; getBinaryBufferString(dataPath: string): Promise; + getScopes: (credentialType: string) => Promise; } export interface INodeTranslationHeaders { diff --git a/packages/editor-ui/src/components/mixins/restApi.ts b/packages/editor-ui/src/components/mixins/restApi.ts index 7dad40044f..72e22cad09 100644 --- a/packages/editor-ui/src/components/mixins/restApi.ts +++ b/packages/editor-ui/src/components/mixins/restApi.ts @@ -195,6 +195,11 @@ export const restApi = Vue.extend({ getBinaryBufferString: (dataPath: string): Promise => { return self.restApi().makeRestApiRequest('GET', `/data/${dataPath}`); }, + + // Returns scopes for OAuth credential types + getScopes: (credentialType: string): Promise => { + return self.restApi().makeRestApiRequest('GET', '/oauth2-credential/scopes', { credentialType }); + }, }; }, }, From 04997c5184727f73d8fcfe263d1964c3a5ad97a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Ovejero?= Date: Wed, 4 May 2022 14:59:18 +0200 Subject: [PATCH 2/4] :bug: Fix edge case in endpoint --- packages/cli/src/CredentialsHelper.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/cli/src/CredentialsHelper.ts b/packages/cli/src/CredentialsHelper.ts index d964daeb9b..99c92a5bc7 100644 --- a/packages/cli/src/CredentialsHelper.ts +++ b/packages/cli/src/CredentialsHelper.ts @@ -296,6 +296,9 @@ export class CredentialsHelper extends ICredentialsHelper { getScopes(type: string): string[] { const scopeProperty = this.getCredentialsProperties(type).find(({ name }) => name === 'scope'); + // edge case: scope property exists but is required to be empty string, e.g. GoToWebinar + if (scopeProperty?.default === '') return []; + if (!scopeProperty?.default || typeof scopeProperty.default !== 'string') { const errorMessage = `No \`scope\` property found for credential type: ${type}`; From 1efedfddf362cee355445eb1732480f69bba2c72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Ovejero?= Date: Wed, 4 May 2022 14:59:45 +0200 Subject: [PATCH 3/4] :zap: Display scopes alert box --- .../src/components/NodeCredentials.vue | 5 +++ .../editor-ui/src/components/NodeSettings.vue | 43 ++++++++++++++++++- .../src/plugins/i18n/locales/en.json | 1 + 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/packages/editor-ui/src/components/NodeCredentials.vue b/packages/editor-ui/src/components/NodeCredentials.vue index f82d28e737..10a6e5d458 100644 --- a/packages/editor-ui/src/components/NodeCredentials.vue +++ b/packages/editor-ui/src/components/NodeCredentials.vue @@ -72,6 +72,7 @@ import { showMessage } from '@/components/mixins/showMessage'; import { mapGetters } from "vuex"; import mixins from 'vue-typed-mixins'; +import { HTTP_REQUEST_NODE_TYPE } from '@/constants'; export default mixins( genericHelpers, @@ -106,6 +107,10 @@ export default mixins( credentialTypesNodeDescription (): INodeCredentialDescription[] { const node = this.node as INodeUi; + if (this.node.type === HTTP_REQUEST_NODE_TYPE && this.node.typeVersion === 2) { + this.$emit('newHttpRequestNodeCredentialType', this.node.parameters.nodeCredentialType); + } + const activeNodeType = this.$store.getters.nodeType(node.type, node.typeVersion) as INodeTypeDescription | null; if (activeNodeType && activeNodeType.credentials) { return activeNodeType.credentials; diff --git a/packages/editor-ui/src/components/NodeSettings.vue b/packages/editor-ui/src/components/NodeSettings.vue index 58a7708e58..229aa6fda4 100644 --- a/packages/editor-ui/src/components/NodeSettings.vue +++ b/packages/editor-ui/src/components/NodeSettings.vue @@ -23,7 +23,25 @@
- + +
@@ -69,6 +87,8 @@ import { nodeHelpers } from '@/components/mixins/nodeHelpers'; import mixins from 'vue-typed-mixins'; import NodeExecuteButton from './NodeExecuteButton.vue'; +import { mapGetters } from 'vuex'; +import { HTTP_REQUEST_NODE_TYPE } from '@/constants'; export default mixins( externalHooks, @@ -87,6 +107,10 @@ export default mixins( NodeExecuteButton, }, computed: { + ...mapGetters('credentials', [ 'getCredentialTypeByName' ]), + isHttpRequestNodeV2(): boolean { + return this.node.type === HTTP_REQUEST_NODE_TYPE && this.node.typeVersion === 2; + }, nodeType (): INodeTypeDescription | null { if (this.node) { return this.$store.getters.nodeType(this.node.type, this.node.typeVersion); @@ -169,6 +193,8 @@ export default mixins( notes: '', parameters: {}, } as INodeParameters, + activeCredential: '', + scopes: [] as string[], nodeSettings: [ { @@ -270,6 +296,21 @@ export default mixins( }, }, methods: { + async loadScopesNoticeData(activeCredentialType: string) { + if (!this.isHttpRequestNodeV2) return; + + if ( + !activeCredentialType || + !activeCredentialType.endsWith('OAuth2Api') + ) { + this.scopes = []; + return; + } + + this.activeCredential = this.getCredentialTypeByName(activeCredentialType).displayName; + + this.scopes = await this.restApi().getScopes(activeCredentialType); + }, onNodeExecute () { this.$emit('execute'); }, diff --git a/packages/editor-ui/src/plugins/i18n/locales/en.json b/packages/editor-ui/src/plugins/i18n/locales/en.json index 07d529d4c0..18ca996797 100644 --- a/packages/editor-ui/src/plugins/i18n/locales/en.json +++ b/packages/editor-ui/src/plugins/i18n/locales/en.json @@ -410,6 +410,7 @@ "nodeSettings.thisNodeDoesNotHaveAnyParameters": "This node does not have any parameters", "nodeSettings.waitBetweenTries.description": "How long to wait between each attempt (in milliseconds)", "nodeSettings.waitBetweenTries.displayName": "Wait Between Tries (ms)", + "nodeSettings.scopes": "Your {activeCredential} credential has access to the following scope:
{scopes} | Your {activeCredential} credential has access to the following scopes:
{scopes}", "nodeView.addNode": "Add node", "nodeView.addSticky": "Click to add sticky note", "nodeView.confirmMessage.beforeRouteLeave.cancelButtonText": "Leave without saving", From e530bd45e8825efdd2fe0f0510c6705cea26837b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Ovejero?= Date: Thu, 5 May 2022 18:12:08 +0200 Subject: [PATCH 4/4] :zap: Post-merge fixes --- .../editor-ui/src/components/NodeCredentials.vue | 2 +- .../editor-ui/src/components/NodeSettings.vue | 15 ++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/packages/editor-ui/src/components/NodeCredentials.vue b/packages/editor-ui/src/components/NodeCredentials.vue index 40e185769c..3fe09f52f7 100644 --- a/packages/editor-ui/src/components/NodeCredentials.vue +++ b/packages/editor-ui/src/components/NodeCredentials.vue @@ -121,7 +121,7 @@ export default mixins( credentialTypesNodeDescription (): INodeCredentialDescription[] { const node = this.node as INodeUi; - if (this.node.type === HTTP_REQUEST_NODE_TYPE && this.node.typeVersion === 2) { + if (this.isHttpRequestNodeV2(this.node)) { this.$emit('newHttpRequestNodeCredentialType', this.node.parameters.nodeCredentialType); } diff --git a/packages/editor-ui/src/components/NodeSettings.vue b/packages/editor-ui/src/components/NodeSettings.vue index 9b9f2660ee..64806d9ec2 100644 --- a/packages/editor-ui/src/components/NodeSettings.vue +++ b/packages/editor-ui/src/components/NodeSettings.vue @@ -24,7 +24,7 @@
@@ -96,7 +96,6 @@ import { nodeHelpers } from '@/components/mixins/nodeHelpers'; import mixins from 'vue-typed-mixins'; import NodeExecuteButton from './NodeExecuteButton.vue'; import { mapGetters } from 'vuex'; -import { HTTP_REQUEST_NODE_TYPE } from '@/constants'; export default mixins( externalHooks, @@ -116,9 +115,6 @@ export default mixins( }, computed: { ...mapGetters('credentials', [ 'getCredentialTypeByName' ]), - isHttpRequestNodeV2(): boolean { - return this.node.type === HTTP_REQUEST_NODE_TYPE && this.node.typeVersion === 2; - }, nodeType (): INodeTypeDescription | null { if (this.node) { return this.$store.getters.nodeType(this.node.type, this.node.typeVersion); @@ -305,7 +301,7 @@ export default mixins( }, methods: { async loadScopesNoticeData(activeCredentialType: string) { - if (!this.isHttpRequestNodeV2) return; + if (!this.isHttpRequestNodeV2(this.node)) return; if ( !activeCredentialType || @@ -617,6 +613,11 @@ export default mixins( height: 100%; overflow-y: auto; padding: 0 20px 200px 20px; + + // @TODO Revisit + > div > .notice[role=alert] { + margin-top: var(--spacing-s); + } } }