diff --git a/packages/cli/src/Server.ts b/packages/cli/src/Server.ts
index 9da615f7a3..1d82c4d807 100644
--- a/packages/cli/src/Server.ts
+++ b/packages/cli/src/Server.ts
@@ -731,8 +731,6 @@ class App {
// Encrypt the data
const credentials = new Credentials(incomingData.name, incomingData.type, incomingData.nodesAccess);
- _.unset(incomingData.data, 'csrfSecret');
- _.unset(incomingData.data, 'oauthTokenData');
credentials.setData(incomingData.data, encryptionKey);
const newCredentialsData = credentials.getDataToSave() as unknown as ICredentialsDb;
@@ -899,7 +897,14 @@ class App {
// Update the credentials in DB
await Db.collections.Credentials!.update(req.query.id, newCredentialsData);
- return oAuthObj.code.getUri();
+ const authQueryParameters = _.get(oauthCredentials, 'authQueryParameters', '') as string;
+ let returnUri = oAuthObj.code.getUri();
+
+ if (authQueryParameters) {
+ returnUri += '&' + authQueryParameters;
+ }
+
+ return returnUri;
}));
// ----------------------------------------
diff --git a/packages/editor-ui/src/Interface.ts b/packages/editor-ui/src/Interface.ts
index 7c692881a8..e0e6355359 100644
--- a/packages/editor-ui/src/Interface.ts
+++ b/packages/editor-ui/src/Interface.ts
@@ -157,6 +157,13 @@ export interface IBinaryDisplayData {
runIndex: number;
}
+export interface ICredentialsCreatedEvent {
+ data: ICredentialsDecryptedResponse;
+ options: {
+ closeDialog: boolean,
+ };
+}
+
export interface IStartRunData {
workflowData: IWorkflowData;
startNodes?: string[];
diff --git a/packages/editor-ui/src/components/CredentialsEdit.vue b/packages/editor-ui/src/components/CredentialsEdit.vue
index 256cf70311..cd3b6c1f74 100644
--- a/packages/editor-ui/src/components/CredentialsEdit.vue
+++ b/packages/editor-ui/src/components/CredentialsEdit.vue
@@ -31,7 +31,10 @@ import Vue from 'vue';
import { restApi } from '@/components/mixins/restApi';
import { showMessage } from '@/components/mixins/showMessage';
import CredentialsInput from '@/components/CredentialsInput.vue';
-import { ICredentialsDecryptedResponse } from '@/Interface';
+import {
+ ICredentialsCreatedEvent,
+ ICredentialsDecryptedResponse,
+} from '@/Interface';
import {
ICredentialType,
@@ -185,27 +188,31 @@ export default mixins(
return credentialData;
},
- credentialsCreated (data: ICredentialsDecryptedResponse): void {
- this.$emit('credentialsCreated', data);
+ credentialsCreated (eventData: ICredentialsCreatedEvent): void {
+ this.$emit('credentialsCreated', eventData);
this.$showMessage({
title: 'Credentials created',
- message: `The credential "${data.name}" got created!`,
+ message: `The credential "${eventData.data.name}" got created!`,
type: 'success',
});
- this.closeDialog();
+ if (eventData.options.closeDialog === true) {
+ this.closeDialog();
+ }
},
- credentialsUpdated (data: ICredentialsDecryptedResponse): void {
- this.$emit('credentialsUpdated', data);
+ credentialsUpdated (eventData: ICredentialsCreatedEvent): void {
+ this.$emit('credentialsUpdated', eventData);
this.$showMessage({
title: 'Credentials updated',
- message: `The credential "${data.name}" got updated!`,
+ message: `The credential "${eventData.data.name}" got updated!`,
type: 'success',
});
- this.closeDialog();
+ if (eventData.options.closeDialog === true) {
+ this.closeDialog();
+ }
},
closeDialog (): void {
// Handle the close externally as the visible parameter is an external prop
diff --git a/packages/editor-ui/src/components/CredentialsInput.vue b/packages/editor-ui/src/components/CredentialsInput.vue
index d8be6d09a9..bc5b6225d3 100644
--- a/packages/editor-ui/src/components/CredentialsInput.vue
+++ b/packages/editor-ui/src/components/CredentialsInput.vue
@@ -79,10 +79,10 @@
-
+
Save
-
+
Create
@@ -141,6 +141,7 @@ export default mixins(
credentialsName: 'The name the credentials should be saved as. Use a name
which makes it clear to what exactly they give access to.
For credentials of an Email account that could be the Email address itself.',
nodesWithAccess: 'The nodes which allowed to use this credentials.',
},
+ credentialDataTemp: null as ICredentialsDecryptedResponse | null,
nodesAccess: [] as string[],
name: '',
propertyValue: {} as ICredentialDataDecryptedObject,
@@ -182,6 +183,13 @@ export default mixins(
return !this.credentialTypeData.__overwrittenProperties || !this.credentialTypeData.__overwrittenProperties.includes(propertyData.name);
});
},
+ credentialDataDynamic (): ICredentialsDecryptedResponse | null {
+ if (this.credentialData) {
+ return this.credentialData;
+ }
+
+ return this.credentialDataTemp;
+ },
isOAuthType (): boolean {
return this.credentialTypeData.name === 'oAuth2Api' || (this.credentialTypeData.extends !== undefined && this.credentialTypeData.extends.includes('oAuth2Api'));
},
@@ -190,7 +198,7 @@ export default mixins(
return false;
}
- return this.credentialData !== null && !!this.credentialData.data.oauthTokenData;
+ return this.credentialDataDynamic !== null && !!this.credentialDataDynamic.data!.oauthTokenData;
},
},
methods: {
@@ -202,7 +210,7 @@ export default mixins(
tempValue[name] = parameterData.value;
Vue.set(this, 'propertyValue', tempValue);
},
- async createCredentials (doNotEmitData?: boolean): Promise {
+ async createCredentials (closeDialog: boolean): Promise {
const nodesAccess = this.nodesAccess.map((nodeType) => {
return {
nodeType,
@@ -227,29 +235,30 @@ export default mixins(
// Add also to local store
this.$store.commit('addCredentials', result);
- if (doNotEmitData !== true) {
- this.$emit('credentialsCreated', result);
- }
+ this.$emit('credentialsCreated', {data: result, options: { closeDialog }});
return result;
},
async oAuth2CredentialAuthorize () {
let url;
- let credentialData = this.credentialData;
+ let credentialData = this.credentialDataDynamic;
let newCredentials = false;
if (!credentialData) {
// Credentials did not get created yet. So create first before
// doing oauth authorize
- credentialData = await this.createCredentials(true);
+ credentialData = await this.createCredentials(false) as ICredentialsDecryptedResponse;
newCredentials = true;
if (credentialData === null) {
return;
}
+ } else {
+ // Exists already but got maybe changed. So save first
+ credentialData = await this.updateCredentials(false) as ICredentialsDecryptedResponse;
}
try {
- url = await this.restApi().oAuth2CredentialAuthorize(credentialData) as string;
+ url = await this.restApi().oAuth2CredentialAuthorize(credentialData as ICredentialsResponse) as string;
} catch (error) {
this.$showError(error, 'OAuth Authorization Error', 'Error generating authorization URL:');
return;
@@ -268,7 +277,17 @@ export default mixins(
// Set some kind of data that status changes.
// As data does not get displayed directly it does not matter what data.
- credentialData.data.oauthTokenData = {};
+ if (this.credentialData === null) {
+ // Are new credentials so did not get send via "credentialData"
+ this.credentialDataTemp = credentialData as ICredentialsDecryptedResponse;
+ Vue.set(this.credentialDataTemp.data, 'oauthTokenData', {});
+ } else {
+ // Credentials did already exist so can be set directly
+ Vue.set(this.credentialData.data, 'oauthTokenData', {});
+ }
+
+ // Save that OAuth got authorized locally
+ this.$store.commit('updateCredentials', this.credentialDataDynamic);
// Close the window
if (oauthPopup) {
@@ -276,7 +295,7 @@ export default mixins(
}
if (newCredentials === true) {
- this.$emit('credentialsCreated', credentialData);
+ this.$emit('credentialsCreated', {data: credentialData, options: { closeDialog: false }});
}
this.$showMessage({
@@ -292,13 +311,13 @@ export default mixins(
window.addEventListener('message', receiveMessage, false);
},
- async updateCredentials () {
+ async updateCredentials (closeDialog: boolean): Promise {
const nodesAccess: ICredentialNodeAccess[] = [];
const addedNodeTypes: string[] = [];
// Add Node-type which already had access to keep the original added date
let nodeAccessData: ICredentialNodeAccess;
- for (nodeAccessData of (this.credentialData as ICredentialsDecryptedResponse).nodesAccess) {
+ for (nodeAccessData of (this.credentialDataDynamic as ICredentialsDecryptedResponse).nodesAccess) {
if (this.nodesAccess.includes((nodeAccessData.nodeType))) {
nodesAccess.push(nodeAccessData);
addedNodeTypes.push(nodeAccessData.nodeType);
@@ -323,7 +342,7 @@ export default mixins(
let result;
try {
- result = await this.restApi().updateCredentials((this.credentialData as ICredentialsDecryptedResponse).id as string, newCredentials);
+ result = await this.restApi().updateCredentials((this.credentialDataDynamic as ICredentialsDecryptedResponse).id as string, newCredentials);
} catch (error) {
this.$showError(error, 'Problem Updating Credentials', 'There was a problem updating the credentials:');
return;
@@ -336,7 +355,9 @@ export default mixins(
// which have now a different name
this.updateNodesCredentialsIssues();
- this.$emit('credentialsUpdated', result);
+ this.$emit('credentialsUpdated', {data: result, options: { closeDialog }});
+
+ return result;
},
init () {
if (this.credentialData) {
diff --git a/packages/editor-ui/src/components/NodeCredentials.vue b/packages/editor-ui/src/components/NodeCredentials.vue
index 213f142840..8284c272e1 100644
--- a/packages/editor-ui/src/components/NodeCredentials.vue
+++ b/packages/editor-ui/src/components/NodeCredentials.vue
@@ -45,6 +45,7 @@ import Vue from 'vue';
import { restApi } from '@/components/mixins/restApi';
import {
+ ICredentialsCreatedEvent,
ICredentialsResponse,
INodeUi,
INodeUpdatePropertiesInformation,
@@ -134,21 +135,23 @@ export default mixins(
closeCredentialNewDialog () {
this.credentialNewDialogVisible = false;
},
- async credentialsCreated (data: ICredentialsResponse) {
- await this.credentialsUpdated(data);
+ async credentialsCreated (eventData: ICredentialsCreatedEvent) {
+ await this.credentialsUpdated(eventData.data as ICredentialsResponse);
},
- credentialsUpdated (data: ICredentialsResponse) {
- if (!this.credentialTypesNode.includes(data.type)) {
+ credentialsUpdated (eventData: ICredentialsCreatedEvent) {
+ if (!this.credentialTypesNode.includes(eventData.data.type)) {
return;
}
this.init();
- Vue.set(this.credentials, data.type, data.name);
+ Vue.set(this.credentials, eventData.data.type, eventData.data.name);
// Makes sure that it does also get set correctly on the node not just the UI
- this.credentialSelected(data.type);
+ this.credentialSelected(eventData.data.type);
- this.closeCredentialNewDialog();
+ if (eventData.options.closeDialog === true) {
+ this.closeCredentialNewDialog();
+ }
},
credentialInputWrapperStyle (credentialType: string) {
let deductWidth = 0;
diff --git a/packages/nodes-base/credentials/OAuth2Api.credentials.ts b/packages/nodes-base/credentials/OAuth2Api.credentials.ts
index 99e8e025de..efa5127e6e 100644
--- a/packages/nodes-base/credentials/OAuth2Api.credentials.ts
+++ b/packages/nodes-base/credentials/OAuth2Api.credentials.ts
@@ -45,5 +45,13 @@ export class OAuth2Api implements ICredentialType {
type: 'string' as NodePropertyTypes,
default: '',
},
+ {
+ displayName: 'Auth URI Query Parameters',
+ name: 'authQueryParameters',
+ type: 'string' as NodePropertyTypes,
+ default: '',
+ description: 'For some services additional query parameters have to be set which can be defined here.',
+ placeholder: 'access_type=offline',
+ },
];
}