Added api key setup view.

This commit is contained in:
Alex Grozav 2022-04-28 13:11:44 +03:00
parent f98813cdc6
commit 88ec0b5313
8 changed files with 178 additions and 1 deletions

View file

@ -0,0 +1,14 @@
import {IRestApiContext} from "@/Interface";
import {makeRestApiRequest} from "@/api/helpers";
export function getApiKey(context: IRestApiContext): Promise<{ apiKey: string | null }> {
return makeRestApiRequest(context, 'GET', '/me/api-key');
}
export function createApiKey(context: IRestApiContext): Promise<{ apiKey: string | null }> {
return makeRestApiRequest(context, 'POST', '/users/me/api-key');
}
export function deleteApiKey(context: IRestApiContext): Promise<{ success: boolean }> {
return makeRestApiRequest(context, 'DELETE', '/me/api-key');
}

View file

@ -1,4 +1,4 @@
import { IRestApiContext, IN8nPrompts, IN8nValueSurveyData, IN8nUISettings } from '../Interface';
import {IRestApiContext, IN8nPrompts, IN8nValueSurveyData, IN8nUISettings} from '../Interface';
import { makeRestApiRequest, get, post } from './helpers';
import { N8N_IO_BASE_URL } from '@/constants';

View file

@ -19,6 +19,12 @@
</i>
<span slot="title">{{ $locale.baseText('settings.users') }}</span>
</n8n-menu-item>
<n8n-menu-item index="/settings/api" :class="$style.tab">
<i :class="$style.icon">
<font-awesome-icon icon="plug" />
</i>
<span slot="title">{{ $locale.baseText('settings.api') }}</span>
</n8n-menu-item>
</n8n-menu>
<div :class="$style.versionContainer">
<n8n-link @click="onVersionClick" size="small">

View file

@ -234,5 +234,6 @@ export enum VIEWS {
CHANGE_PASSWORD = "ChangePasswordView",
USERS_SETTINGS = "UsersSettings",
PERSONAL_SETTINGS = "PersonalSettings",
API_SETTINGS = "APISettings",
NOT_FOUND = "NotFoundView",
}

View file

@ -647,6 +647,18 @@
"settings.users.usersEmailedError": "Couldn't send invite email",
"settings.users.usersInvited": "Users invited",
"settings.users.usersInvitedError": "Could not invite users",
"settings.api": "API",
"settings.api.create.title": "Set up your API Key",
"settings.api.create.description": "You can use API keys for accessing n8n's",
"settings.api.create.description.link": "REST API",
"settings.api.create.button": "Create an API Key",
"settings.api.create.button.loading": "Creating API Key...",
"settings.api.error.title": "Something went wrong",
"settings.api.error.get": "Could not check if an api key already exists.",
"settings.api.error.create": "Creating the API Key failed.",
"settings.api.error.delete": "Deleting the API Key failed.",
"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.version": "Version",
"showMessage.cancel": "@:_reusableBaseText.cancel",
"showMessage.ok": "OK",

View file

@ -64,6 +64,7 @@ import {
faPencilAlt,
faPlay,
faPlayCircle,
faPlug,
faPlus,
faPlusCircle,
faPlusSquare,
@ -166,6 +167,7 @@ addIcon(faPen);
addIcon(faPencilAlt);
addIcon(faPlay);
addIcon(faPlayCircle);
addIcon(faPlug);
addIcon(faPlus);
addIcon(faPlusCircle);
addIcon(faPlusSquare);

View file

@ -8,6 +8,7 @@ import MainSidebar from '@/components/MainSidebar.vue';
import NodeView from '@/views/NodeView.vue';
import SettingsPersonalView from './views/SettingsPersonalView.vue';
import SettingsUsersView from './views/SettingsUsersView.vue';
import SettingsApiView from './views/SettingsApiView.vue';
import SetupView from './views/SetupView.vue';
import SigninView from './views/SigninView.vue';
import SignupView from './views/SignupView.vue';
@ -360,6 +361,23 @@ const router = new Router({
},
},
},
{
path: '/settings/api',
name: VIEWS.API_SETTINGS,
components: {
default: SettingsApiView,
},
meta: {
telemetry: {
pageCategory: 'settings',
},
permissions: {
allow: {
loginStatus: [LOGIN_STATUS.LoggedIn],
},
},
},
},
{
path: '*',
name: VIEWS.NOT_FOUND,

View file

@ -0,0 +1,124 @@
<template>
<SettingsView>
<div :class="$style.container">
<div :class="$style.header">
<n8n-heading size="2xlarge">
{{ $locale.baseText('settings.api') }}
</n8n-heading>
</div>
<n8n-card v-if="apiKey">
Hello
</n8n-card>
<div :class="$style.placeholder" v-else>
<n8n-heading size="xlarge">
{{ $locale.baseText('settings.api.create.title') }}
</n8n-heading>
<p class="mt-2xs mb-l">
{{$locale.baseText('settings.api.create.description')}}
<a href="https://docs.n8n.io/reference/glossary/#rest-api" target="_blank">
{{$locale.baseText('settings.api.create.description.link')}}
</a>
</p>
<n8n-button :loading="loading" size="large" class="mt-l" @click="createApiKey">
{{$locale.baseText(loading ? 'settings.api.create.button.loading' : 'settings.api.create.button')}}
</n8n-button>
</div>
</div>
</SettingsView>
</template>
<script lang="ts">
import {createApiKey, deleteApiKey, getApiKey } from '../api/api-keys';
import { showMessage } from '@/components/mixins/showMessage';
import { IUser } from '@/Interface';
import mixins from 'vue-typed-mixins';
import SettingsView from './SettingsView.vue';
export default mixins(
showMessage,
).extend({
name: 'SettingsPersonalView',
components: {
SettingsView,
},
data() {
return {
apiKey: '' as string | null,
loading: false,
mounted: false,
error: '',
};
},
async mounted() {
this.getApiKey();
},
computed: {
currentUser() {
return this.$store.getters['users/currentUser'] as IUser;
},
},
methods: {
async getApiKey() {
try {
const { apiKey } = await getApiKey(this.$store.getters['getRestApiContext']);
this.apiKey = apiKey;
} catch (error) {
this.$showError(error, this.$locale.baseText('settings.api.error.get'));
} finally {
this.mounted = true;
}
},
async createApiKey() {
this.loading = true;
try {
const { apiKey } = await createApiKey(this.$store.getters['getRestApiContext']);
this.apiKey = apiKey;
} catch (error) {
this.$showError(error, this.$locale.baseText('settings.api.error.create'));
} finally {
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>
<style lang="scss" module>
.container {
> * {
margin-bottom: var(--spacing-2xl);
}
}
.header {
display: flex;
align-items: center;
white-space: nowrap;
*:first-child {
flex-grow: 1;
}
}
.placeholder {
border-radius: var(--border-radius-xlarge);
border: 2px dashed var(--color-foreground-light);
height: 245px;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
</style>