mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
✨ Added api keys get/create/delete actions.
This commit is contained in:
parent
88ec0b5313
commit
c0f3bd3c17
|
@ -833,6 +833,9 @@ export interface ISettingsState {
|
||||||
promptsData: IN8nPrompts;
|
promptsData: IN8nPrompts;
|
||||||
userManagement: IUserManagementConfig;
|
userManagement: IUserManagementConfig;
|
||||||
templatesEndpointHealthy: boolean;
|
templatesEndpointHealthy: boolean;
|
||||||
|
api: {
|
||||||
|
key: string | undefined;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ITemplateState {
|
export interface ITemplateState {
|
||||||
|
|
|
@ -6,7 +6,7 @@ export function getApiKey(context: IRestApiContext): Promise<{ apiKey: string |
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createApiKey(context: IRestApiContext): Promise<{ apiKey: string | null }> {
|
export function createApiKey(context: IRestApiContext): Promise<{ apiKey: string | null }> {
|
||||||
return makeRestApiRequest(context, 'POST', '/users/me/api-key');
|
return makeRestApiRequest(context, 'POST', '/me/api-key');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function deleteApiKey(context: IRestApiContext): Promise<{ success: boolean }> {
|
export function deleteApiKey(context: IRestApiContext): Promise<{ success: boolean }> {
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
<div>
|
<div>
|
||||||
<n8n-input-label :label="label">
|
<n8n-input-label :label="label">
|
||||||
<div :class="$style.copyText" @click="copy">
|
<div :class="$style.copyText" @click="copy">
|
||||||
<span>{{ copyContent }}</span>
|
<span>{{ value }}</span>
|
||||||
<div :class="$style.copyButton"><span>{{ copyButtonText }}</span></div>
|
<div :class="$style.copyButton"><span>{{ copyButtonText || $locale.baseText('generic.copyToClipboard') }}</span></div>
|
||||||
</div>
|
</div>
|
||||||
</n8n-input-label>
|
</n8n-input-label>
|
||||||
<div :class="$style.subtitle">{{ subtitle }}</div>
|
<div v-if="hint" :class="$style.hint">{{ hint }}</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -20,26 +20,29 @@ export default mixins(copyPaste, showMessage).extend({
|
||||||
label: {
|
label: {
|
||||||
type: String,
|
type: String,
|
||||||
},
|
},
|
||||||
subtitle: {
|
hint: {
|
||||||
type: String,
|
type: String,
|
||||||
},
|
},
|
||||||
copyContent: {
|
value: {
|
||||||
type: String,
|
type: String,
|
||||||
},
|
},
|
||||||
copyButtonText: {
|
copyButtonText: {
|
||||||
type: String,
|
type: String,
|
||||||
},
|
},
|
||||||
successMessage: {
|
toastTitle: {
|
||||||
|
type: String,
|
||||||
|
},
|
||||||
|
toastMessage: {
|
||||||
type: String,
|
type: String,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
copy(): void {
|
copy(): void {
|
||||||
this.copyToClipboard(this.$props.copyContent);
|
this.copyToClipboard(this.value);
|
||||||
|
|
||||||
this.$showMessage({
|
this.$showMessage({
|
||||||
title: this.$locale.baseText('credentialEdit.credentialEdit.showMessage.title'),
|
title: this.toastTitle || this.$locale.baseText('generic.copiedToClipboard'),
|
||||||
message: this.$props.successMessage,
|
message: this.toastMessage,
|
||||||
type: 'success',
|
type: 'success',
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -54,6 +57,10 @@ export default mixins(copyPaste, showMessage).extend({
|
||||||
font-family: Monaco, Consolas;
|
font-family: Monaco, Consolas;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
font-size: var(--font-size-s);
|
font-size: var(--font-size-s);
|
||||||
|
overflow: hidden;
|
||||||
|
width: 100%;
|
||||||
|
display: block;
|
||||||
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
padding: var(--spacing-xs);
|
padding: var(--spacing-xs);
|
||||||
|
@ -86,7 +93,7 @@ export default mixins(copyPaste, showMessage).extend({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.subtitle {
|
.hint {
|
||||||
margin-top: var(--spacing-2xs);
|
margin-top: var(--spacing-2xs);
|
||||||
font-size: var(--font-size-2xs);
|
font-size: var(--font-size-2xs);
|
||||||
line-height: var(--font-line-height-loose);
|
line-height: var(--font-line-height-loose);
|
||||||
|
|
|
@ -48,10 +48,11 @@
|
||||||
<CopyInput
|
<CopyInput
|
||||||
v-if="isOAuthType && credentialProperties.length"
|
v-if="isOAuthType && credentialProperties.length"
|
||||||
:label="$locale.baseText('credentialEdit.credentialConfig.oAuthRedirectUrl')"
|
:label="$locale.baseText('credentialEdit.credentialConfig.oAuthRedirectUrl')"
|
||||||
:copyContent="oAuthCallbackUrl"
|
:value="oAuthCallbackUrl"
|
||||||
:copyButtonText="$locale.baseText('credentialEdit.credentialConfig.clickToCopy')"
|
:copyButtonText="$locale.baseText('credentialEdit.credentialConfig.clickToCopy')"
|
||||||
:subtitle="$locale.baseText('credentialEdit.credentialConfig.subtitle', { interpolate: { appName } })"
|
:hint="$locale.baseText('credentialEdit.credentialConfig.subtitle', { interpolate: { appName } })"
|
||||||
:successMessage="$locale.baseText('credentialEdit.credentialConfig.redirectUrlCopiedToClipboard')"
|
:toastTitle="$locale.baseText('credentialEdit.credentialEdit.showMessage.title')"
|
||||||
|
:toastMessage="$locale.baseText('credentialEdit.credentialConfig.redirectUrlCopiedToClipboard')"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<CredentialInputs
|
<CredentialInputs
|
||||||
|
|
84
packages/editor-ui/src/components/DeleteApiKeyModal.vue
Normal file
84
packages/editor-ui/src/components/DeleteApiKeyModal.vue
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
<template>
|
||||||
|
<Modal
|
||||||
|
:name="name"
|
||||||
|
:title="$locale.baseText('settings.api.delete.title')"
|
||||||
|
:center="true"
|
||||||
|
:eventBus="modalBus"
|
||||||
|
width="460px"
|
||||||
|
@enter="deleteApiKey"
|
||||||
|
>
|
||||||
|
<template slot="content">
|
||||||
|
<div>
|
||||||
|
<n8n-text tag="p" color="text-base">
|
||||||
|
{{$locale.baseText('settings.api.delete.description')}}
|
||||||
|
</n8n-text>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template slot="footer">
|
||||||
|
<div :class="$style.footer">
|
||||||
|
<n8n-button type="outline" @click="cancel">
|
||||||
|
{{ $locale.baseText('generic.cancel') }}
|
||||||
|
</n8n-button>
|
||||||
|
<n8n-button :loading="loading" @click="deleteApiKey">
|
||||||
|
{{ $locale.baseText('settings.api.delete.button') }}
|
||||||
|
</n8n-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</Modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import Vue from 'vue';
|
||||||
|
import mixins from "vue-typed-mixins";
|
||||||
|
|
||||||
|
import Modal from "./Modal.vue";
|
||||||
|
import { N8nUserSelect } from 'n8n-design-system';
|
||||||
|
import { showMessage } from "../components/mixins/showMessage";
|
||||||
|
import {DELETE_API_KEY_MODAL_KEY} from "../constants";
|
||||||
|
|
||||||
|
export default mixins(showMessage).extend({
|
||||||
|
components: {
|
||||||
|
Modal,
|
||||||
|
N8nUserSelect,
|
||||||
|
},
|
||||||
|
name: "DeleteApiKeyModal",
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
modalBus: new Vue(),
|
||||||
|
name: DELETE_API_KEY_MODAL_KEY,
|
||||||
|
loading: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
cancel() {
|
||||||
|
this.$store.dispatch('ui/closeModal', DELETE_API_KEY_MODAL_KEY);
|
||||||
|
},
|
||||||
|
async deleteApiKey() {
|
||||||
|
this.loading = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.$store.dispatch('settings/deleteApiKey');
|
||||||
|
this.$store.dispatch('ui/closeModal', DELETE_API_KEY_MODAL_KEY);
|
||||||
|
this.$showMessage({ title: this.$locale.baseText("settings.api.delete.toast"), type: 'success' });
|
||||||
|
} catch (error) {
|
||||||
|
this.$showError(error, this.$locale.baseText('settings.api.delete.error'));
|
||||||
|
} finally {
|
||||||
|
this.loading = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" module>
|
||||||
|
.footer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
|
||||||
|
button + button {
|
||||||
|
margin-left: var(--spacing-xs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -88,6 +88,10 @@
|
||||||
<ModalRoot :name="WORKFLOW_ACTIVE_MODAL_KEY">
|
<ModalRoot :name="WORKFLOW_ACTIVE_MODAL_KEY">
|
||||||
<ActivationModal />
|
<ActivationModal />
|
||||||
</ModalRoot>
|
</ModalRoot>
|
||||||
|
|
||||||
|
<ModalRoot :name="DELETE_API_KEY_MODAL_KEY">
|
||||||
|
<DeleteApiKeyModal />
|
||||||
|
</ModalRoot>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -95,6 +99,7 @@
|
||||||
import Vue from "vue";
|
import Vue from "vue";
|
||||||
import {
|
import {
|
||||||
ABOUT_MODAL_KEY,
|
ABOUT_MODAL_KEY,
|
||||||
|
DELETE_API_KEY_MODAL_KEY,
|
||||||
CHANGE_PASSWORD_MODAL_KEY,
|
CHANGE_PASSWORD_MODAL_KEY,
|
||||||
CONTACT_PROMPT_MODAL_KEY,
|
CONTACT_PROMPT_MODAL_KEY,
|
||||||
CREDENTIAL_EDIT_MODAL_KEY,
|
CREDENTIAL_EDIT_MODAL_KEY,
|
||||||
|
@ -120,6 +125,7 @@ import CredentialEdit from "./CredentialEdit/CredentialEdit.vue";
|
||||||
import CredentialsList from "./CredentialsList.vue";
|
import CredentialsList from "./CredentialsList.vue";
|
||||||
import InviteUsersModal from "./InviteUsersModal.vue";
|
import InviteUsersModal from "./InviteUsersModal.vue";
|
||||||
import CredentialsSelectModal from "./CredentialsSelectModal.vue";
|
import CredentialsSelectModal from "./CredentialsSelectModal.vue";
|
||||||
|
import DeleteApiKeyModal from "./DeleteApiKeyModal.vue";
|
||||||
import DuplicateWorkflowDialog from "./DuplicateWorkflowDialog.vue";
|
import DuplicateWorkflowDialog from "./DuplicateWorkflowDialog.vue";
|
||||||
import ModalRoot from "./ModalRoot.vue";
|
import ModalRoot from "./ModalRoot.vue";
|
||||||
import PersonalizationModal from "./PersonalizationModal.vue";
|
import PersonalizationModal from "./PersonalizationModal.vue";
|
||||||
|
@ -142,6 +148,7 @@ export default Vue.extend({
|
||||||
CredentialEdit,
|
CredentialEdit,
|
||||||
CredentialsList,
|
CredentialsList,
|
||||||
CredentialsSelectModal,
|
CredentialsSelectModal,
|
||||||
|
DeleteApiKeyModal,
|
||||||
DeleteUserModal,
|
DeleteUserModal,
|
||||||
DuplicateWorkflowDialog,
|
DuplicateWorkflowDialog,
|
||||||
InviteUsersModal,
|
InviteUsersModal,
|
||||||
|
@ -155,6 +162,7 @@ export default Vue.extend({
|
||||||
WorkflowOpen,
|
WorkflowOpen,
|
||||||
},
|
},
|
||||||
data: () => ({
|
data: () => ({
|
||||||
|
DELETE_API_KEY_MODAL_KEY,
|
||||||
CONTACT_PROMPT_MODAL_KEY,
|
CONTACT_PROMPT_MODAL_KEY,
|
||||||
CREDENTIAL_EDIT_MODAL_KEY,
|
CREDENTIAL_EDIT_MODAL_KEY,
|
||||||
CREDENTIAL_LIST_MODAL_KEY,
|
CREDENTIAL_LIST_MODAL_KEY,
|
||||||
|
|
|
@ -22,6 +22,7 @@ export const CHANGE_PASSWORD_MODAL_KEY = 'changePassword';
|
||||||
export const CREDENTIAL_EDIT_MODAL_KEY = 'editCredential';
|
export const CREDENTIAL_EDIT_MODAL_KEY = 'editCredential';
|
||||||
export const CREDENTIAL_SELECT_MODAL_KEY = 'selectCredential';
|
export const CREDENTIAL_SELECT_MODAL_KEY = 'selectCredential';
|
||||||
export const DELETE_USER_MODAL_KEY = 'deleteUser';
|
export const DELETE_USER_MODAL_KEY = 'deleteUser';
|
||||||
|
export const DELETE_API_KEY_MODAL_KEY = 'deleteApiKey';
|
||||||
export const INVITE_USER_MODAL_KEY = 'inviteUser';
|
export const INVITE_USER_MODAL_KEY = 'inviteUser';
|
||||||
export const DUPLICATE_MODAL_KEY = 'duplicate';
|
export const DUPLICATE_MODAL_KEY = 'duplicate';
|
||||||
export const TAGS_MANAGER_MODAL_KEY = 'tagsManager';
|
export const TAGS_MANAGER_MODAL_KEY = 'tagsManager';
|
||||||
|
|
|
@ -12,6 +12,7 @@ import Vue from 'vue';
|
||||||
import { CONTACT_PROMPT_MODAL_KEY, VALUE_SURVEY_MODAL_KEY } from '@/constants';
|
import { CONTACT_PROMPT_MODAL_KEY, VALUE_SURVEY_MODAL_KEY } from '@/constants';
|
||||||
import { ITelemetrySettings } from 'n8n-workflow';
|
import { ITelemetrySettings } from 'n8n-workflow';
|
||||||
import { testHealthEndpoint } from '@/api/templates';
|
import { testHealthEndpoint } from '@/api/templates';
|
||||||
|
import {createApiKey, deleteApiKey, getApiKey} from "@/api/api-keys";
|
||||||
|
|
||||||
const module: Module<ISettingsState, IRootState> = {
|
const module: Module<ISettingsState, IRootState> = {
|
||||||
namespaced: true,
|
namespaced: true,
|
||||||
|
@ -24,6 +25,9 @@ const module: Module<ISettingsState, IRootState> = {
|
||||||
smtpSetup: false,
|
smtpSetup: false,
|
||||||
},
|
},
|
||||||
templatesEndpointHealthy: false,
|
templatesEndpointHealthy: false,
|
||||||
|
api: {
|
||||||
|
key: undefined,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
getters: {
|
getters: {
|
||||||
versionCli(state: ISettingsState) {
|
versionCli(state: ISettingsState) {
|
||||||
|
@ -68,6 +72,9 @@ const module: Module<ISettingsState, IRootState> = {
|
||||||
templatesHost: (state): string => {
|
templatesHost: (state): string => {
|
||||||
return state.settings.templates.host;
|
return state.settings.templates.host;
|
||||||
},
|
},
|
||||||
|
apiKey: (state): string | undefined => {
|
||||||
|
return state.api.key;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
mutations: {
|
mutations: {
|
||||||
setSettings(state: ISettingsState, settings: IN8nUISettings) {
|
setSettings(state: ISettingsState, settings: IN8nUISettings) {
|
||||||
|
@ -85,6 +92,9 @@ const module: Module<ISettingsState, IRootState> = {
|
||||||
setTemplatesEndpointHealthy(state: ISettingsState) {
|
setTemplatesEndpointHealthy(state: ISettingsState) {
|
||||||
state.templatesEndpointHealthy = true;
|
state.templatesEndpointHealthy = true;
|
||||||
},
|
},
|
||||||
|
setApiKey(state: ISettingsState, apiKey: string | undefined) {
|
||||||
|
state.api.key = apiKey;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
async getSettings(context: ActionContext<ISettingsState, IRootState>) {
|
async getSettings(context: ActionContext<ISettingsState, IRootState>) {
|
||||||
|
@ -153,6 +163,18 @@ const module: Module<ISettingsState, IRootState> = {
|
||||||
await Promise.race([testHealthEndpoint(context.getters.templatesHost), timeout]);
|
await Promise.race([testHealthEndpoint(context.getters.templatesHost), timeout]);
|
||||||
context.commit('setTemplatesEndpointHealthy', true);
|
context.commit('setTemplatesEndpointHealthy', true);
|
||||||
},
|
},
|
||||||
|
async getApiKey(context: ActionContext<ISettingsState, IRootState>) {
|
||||||
|
const { apiKey } = await getApiKey(context.rootGetters['getRestApiContext']);
|
||||||
|
context.commit('setApiKey', apiKey);
|
||||||
|
},
|
||||||
|
async createApiKey(context: ActionContext<ISettingsState, IRootState>) {
|
||||||
|
const { apiKey } = await createApiKey(context.rootGetters['getRestApiContext']);
|
||||||
|
context.commit('setApiKey', apiKey);
|
||||||
|
},
|
||||||
|
async deleteApiKey(context: ActionContext<ISettingsState, IRootState>) {
|
||||||
|
await deleteApiKey(context.rootGetters['getRestApiContext']);
|
||||||
|
context.commit('setApiKey', undefined);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import {
|
import {
|
||||||
ABOUT_MODAL_KEY,
|
ABOUT_MODAL_KEY,
|
||||||
|
DELETE_API_KEY_MODAL_KEY,
|
||||||
CREDENTIAL_EDIT_MODAL_KEY,
|
CREDENTIAL_EDIT_MODAL_KEY,
|
||||||
CREDENTIAL_SELECT_MODAL_KEY,
|
CREDENTIAL_SELECT_MODAL_KEY,
|
||||||
CHANGE_PASSWORD_MODAL_KEY,
|
CHANGE_PASSWORD_MODAL_KEY,
|
||||||
|
@ -32,6 +33,9 @@ const module: Module<IUiState, IRootState> = {
|
||||||
[ABOUT_MODAL_KEY]: {
|
[ABOUT_MODAL_KEY]: {
|
||||||
open: false,
|
open: false,
|
||||||
},
|
},
|
||||||
|
[DELETE_API_KEY_MODAL_KEY]: {
|
||||||
|
open: false,
|
||||||
|
},
|
||||||
[CHANGE_PASSWORD_MODAL_KEY]: {
|
[CHANGE_PASSWORD_MODAL_KEY]: {
|
||||||
open: false,
|
open: false,
|
||||||
},
|
},
|
||||||
|
@ -145,6 +149,9 @@ const module: Module<IUiState, IRootState> = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
|
closeModal: async (context: ActionContext<IUiState, IRootState>, modalKey: string) => {
|
||||||
|
context.commit('closeModal', modalKey);
|
||||||
|
},
|
||||||
openModal: async (context: ActionContext<IUiState, IRootState>, modalKey: string) => {
|
openModal: async (context: ActionContext<IUiState, IRootState>, modalKey: string) => {
|
||||||
context.commit('openModal', modalKey);
|
context.commit('openModal', modalKey);
|
||||||
},
|
},
|
||||||
|
|
|
@ -4,6 +4,12 @@
|
||||||
"_reusableBaseText.save": "Save",
|
"_reusableBaseText.save": "Save",
|
||||||
"_reusableDynamicText.oauth2.clientId": "Client ID",
|
"_reusableDynamicText.oauth2.clientId": "Client ID",
|
||||||
"_reusableDynamicText.oauth2.clientSecret": "Client Secret",
|
"_reusableDynamicText.oauth2.clientSecret": "Client Secret",
|
||||||
|
"generic.learnMore": "Learn more",
|
||||||
|
"generic.confirm": "Confirm",
|
||||||
|
"generic.cancel": "Cancel",
|
||||||
|
"generic.delete": "Delete",
|
||||||
|
"generic.copyToClipboard": "Copy to clipboard",
|
||||||
|
"generic.copiedToClipboard": "Copied to clipboard",
|
||||||
"about.aboutN8n": "About n8n",
|
"about.aboutN8n": "About n8n",
|
||||||
"about.close": "Close",
|
"about.close": "Close",
|
||||||
"about.license": "License",
|
"about.license": "License",
|
||||||
|
@ -653,12 +659,16 @@
|
||||||
"settings.api.create.description.link": "REST API",
|
"settings.api.create.description.link": "REST API",
|
||||||
"settings.api.create.button": "Create an API Key",
|
"settings.api.create.button": "Create an API Key",
|
||||||
"settings.api.create.button.loading": "Creating API Key...",
|
"settings.api.create.button.loading": "Creating API Key...",
|
||||||
"settings.api.error.title": "Something went wrong",
|
"settings.api.create.error": "Creating the API Key failed.",
|
||||||
"settings.api.error.get": "Could not check if an api key already exists.",
|
"settings.api.delete.title": "Delete this API Key?",
|
||||||
"settings.api.error.create": "Creating the API Key failed.",
|
"settings.api.delete.description": "Any application using this API Key will no longer be granted access to n8n data. This operation cannot be undone.",
|
||||||
"settings.api.error.delete": "Deleting the API Key failed.",
|
"settings.api.delete.button": "Delete Forever",
|
||||||
|
"settings.api.delete.error": "Deleting the API Key failed.",
|
||||||
|
"settings.api.delete.toast": "API Key deleted",
|
||||||
"settings.api.view.info": "Use your API Key to access n8n's REST API to build your own integrations.",
|
"settings.api.view.info": "Use your API Key to access n8n's REST API to build your own integrations.",
|
||||||
"settings.api.view.myKey": "My API Key",
|
"settings.api.view.myKey": "My API Key",
|
||||||
|
"settings.api.view.copy.toast": "API Key copied to clipboard",
|
||||||
|
"settings.api.view.error": "Could not check if an api key already exists.",
|
||||||
"settings.version": "Version",
|
"settings.version": "Version",
|
||||||
"showMessage.cancel": "@:_reusableBaseText.cancel",
|
"showMessage.cancel": "@:_reusableBaseText.cancel",
|
||||||
"showMessage.ok": "OK",
|
"showMessage.ok": "OK",
|
||||||
|
|
|
@ -6,18 +6,41 @@
|
||||||
{{ $locale.baseText('settings.api') }}
|
{{ $locale.baseText('settings.api') }}
|
||||||
</n8n-heading>
|
</n8n-heading>
|
||||||
</div>
|
</div>
|
||||||
<n8n-card v-if="apiKey">
|
|
||||||
Hello
|
<div v-if="apiKey">
|
||||||
</n8n-card>
|
<p class="mb-s">
|
||||||
|
<n8n-text color="text-base">
|
||||||
|
<font-awesome-icon icon="info-circle" />
|
||||||
|
{{ $locale.baseText('settings.api.view.info') }}
|
||||||
|
<n8n-link to="https://docs.n8n.io/api/">
|
||||||
|
{{ $locale.baseText('generic.learnMore') }}
|
||||||
|
</n8n-link>
|
||||||
|
</n8n-text>
|
||||||
|
</p>
|
||||||
|
<n8n-card :class="$style.card">
|
||||||
|
<span :class="$style.delete">
|
||||||
|
<n8n-link @click="showDeleteModal">
|
||||||
|
{{ $locale.baseText('generic.delete') }}
|
||||||
|
</n8n-link>
|
||||||
|
</span>
|
||||||
|
<CopyInput
|
||||||
|
:label="$locale.baseText('settings.api.view.myKey')"
|
||||||
|
:value="apiKey"
|
||||||
|
:toast-title="$locale.baseText('settings.api.view.copy.toast')"
|
||||||
|
/>
|
||||||
|
</n8n-card>
|
||||||
|
</div>
|
||||||
<div :class="$style.placeholder" v-else>
|
<div :class="$style.placeholder" v-else>
|
||||||
<n8n-heading size="xlarge">
|
<n8n-heading size="xlarge">
|
||||||
{{ $locale.baseText('settings.api.create.title') }}
|
{{ $locale.baseText('settings.api.create.title') }}
|
||||||
</n8n-heading>
|
</n8n-heading>
|
||||||
<p class="mt-2xs mb-l">
|
<p class="mt-2xs mb-l">
|
||||||
{{$locale.baseText('settings.api.create.description')}}
|
<n8n-text color="text-base">
|
||||||
<a href="https://docs.n8n.io/reference/glossary/#rest-api" target="_blank">
|
{{$locale.baseText('settings.api.create.description')}}
|
||||||
{{$locale.baseText('settings.api.create.description.link')}}
|
<n8n-link to="https://docs.n8n.io/api/">
|
||||||
</a>
|
{{$locale.baseText('settings.api.create.description.link')}}
|
||||||
|
</n8n-link>
|
||||||
|
</n8n-text>
|
||||||
</p>
|
</p>
|
||||||
<n8n-button :loading="loading" size="large" class="mt-l" @click="createApiKey">
|
<n8n-button :loading="loading" size="large" class="mt-l" @click="createApiKey">
|
||||||
{{$locale.baseText(loading ? 'settings.api.create.button.loading' : 'settings.api.create.button')}}
|
{{$locale.baseText(loading ? 'settings.api.create.button.loading' : 'settings.api.create.button')}}
|
||||||
|
@ -34,6 +57,8 @@ import { IUser } from '@/Interface';
|
||||||
import mixins from 'vue-typed-mixins';
|
import mixins from 'vue-typed-mixins';
|
||||||
|
|
||||||
import SettingsView from './SettingsView.vue';
|
import SettingsView from './SettingsView.vue';
|
||||||
|
import CopyInput from '../components/CopyInput.vue';
|
||||||
|
import {DELETE_API_KEY_MODAL_KEY} from "../constants";
|
||||||
|
|
||||||
export default mixins(
|
export default mixins(
|
||||||
showMessage,
|
showMessage,
|
||||||
|
@ -41,30 +66,35 @@ export default mixins(
|
||||||
name: 'SettingsPersonalView',
|
name: 'SettingsPersonalView',
|
||||||
components: {
|
components: {
|
||||||
SettingsView,
|
SettingsView,
|
||||||
|
CopyInput,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
apiKey: '' as string | null,
|
|
||||||
loading: false,
|
loading: false,
|
||||||
mounted: false,
|
mounted: false,
|
||||||
error: '',
|
error: '',
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
async mounted() {
|
mounted() {
|
||||||
this.getApiKey();
|
this.getApiKey();
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
currentUser() {
|
currentUser() {
|
||||||
return this.$store.getters['users/currentUser'] as IUser;
|
return this.$store.getters['users/currentUser'] as IUser;
|
||||||
},
|
},
|
||||||
|
apiKey() {
|
||||||
|
return this.$store.getters['settings/apiKey'];
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
showDeleteModal() {
|
||||||
|
this.$store.dispatch('ui/openModal', DELETE_API_KEY_MODAL_KEY);
|
||||||
|
},
|
||||||
async getApiKey() {
|
async getApiKey() {
|
||||||
try {
|
try {
|
||||||
const { apiKey } = await getApiKey(this.$store.getters['getRestApiContext']);
|
this.$store.dispatch('settings/getApiKey');
|
||||||
this.apiKey = apiKey;
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.$showError(error, this.$locale.baseText('settings.api.error.get'));
|
this.$showError(error, this.$locale.baseText('settings.api.view.error'));
|
||||||
} finally {
|
} finally {
|
||||||
this.mounted = true;
|
this.mounted = true;
|
||||||
}
|
}
|
||||||
|
@ -73,23 +103,13 @@ export default mixins(
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { apiKey } = await createApiKey(this.$store.getters['getRestApiContext']);
|
this.$store.dispatch('settings/createApiKey');
|
||||||
this.apiKey = apiKey;
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.$showError(error, this.$locale.baseText('settings.api.error.create'));
|
this.$showError(error, this.$locale.baseText('settings.api.create.error'));
|
||||||
} finally {
|
} finally {
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async deleteApiKey() {
|
|
||||||
this.loading = true;
|
|
||||||
|
|
||||||
try {
|
|
||||||
await deleteApiKey(this.$store.getters['getRestApiContext']);
|
|
||||||
} catch (error) {
|
|
||||||
this.$showError(error, this.$locale.baseText('settings.api.error.delete'));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -120,5 +140,16 @@ export default mixins(
|
||||||
align-items: center;
|
align-items: center;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete {
|
||||||
|
position: absolute;
|
||||||
|
display: inline-block;
|
||||||
|
top: var(--spacing-s);
|
||||||
|
right: var(--spacing-s);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue