mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 10:02:05 +00:00
Initial commit to release
This commit is contained in:
270
packages/editor-ui/src/components/CredentialsInput.vue
Normal file
270
packages/editor-ui/src/components/CredentialsInput.vue
Normal file
@@ -0,0 +1,270 @@
|
||||
<template>
|
||||
<div @keydown.stop class="credentials-input-wrapper">
|
||||
<el-row>
|
||||
<el-col :span="6">
|
||||
Preset Name:
|
||||
</el-col>
|
||||
<el-col :span="18">
|
||||
<el-input size="small" type="text" v-model="name"></el-input>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<br />
|
||||
<div class="headline">
|
||||
Credential Data:
|
||||
</div>
|
||||
<el-row v-for="parameter in credentialTypeData.properties" :key="parameter.name" class="parameter-wrapper">
|
||||
<el-col :span="6">
|
||||
{{parameter.displayName}}:
|
||||
</el-col>
|
||||
<el-col :span="18">
|
||||
<parameter-input :parameter="parameter" :value="propertyValue[parameter.name]" :path="parameter.name" :isCredential="true" @valueChanged="valueChanged" />
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row class="nodes-access-wrapper">
|
||||
<el-col :span="6" class="headline">
|
||||
Nodes with access:
|
||||
</el-col>
|
||||
<el-col :span="18">
|
||||
<el-transfer
|
||||
:titles="['No Access', 'Access ']"
|
||||
v-model="nodesAccess"
|
||||
:data="allNodesRequestingAccess">
|
||||
</el-transfer>
|
||||
|
||||
<div v-if="nodesAccess.length === 0" class="no-nodes-access">
|
||||
<strong>
|
||||
Important!
|
||||
</strong><br />
|
||||
Add at least one node which has access to the credentials!
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<div class="action-buttons">
|
||||
<el-button type="success" @click="updateCredentials" v-if="credentialData">
|
||||
Save
|
||||
</el-button>
|
||||
<el-button type="success" @click="createCredentials" v-else>
|
||||
Create
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
|
||||
import { restApi } from '@/components/mixins/restApi';
|
||||
import { nodeHelpers } from '@/components/mixins/nodeHelpers';
|
||||
import { ICredentialsDecryptedResponse, IUpdateInformation } from '@/Interface';
|
||||
import {
|
||||
CredentialInformation,
|
||||
ICredentialDataDecryptedObject,
|
||||
ICredentialsDecrypted,
|
||||
ICredentialType,
|
||||
ICredentialNodeAccess,
|
||||
INodeCredentialDescription,
|
||||
INodeTypeDescription,
|
||||
} from 'n8n-workflow';
|
||||
|
||||
import ParameterInput from '@/components/ParameterInput.vue';
|
||||
|
||||
import mixins from 'vue-typed-mixins';
|
||||
|
||||
export default mixins(
|
||||
nodeHelpers,
|
||||
restApi,
|
||||
).extend({
|
||||
name: 'CredentialsInput',
|
||||
props: [
|
||||
'credentialTypeData', // ICredentialType
|
||||
'credentialData', // ICredentialsDecryptedResponse
|
||||
'nodesInit', // {
|
||||
// type: Array,
|
||||
// default: () => { [] },
|
||||
// }
|
||||
],
|
||||
components: {
|
||||
ParameterInput,
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
nodesAccess: [] as string[],
|
||||
name: '',
|
||||
propertyValue: {} as ICredentialDataDecryptedObject,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
allNodesRequestingAccess (): Array<{key: string, label: string}> {
|
||||
const returnNodeTypes: string[] = [];
|
||||
|
||||
const nodeTypes: INodeTypeDescription[] = this.$store.getters.allNodeTypes;
|
||||
|
||||
let nodeType: INodeTypeDescription;
|
||||
let credentialTypeDescription: INodeCredentialDescription;
|
||||
|
||||
// Find the node types which need the credentials
|
||||
for (nodeType of nodeTypes) {
|
||||
if (!nodeType.credentials) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (credentialTypeDescription of nodeType.credentials) {
|
||||
if (credentialTypeDescription.name === (this.credentialTypeData as ICredentialType).name && !returnNodeTypes.includes(credentialTypeDescription.name)) {
|
||||
returnNodeTypes.push(nodeType.name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return the data in the correct format el-transfer expects
|
||||
return returnNodeTypes.map((nodeTypeName: string) => {
|
||||
return {
|
||||
key: nodeTypeName,
|
||||
label: this.$store.getters.nodeType(nodeTypeName).displayName as string,
|
||||
};
|
||||
});
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
valueChanged (parameterData: IUpdateInformation) {
|
||||
const name = parameterData.name.split('.').pop();
|
||||
// @ts-ignore
|
||||
this.propertyValue[name] = parameterData.value;
|
||||
},
|
||||
async createCredentials () {
|
||||
const nodesAccess = this.nodesAccess.map((nodeType) => {
|
||||
return {
|
||||
nodeType,
|
||||
};
|
||||
});
|
||||
|
||||
const newCredentials = {
|
||||
name: this.name,
|
||||
type: (this.credentialTypeData as ICredentialType).name,
|
||||
nodesAccess,
|
||||
data: this.propertyValue,
|
||||
} as ICredentialsDecrypted;
|
||||
|
||||
const result = await this.restApi().createNewCredentials(newCredentials);
|
||||
|
||||
// Add also to local store
|
||||
this.$store.commit('addCredentials', result);
|
||||
|
||||
this.$emit('credentialsCreated', result);
|
||||
},
|
||||
async updateCredentials () {
|
||||
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) {
|
||||
if (this.nodesAccess.includes((nodeAccessData.nodeType))) {
|
||||
nodesAccess.push(nodeAccessData);
|
||||
addedNodeTypes.push(nodeAccessData.nodeType);
|
||||
}
|
||||
}
|
||||
|
||||
// Add Node-type which did not have access before
|
||||
for (const nodeType of this.nodesAccess) {
|
||||
if (!addedNodeTypes.includes(nodeType)) {
|
||||
nodesAccess.push({
|
||||
nodeType,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const newCredentials = {
|
||||
name: this.name,
|
||||
type: (this.credentialTypeData as ICredentialType).name,
|
||||
nodesAccess,
|
||||
data: this.propertyValue,
|
||||
} as ICredentialsDecrypted;
|
||||
|
||||
const result = await this.restApi().updateCredentials((this.credentialData as ICredentialsDecryptedResponse).id as string, newCredentials);
|
||||
|
||||
// Update also in local store
|
||||
this.$store.commit('updateCredentials', result);
|
||||
|
||||
// Now that the credentials changed check if any nodes use credentials
|
||||
// which have now a different name
|
||||
this.updateNodesCredentialsIssues();
|
||||
|
||||
this.$emit('credentialsUpdated', result);
|
||||
},
|
||||
init () {
|
||||
if (this.credentialData) {
|
||||
// Initialize with the given data
|
||||
this.name = (this.credentialData as ICredentialsDecryptedResponse).name;
|
||||
this.propertyValue = (this.credentialData as ICredentialsDecryptedResponse).data as ICredentialDataDecryptedObject;
|
||||
const nodesAccess = (this.credentialData as ICredentialsDecryptedResponse).nodesAccess.map((nodeAccess) => {
|
||||
return nodeAccess.nodeType;
|
||||
});
|
||||
|
||||
Vue.set(this, 'nodesAccess', nodesAccess);
|
||||
} else {
|
||||
// No data supplied so init empty
|
||||
this.name = '';
|
||||
this.propertyValue = {} as ICredentialDataDecryptedObject;
|
||||
const nodesAccess = [] as string[];
|
||||
nodesAccess.push.apply(nodesAccess, this.nodesInit);
|
||||
|
||||
Vue.set(this, 'nodesAccess', nodesAccess);
|
||||
}
|
||||
|
||||
// Set default values
|
||||
for (const property of (this.credentialTypeData as ICredentialType).properties) {
|
||||
if (!this.propertyValue.hasOwnProperty(property.name)) {
|
||||
this.propertyValue[property.name] = property.default as CredentialInformation;
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
credentialData () {
|
||||
this.init();
|
||||
},
|
||||
credentialTypeData () {
|
||||
this.init();
|
||||
},
|
||||
},
|
||||
mounted () {
|
||||
this.init();
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
.credentials-input-wrapper {
|
||||
.action-buttons {
|
||||
margin-top: 2em;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.headline {
|
||||
font-weight: 600;
|
||||
color: $--color-primary;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.nodes-access-wrapper {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.no-nodes-access {
|
||||
margin: 1em 0;
|
||||
color: $--color-primary;
|
||||
line-height: 1.75em;
|
||||
}
|
||||
|
||||
.parameter-wrapper {
|
||||
line-height: 3em;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
Reference in New Issue
Block a user