refactor: Remove pre-setup prompt on owner setup (#6495)

This commit is contained in:
कारतोफ्फेलस्क्रिप्ट™ 2023-06-21 13:21:34 +02:00 committed by कारतोफ्फेलस्क्रिप्ट™
parent 0287d5becd
commit abe7f71627
7 changed files with 8 additions and 134 deletions

View file

@ -1,6 +1,6 @@
import validator from 'validator';
import { validateEntity } from '@/GenericHelpers';
import { Authorized, Get, Post, RestController } from '@/decorators';
import { Authorized, Post, RestController } from '@/decorators';
import { BadRequestError } from '@/ResponseHelper';
import {
hashPassword,
@ -13,12 +13,7 @@ import type { ILogger } from 'n8n-workflow';
import type { Config } from '@/config';
import { OwnerRequest } from '@/requests';
import type { IDatabaseCollections, IInternalHooksClass } from '@/Interfaces';
import type {
CredentialsRepository,
SettingsRepository,
UserRepository,
WorkflowRepository,
} from '@db/repositories';
import type { SettingsRepository, UserRepository } from '@db/repositories';
@Authorized(['global', 'owner'])
@RestController('/owner')
@ -33,10 +28,6 @@ export class OwnerController {
private readonly settingsRepository: SettingsRepository;
private readonly credentialsRepository: CredentialsRepository;
private readonly workflowsRepository: WorkflowRepository;
constructor({
config,
logger,
@ -46,28 +37,13 @@ export class OwnerController {
config: Config;
logger: ILogger;
internalHooks: IInternalHooksClass;
repositories: Pick<IDatabaseCollections, 'User' | 'Settings' | 'Credentials' | 'Workflow'>;
repositories: Pick<IDatabaseCollections, 'User' | 'Settings'>;
}) {
this.config = config;
this.logger = logger;
this.internalHooks = internalHooks;
this.userRepository = repositories.User;
this.settingsRepository = repositories.Settings;
this.credentialsRepository = repositories.Credentials;
this.workflowsRepository = repositories.Workflow;
}
@Get('/pre-setup')
async preSetup(): Promise<{ credentials: number; workflows: number }> {
if (this.config.getEnv('userManagement.isInstanceOwnerSetUp')) {
throw new BadRequestError('Instance owner already setup');
}
const [credentials, workflows] = await Promise.all([
this.credentialsRepository.countBy({}),
this.workflowsRepository.countBy({}),
]);
return { credentials, workflows };
}
/**

View file

@ -42,7 +42,6 @@ export const ROUTES_REQUIRING_AUTHORIZATION: Readonly<string[]> = [
'POST /users',
'DELETE /users/123',
'POST /users/123/reinvite',
'GET /owner/pre-setup',
'POST /owner/setup',
];

View file

@ -4,12 +4,7 @@ import type { ILogger } from 'n8n-workflow';
import jwt from 'jsonwebtoken';
import type { IInternalHooksClass } from '@/Interfaces';
import type { User } from '@db/entities/User';
import type {
CredentialsRepository,
SettingsRepository,
UserRepository,
WorkflowRepository,
} from '@db/repositories';
import type { SettingsRepository, UserRepository } from '@db/repositories';
import type { Config } from '@/config';
import { BadRequestError } from '@/ResponseHelper';
import type { OwnerRequest } from '@/requests';
@ -23,8 +18,6 @@ describe('OwnerController', () => {
const internalHooks = mock<IInternalHooksClass>();
const userRepository = mock<UserRepository>();
const settingsRepository = mock<SettingsRepository>();
const credentialsRepository = mock<CredentialsRepository>();
const workflowsRepository = mock<WorkflowRepository>();
const controller = new OwnerController({
config,
logger,
@ -32,29 +25,9 @@ describe('OwnerController', () => {
repositories: {
User: userRepository,
Settings: settingsRepository,
Credentials: credentialsRepository,
Workflow: workflowsRepository,
},
});
describe('preSetup', () => {
it('should throw a BadRequestError if the instance owner is already setup', async () => {
config.getEnv.calledWith('userManagement.isInstanceOwnerSetUp').mockReturnValue(true);
await expect(controller.preSetup()).rejects.toThrowError(
new BadRequestError('Instance owner already setup'),
);
});
it('should a return credential and workflow count', async () => {
config.getEnv.calledWith('userManagement.isInstanceOwnerSetUp').mockReturnValue(false);
credentialsRepository.countBy.mockResolvedValue(7);
workflowsRepository.countBy.mockResolvedValue(31);
const { credentials, workflows } = await controller.preSetup();
expect(credentials).toBe(7);
expect(workflows).toBe(31);
});
});
describe('setupOwner', () => {
it('should throw a BadRequestError if the instance owner is already setup', async () => {
config.getEnv.calledWith('userManagement.isInstanceOwnerSetUp').mockReturnValue(true);

View file

@ -25,12 +25,6 @@ export async function logout(context: IRestApiContext): Promise<void> {
await makeRestApiRequest(context, 'POST', '/logout');
}
export async function preOwnerSetup(
context: IRestApiContext,
): Promise<{ credentials: number; workflows: number }> {
return makeRestApiRequest(context, 'GET', '/owner/pre-setup');
}
export async function setupOwner(
context: IRestApiContext,
params: { firstName: string; lastName: string; email: string; password: string },

View file

@ -90,15 +90,8 @@
"auth.roles.member": "Member",
"auth.roles.owner": "Owner",
"auth.agreement.label": "Inform me about security vulnerabilities if they arise",
"auth.setup.confirmOwnerSetup": "Set up owner account?",
"auth.setup.confirmOwnerSetupMessage": "To give others access to your <b>{entities}</b>, youll need to share these account details with them. Or you can continue as before with no account, by going back and skipping this setup. <a href=\"https://docs.n8n.io/user-management/\" target=\"_blank\">More info</a>",
"auth.setup.createAccount": "Create account",
"auth.setup.goBack": "Go back",
"auth.setup.next": "Next",
"auth.setup.settingUpOwnerError": "Problem setting up owner",
"auth.setup.setupConfirmation.concatEntities": "{workflows} and {credentials}",
"auth.setup.setupConfirmation.credentials": "{count} credential | {count} credentials",
"auth.setup.setupConfirmation.existingWorkflows": "{count} existing workflow | {count} existing workflows",
"auth.setup.setupOwner": "Set up owner account",
"auth.signin": "Sign in",
"auth.signin.error": "Problem logging in",

View file

@ -8,7 +8,6 @@ import {
login,
loginCurrentUser,
logout,
preOwnerSetup,
reinvite,
sendForgotPasswordEmail,
setupOwner,
@ -185,9 +184,6 @@ export const useUsersStore = defineStore(STORES.USERS, {
this.currentUserId = null;
usePostHog().reset();
},
async preOwnerSetup() {
return preOwnerSetup(useRootStore().getRestApiContext);
},
async createOwner(params: {
firstName: string;
lastName: string;

View file

@ -11,14 +11,13 @@
import AuthView from './AuthView.vue';
import { defineComponent } from 'vue';
import { useToast, useMessage } from '@/composables';
import { useToast } from '@/composables';
import type { IFormBoxConfig } from '@/Interface';
import { MODAL_CONFIRM, VIEWS } from '@/constants';
import { VIEWS } from '@/constants';
import { mapStores } from 'pinia';
import { useUIStore } from '@/stores/ui.store';
import { useSettingsStore } from '@/stores/settings.store';
import { useUsersStore } from '@/stores/users.store';
import { useCredentialsStore } from '@/stores/credentials.store';
export default defineComponent({
name: 'SetupView',
@ -26,15 +25,7 @@ export default defineComponent({
AuthView,
},
setup() {
return {
...useToast(),
...useMessage(),
};
},
async mounted() {
const { credentials, workflows } = await this.usersStore.preOwnerSetup();
this.credentialsCount = credentials;
this.workflowsCount = workflows;
return useToast();
},
data() {
const FORM_CONFIG: IFormBoxConfig = {
@ -97,62 +88,14 @@ export default defineComponent({
return {
FORM_CONFIG,
loading: false,
workflowsCount: 0,
credentialsCount: 0,
};
},
computed: {
...mapStores(useCredentialsStore, useSettingsStore, useUIStore, useUsersStore),
...mapStores(useSettingsStore, useUIStore, useUsersStore),
},
methods: {
async confirmSetupOrGoBack(): Promise<boolean> {
if (this.workflowsCount === 0 && this.credentialsCount === 0) {
return true;
}
const workflows =
this.workflowsCount > 0
? this.$locale.baseText('auth.setup.setupConfirmation.existingWorkflows', {
adjustToNumber: this.workflowsCount,
})
: '';
const credentials =
this.credentialsCount > 0
? this.$locale.baseText('auth.setup.setupConfirmation.credentials', {
adjustToNumber: this.credentialsCount,
})
: '';
const entities =
workflows && credentials
? this.$locale.baseText('auth.setup.setupConfirmation.concatEntities', {
interpolate: { workflows, credentials },
})
: workflows || credentials;
const confirm = await this.confirm(
this.$locale.baseText('auth.setup.confirmOwnerSetupMessage', {
interpolate: {
entities,
},
}),
this.$locale.baseText('auth.setup.confirmOwnerSetup'),
{
dangerouslyUseHTMLString: true,
confirmButtonText: this.$locale.baseText('auth.setup.createAccount'),
cancelButtonText: this.$locale.baseText('auth.setup.goBack'),
},
);
return confirm === MODAL_CONFIRM;
},
async onSubmit(values: { [key: string]: string | boolean }) {
try {
const confirmSetup = await this.confirmSetupOrGoBack();
if (!confirmSetup) {
return;
}
const forceRedirectedHere = this.settingsStore.showSetupPage;
this.loading = true;
await this.usersStore.createOwner(