Browse Source

refactor: update useApis content

Signed-off-by: Pranav C <pranavxc@gmail.com>
pull/5239/head
Pranav C 2 years ago
parent
commit
40689609fb
  1. 315
      packages/nocodb/src/lib/controllers/userController/userApis.ts

315
packages/nocodb/src/lib/controllers/userController/userApis.ts

@ -1,82 +1,24 @@
import { Request, Response } from 'express';
import { TableType, validatePassword } from 'nocodb-sdk';
import { OrgUserRoles } from 'nocodb-sdk';
import { NC_APP_SETTINGS } from '../../../constants';
import Store from '../../../models/Store';
import { T } from 'nc-help';
import catchError, { NcError } from '../../helpers/catchError';
const { isEmail } = require('validator');
import * as ejs from 'ejs';
import bcrypt from 'bcryptjs';
import { promisify } from 'util';
import User from '../../../models/User';
const { v4: uuidv4 } = require('uuid');
import Audit from '../../../models/Audit';
import NcPluginMgrv2 from '../../helpers/NcPluginMgrv2';
import passport from 'passport';
import extractProjectIdAndAuthenticate from '../../helpers/extractProjectIdAndAuthenticate';
import ncMetaAclMw from '../../helpers/ncMetaAclMw';
import { MetaTable } from '../../../utils/globals';
import Noco from '../../../Noco';
import { getAjvValidatorMw } from '../helpers';
import { genJwt } from './helpers';
import { randomTokenString } from '../../helpers/stringHelpers';
export async function registerNewUserIfAllowed({
firstname,
lastname,
email,
salt,
password,
email_verification_token,
}: {
firstname;
lastname;
email: string;
salt: any;
password;
email_verification_token;
}) {
let roles: string = OrgUserRoles.CREATOR;
if (await User.isFirst()) {
roles = `${OrgUserRoles.CREATOR},${OrgUserRoles.SUPER_ADMIN}`;
// todo: update in nc_store
// roles = 'owner,creator,editor'
T.emit('evt', {
evt_type: 'project:invite',
count: 1,
});
} else {
let settings: { invite_only_signup?: boolean } = {};
try {
settings = JSON.parse((await Store.get(NC_APP_SETTINGS))?.value);
} catch {}
if (settings?.invite_only_signup) {
NcError.badRequest('Not allowed to signup, contact super admin.');
} else {
roles = OrgUserRoles.VIEWER;
}
}
const token_version = randomTokenString();
return await User.insert({
firstname,
lastname,
email,
salt,
password,
email_verification_token,
roles,
token_version,
});
}
import { getAjvValidatorMw } from '../../meta/api/helpers';
import catchError, { NcError } from '../../meta/helpers/catchError';
import extractProjectIdAndAuthenticate from '../../meta/helpers/extractProjectIdAndAuthenticate';
import ncMetaAclMw from '../../meta/helpers/ncMetaAclMw';
import NcPluginMgrv2 from '../../meta/helpers/NcPluginMgrv2';
import { Audit, User } from '../../models';
import Noco from '../../Noco';
import { userService } from '../../services';
export async function signup(req: Request, res: Response<TableType>) {
const {
@ -141,7 +83,7 @@ export async function signup(req: Request, res: Response<TableType>) {
NcError.badRequest('User already exist');
}
} else {
await registerNewUserIfAllowed({
await userService.registerNewUserIfAllowed({
firstname,
lastname,
email,
@ -171,7 +113,7 @@ export async function signup(req: Request, res: Response<TableType>) {
);
}
await promisify((req as any).login.bind(req))(user);
const refreshToken = randomTokenString();
const refreshToken = userService.randomTokenString();
await User.update(user.id, {
refresh_token: refreshToken,
email: user.email,
@ -190,18 +132,18 @@ export async function signup(req: Request, res: Response<TableType>) {
});
res.json({
token: genJwt(user, Noco.getConfig()),
token: userService.genJwt(user, Noco.getConfig()),
} as any);
}
async function successfulSignIn({
user,
err,
info,
req,
res,
auditDescription,
}) {
user,
err,
info,
req,
res,
auditDescription,
}) {
try {
if (!user || !user.email) {
if (err) {
@ -214,10 +156,10 @@ async function successfulSignIn({
}
await promisify((req as any).login.bind(req))(user);
const refreshToken = randomTokenString();
const refreshToken = userService.randomTokenString();
if (!user.token_version) {
user.token_version = randomTokenString();
user.token_version = userService.randomTokenString();
}
await User.update(user.id, {
@ -236,7 +178,7 @@ async function successfulSignIn({
});
res.json({
token: genJwt(user, Noco.getConfig()),
token: userService.genJwt(user, Noco.getConfig()),
} as any);
} catch (e) {
console.log(e);
@ -279,15 +221,13 @@ async function googleSignin(req, res, next) {
)(req, res, next);
}
const REFRESH_TOKEN_COOKIE_KEY = 'refresh_token';
function setTokenCookie(res, token): void {
function setTokenCookie(res: Response, token): void {
// create http only cookie with refresh token that expires in 7 days
const cookieOptions = {
httpOnly: true,
expires: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
};
res.cookie(REFRESH_TOKEN_COOKIE_KEY, token, cookieOptions);
res.cookie('refresh_token', token, cookieOptions);
}
async function me(req, res): Promise<any> {
@ -298,184 +238,47 @@ async function passwordChange(req: Request<any, any>, res): Promise<any> {
if (!(req as any).isAuthenticated()) {
NcError.forbidden('Not allowed');
}
const { currentPassword, newPassword } = req.body;
if (!currentPassword || !newPassword) {
return NcError.badRequest('Missing new/old password');
}
// validate password and throw error if password is satisfying the conditions
const { valid, error } = validatePassword(newPassword);
if (!valid) {
NcError.badRequest(`Password : ${error}`);
}
const user = await User.getByEmail((req as any).user.email);
const hashedPassword = await promisify(bcrypt.hash)(
currentPassword,
user.salt
);
if (hashedPassword !== user.password) {
return NcError.badRequest('Current password is wrong');
}
const salt = await promisify(bcrypt.genSalt)(10);
const password = await promisify(bcrypt.hash)(newPassword, salt);
await User.update(user.id, {
salt,
password,
email: user.email,
token_version: null,
});
await Audit.insert({
op_type: 'AUTHENTICATION',
op_sub_type: 'PASSWORD_CHANGE',
user: user.email,
description: `changed password `,
ip: (req as any).clientIp,
await userService.passwordChange({
user: req['user'],
req,
body: req.body,
});
res.json({ msg: 'Password updated successfully' });
}
async function passwordForgot(req: Request<any, any>, res): Promise<any> {
const _email = req.body.email;
if (!_email) {
NcError.badRequest('Please enter your email address.');
}
const email = _email.toLowerCase();
const user = await User.getByEmail(email);
if (user) {
const token = uuidv4();
await User.update(user.id, {
email: user.email,
reset_password_token: token,
reset_password_expires: new Date(Date.now() + 60 * 60 * 1000),
token_version: null,
});
try {
const template = (await import('./ui/emailTemplates/forgotPassword'))
.default;
await NcPluginMgrv2.emailAdapter().then((adapter) =>
adapter.mailSend({
to: user.email,
subject: 'Password Reset Link',
text: `Visit following link to update your password : ${
(req as any).ncSiteUrl
}/auth/password/reset/${token}.`,
html: ejs.render(template, {
resetLink: (req as any).ncSiteUrl + `/auth/password/reset/${token}`,
}),
})
);
} catch (e) {
console.log(e);
return NcError.badRequest(
'Email Plugin is not found. Please contact administrators to configure it in App Store first.'
);
}
await userService.passwordForgot({
siteUrl: (req as any).ncSiteUrl,
body: req.body,
req,
});
await Audit.insert({
op_type: 'AUTHENTICATION',
op_sub_type: 'PASSWORD_FORGOT',
user: user.email,
description: `requested for password reset `,
ip: (req as any).clientIp,
});
} else {
return NcError.badRequest('Your email has not been registered.');
}
res.json({ msg: 'Please check your email to reset the password' });
}
async function tokenValidate(req, res): Promise<any> {
const token = req.params.tokenId;
const user = await Noco.ncMeta.metaGet(null, null, MetaTable.USERS, {
reset_password_token: token,
await userService.tokenValidate({
token: req.params.tokenId,
});
if (!user || !user.email) {
NcError.badRequest('Invalid reset url');
}
if (new Date(user.reset_password_expires) < new Date()) {
NcError.badRequest('Password reset url expired');
}
res.json(true);
}
async function passwordReset(req, res): Promise<any> {
const token = req.params.tokenId;
const user = await Noco.ncMeta.metaGet(null, null, MetaTable.USERS, {
reset_password_token: token,
});
if (!user) {
NcError.badRequest('Invalid reset url');
}
if (user.reset_password_expires < new Date()) {
NcError.badRequest('Password reset url expired');
}
if (user.provider && user.provider !== 'local') {
NcError.badRequest('Email registered via social account');
}
// validate password and throw error if password is satisfying the conditions
const { valid, error } = validatePassword(req.body.password);
if (!valid) {
NcError.badRequest(`Password : ${error}`);
}
const salt = await promisify(bcrypt.genSalt)(10);
const password = await promisify(bcrypt.hash)(req.body.password, salt);
await User.update(user.id, {
salt,
password,
email: user.email,
reset_password_expires: null,
reset_password_token: '',
token_version: null,
});
await Audit.insert({
op_type: 'AUTHENTICATION',
op_sub_type: 'PASSWORD_RESET',
user: user.email,
description: `did reset password `,
ip: req.clientIp,
await userService.passwordReset({
token: req.params.tokenId,
body: req.body,
req,
});
res.json({ msg: 'Password reset successful' });
}
async function emailVerification(req, res): Promise<any> {
const token = req.params.tokenId;
const user = await Noco.ncMeta.metaGet(null, null, MetaTable.USERS, {
email_verification_token: token,
});
if (!user) {
NcError.badRequest('Invalid verification url');
}
await User.update(user.id, {
email: user.email,
email_verification_token: '',
email_verified: true,
});
await Audit.insert({
op_type: 'AUTHENTICATION',
op_sub_type: 'EMAIL_VERIFICATION',
user: user.email,
description: `verified email `,
ip: req.clientIp,
await userService.emailVerification({
token: req.params.tokenId,
req,
});
res.json({ msg: 'Email verified successfully' });
@ -487,15 +290,13 @@ async function refreshToken(req, res): Promise<any> {
return res.status(400).json({ msg: 'Missing refresh token' });
}
const user = await User.getByRefreshToken(
req.cookies[REFRESH_TOKEN_COOKIE_KEY]
);
const user = await User.getByRefreshToken(req.cookies.refresh_token);
if (!user) {
return res.status(400).json({ msg: 'Invalid refresh token' });
}
const refreshToken = randomTokenString();
const refreshToken = userService.randomTokenString();
await User.update(user.id, {
email: user.email,
@ -505,7 +306,7 @@ async function refreshToken(req, res): Promise<any> {
setTokenCookie(res, refreshToken);
res.json({
token: genJwt(user, Noco.getConfig()),
token: userService.genJwt(user, Noco.getConfig()),
} as any);
} catch (e) {
return res.status(400).json({ msg: e.message });
@ -526,30 +327,6 @@ async function renderPasswordReset(req, res): Promise<any> {
}
}
// clear refresh token cookie and update user refresh token to null
const signout = async (req, res): Promise<any> => {
const resBody = { msg: 'Success' };
if (!req.cookies[REFRESH_TOKEN_COOKIE_KEY]) {
return res.json(resBody);
}
const user = await User.getByRefreshToken(
req.cookies[REFRESH_TOKEN_COOKIE_KEY]
);
if (!user) {
return res.json(resBody);
}
res.clearCookie(REFRESH_TOKEN_COOKIE_KEY);
await User.update(user.id, {
refresh_token: null,
});
res.json(resBody);
};
const mapRoutes = (router) => {
// todo: old api - /auth/signup?tool=1
router.post(
@ -562,7 +339,6 @@ const mapRoutes = (router) => {
getAjvValidatorMw('swagger.json#/components/schemas/SignInReq'),
catchError(signin)
);
router.post('/auth/user/signout', catchError(signout));
router.get('/auth/user/me', extractProjectIdAndAuthenticate, catchError(me));
router.post(
'/auth/password/forgot',
@ -651,7 +427,6 @@ const mapRoutes = (router) => {
getAjvValidatorMw('swagger.json#/components/schemas/SignInReq'),
catchError(signin)
);
router.post('/api/v1/auth/user/signout', catchError(signout));
router.get(
'/api/v1/auth/user/me',
extractProjectIdAndAuthenticate,
@ -683,4 +458,4 @@ const mapRoutes = (router) => {
// respond with password reset page
router.get('/auth/password/reset/:tokenId', catchError(renderPasswordReset));
};
export { mapRoutes as userApis };
export { mapRoutes as userController };

Loading…
Cancel
Save