|
|
@ -1,11 +1,17 @@ |
|
|
|
import { Router } from 'express'; |
|
|
|
import { Router } from 'express'; |
|
|
|
|
|
|
|
import { v4 as uuidv4 } from 'uuid'; |
|
|
|
|
|
|
|
import validator from 'validator'; |
|
|
|
import { OrgUserRoles } from '../../../enums/OrgUserRoles'; |
|
|
|
import { OrgUserRoles } from '../../../enums/OrgUserRoles'; |
|
|
|
|
|
|
|
import Audit from '../../models/Audit'; |
|
|
|
import User from '../../models/User'; |
|
|
|
import User from '../../models/User'; |
|
|
|
import { metaApiMetrics } from '../helpers/apiMetrics'; |
|
|
|
import { metaApiMetrics } from '../helpers/apiMetrics'; |
|
|
|
import { NcError } from '../helpers/catchError'; |
|
|
|
import { NcError } from '../helpers/catchError'; |
|
|
|
import { extractProps } from '../helpers/extractProps'; |
|
|
|
import { extractProps } from '../helpers/extractProps'; |
|
|
|
import ncMetaAclMw from '../helpers/ncMetaAclMw'; |
|
|
|
import ncMetaAclMw from '../helpers/ncMetaAclMw'; |
|
|
|
import { PagedResponseImpl } from '../helpers/PagedResponse'; |
|
|
|
import { PagedResponseImpl } from '../helpers/PagedResponse'; |
|
|
|
|
|
|
|
import { randomTokenString } from '../helpers/stringHelpers'; |
|
|
|
|
|
|
|
import { Tele } from 'nc-help'; |
|
|
|
|
|
|
|
import { sendInviteEmail } from './projectUserApis'; |
|
|
|
|
|
|
|
|
|
|
|
async function userList(req, res) { |
|
|
|
async function userList(req, res) { |
|
|
|
res.json( |
|
|
|
res.json( |
|
|
@ -38,8 +44,90 @@ async function userDelete(req, res) { |
|
|
|
res.json(await User.delete(req.params.userId)); |
|
|
|
res.json(await User.delete(req.params.userId)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
async function userAdd(_req, _res) { |
|
|
|
async function userAdd(req, res, next) { |
|
|
|
NcError.notImplemented(); |
|
|
|
// allow only viewer or creator role
|
|
|
|
|
|
|
|
if ( |
|
|
|
|
|
|
|
req.body.roles && |
|
|
|
|
|
|
|
![OrgUserRoles.VIEWER, OrgUserRoles.CREATOR].includes(req.body.roles) |
|
|
|
|
|
|
|
) { |
|
|
|
|
|
|
|
NcError.badRequest('Invalid role'); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// extract emails from request body
|
|
|
|
|
|
|
|
const emails = (req.body.email || '') |
|
|
|
|
|
|
|
.toLowerCase() |
|
|
|
|
|
|
|
.split(/\s*,\s*/) |
|
|
|
|
|
|
|
.map((v) => v.trim()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// check for invalid emails
|
|
|
|
|
|
|
|
const invalidEmails = emails.filter((v) => !validator.isEmail(v)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!emails.length) { |
|
|
|
|
|
|
|
return NcError.badRequest('Invalid email address'); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (invalidEmails.length) { |
|
|
|
|
|
|
|
NcError.badRequest('Invalid email address : ' + invalidEmails.join(', ')); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const invite_token = uuidv4(); |
|
|
|
|
|
|
|
const error = []; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (const email of emails) { |
|
|
|
|
|
|
|
// add user to project if user already exist
|
|
|
|
|
|
|
|
const user = await User.getByEmail(email); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (user) { |
|
|
|
|
|
|
|
NcError.badRequest('User already exist'); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
// create new user with invite token
|
|
|
|
|
|
|
|
await User.insert({ |
|
|
|
|
|
|
|
invite_token, |
|
|
|
|
|
|
|
invite_token_expires: new Date(Date.now() + 24 * 60 * 60 * 1000), |
|
|
|
|
|
|
|
email, |
|
|
|
|
|
|
|
roles: OrgUserRoles.VIEWER, |
|
|
|
|
|
|
|
token_version: randomTokenString(), |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const count = await User.count(); |
|
|
|
|
|
|
|
Tele.emit('evt', { evt_type: 'org:user:invite', count }); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
await Audit.insert({ |
|
|
|
|
|
|
|
project_id: req.params.projectId, |
|
|
|
|
|
|
|
op_type: 'AUTHENTICATION', |
|
|
|
|
|
|
|
op_sub_type: 'INVITE', |
|
|
|
|
|
|
|
user: req.user.email, |
|
|
|
|
|
|
|
description: `invited ${email} to ${req.params.projectId} project `, |
|
|
|
|
|
|
|
ip: req.clientIp, |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
// in case of single user check for smtp failure
|
|
|
|
|
|
|
|
// and send back token if failed
|
|
|
|
|
|
|
|
if ( |
|
|
|
|
|
|
|
emails.length === 1 && |
|
|
|
|
|
|
|
!(await sendInviteEmail(email, invite_token, req)) |
|
|
|
|
|
|
|
) { |
|
|
|
|
|
|
|
return res.json({ invite_token, email }); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
sendInviteEmail(email, invite_token, req); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} catch (e) { |
|
|
|
|
|
|
|
console.log(e); |
|
|
|
|
|
|
|
if (emails.length === 1) { |
|
|
|
|
|
|
|
return next(e); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
error.push({ email, error: e.message }); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (emails.length === 1) { |
|
|
|
|
|
|
|
res.json({ |
|
|
|
|
|
|
|
msg: 'success', |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
return res.json({ invite_token, emails, error }); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const router = Router({ mergeParams: true }); |
|
|
|
const router = Router({ mergeParams: true }); |
|
|
@ -56,11 +144,11 @@ router.patch( |
|
|
|
router.delete( |
|
|
|
router.delete( |
|
|
|
'/api/v1/users/:userId', |
|
|
|
'/api/v1/users/:userId', |
|
|
|
metaApiMetrics, |
|
|
|
metaApiMetrics, |
|
|
|
ncMetaAclMw(userAdd, 'userAdd', [OrgUserRoles.SUPER]) |
|
|
|
ncMetaAclMw(userDelete, 'userAdd', [OrgUserRoles.SUPER]) |
|
|
|
); |
|
|
|
); |
|
|
|
router.post( |
|
|
|
router.post( |
|
|
|
'/api/v1/users/:userId', |
|
|
|
'/api/v1/users', |
|
|
|
metaApiMetrics, |
|
|
|
metaApiMetrics, |
|
|
|
ncMetaAclMw(userDelete, 'userDelete', [OrgUserRoles.SUPER]) |
|
|
|
ncMetaAclMw(userAdd, 'userDelete', [OrgUserRoles.SUPER]) |
|
|
|
); |
|
|
|
); |
|
|
|
export default router; |
|
|
|
export default router; |
|
|
|