Files
n8n-enterprise-unlocked/packages/cli/src/UserManagement/routes/auth.ts
कारतोफ्फेलस्क्रिप्ट™ 698d96a617 refactor: Setup typescript project references across workflow, core, and cli (#4519)
* refactor: use consistent folder structure across workflow, core, and cli

* setup typescript project references across workflow, core, and cli
2022-11-09 15:25:00 +01:00

119 lines
3.0 KiB
TypeScript

/* eslint-disable @typescript-eslint/naming-convention */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
import { Request, Response } from 'express';
import { IDataObject } from 'n8n-workflow';
import * as Db from '@/Db';
import * as ResponseHelper from '@/ResponseHelper';
import { AUTH_COOKIE_NAME } from '@/constants';
import { issueCookie, resolveJwt } from '../auth/jwt';
import { N8nApp, PublicUser } from '../Interfaces';
import { compareHash, sanitizeUser } from '../UserManagementHelper';
import { User } from '@db/entities/User';
import type { LoginRequest } from '@/requests';
import config from '@/config';
export function authenticationMethods(this: N8nApp): void {
/**
* Log in a user.
*
* Authless endpoint.
*/
this.app.post(
`/${this.restEndpoint}/login`,
ResponseHelper.send(async (req: LoginRequest, res: Response): Promise<PublicUser> => {
const { email, password } = req.body;
if (!email) {
throw new Error('Email is required to log in');
}
if (!password) {
throw new Error('Password is required to log in');
}
let user: User | undefined;
try {
user = await Db.collections.User.findOne(
{ email },
{
relations: ['globalRole'],
},
);
} catch (error) {
throw new Error('Unable to access database.');
}
if (!user?.password || !(await compareHash(req.body.password, user.password))) {
// password is empty until user signs up
const error = new Error('Wrong username or password. Do you have caps lock on?');
// @ts-ignore
error.httpStatusCode = 401;
throw error;
}
await issueCookie(res, user);
return sanitizeUser(user);
}),
);
/**
* Manually check the `n8n-auth` cookie.
*/
this.app.get(
`/${this.restEndpoint}/login`,
ResponseHelper.send(async (req: Request, res: Response): Promise<PublicUser> => {
// Manually check the existing cookie.
const cookieContents = req.cookies?.[AUTH_COOKIE_NAME] as string | undefined;
let user: User;
if (cookieContents) {
// If logged in, return user
try {
user = await resolveJwt(cookieContents);
return sanitizeUser(user);
} catch (error) {
res.clearCookie(AUTH_COOKIE_NAME);
}
}
if (config.get('userManagement.isInstanceOwnerSetUp')) {
const error = new Error('Not logged in');
// @ts-ignore
error.httpStatusCode = 401;
throw error;
}
try {
user = await Db.collections.User.findOneOrFail({ relations: ['globalRole'] });
} catch (error) {
throw new Error(
'No users found in database - did you wipe the users table? Create at least one user.',
);
}
if (user.email || user.password) {
throw new Error('Invalid database state - user has password set.');
}
await issueCookie(res, user);
return sanitizeUser(user);
}),
);
/**
* Log out a user.
*
* Authless endpoint.
*/
this.app.post(
`/${this.restEndpoint}/logout`,
ResponseHelper.send(async (_, res: Response): Promise<IDataObject> => {
res.clearCookie(AUTH_COOKIE_NAME);
return {
loggedOut: true,
};
}),
);
}