2021-04-27 09:16:44 +02:00
|
|
|
import { Request, Response } from 'express';
|
2021-04-09 13:46:53 +02:00
|
|
|
import Controller from '../controller';
|
2021-12-03 12:46:50 +01:00
|
|
|
import { ADMIN, NONE } from '../../types/permissions';
|
2021-04-09 13:46:53 +02:00
|
|
|
import UserService from '../../services/user-service';
|
2021-04-16 15:29:23 +02:00
|
|
|
import { AccessService } from '../../services/access-service';
|
2021-04-09 13:46:53 +02:00
|
|
|
import { Logger } from '../../logger';
|
2021-04-22 10:07:10 +02:00
|
|
|
import { IUnleashConfig } from '../../types/option';
|
2021-04-27 20:47:11 +02:00
|
|
|
import { EmailService } from '../../services/email-service';
|
2021-04-23 10:58:47 +02:00
|
|
|
import ResetTokenService from '../../services/reset-token-service';
|
2021-04-27 09:05:46 +02:00
|
|
|
import { IUnleashServices } from '../../types/services';
|
2021-04-27 09:16:44 +02:00
|
|
|
import SessionService from '../../services/session-service';
|
2021-08-12 15:04:37 +02:00
|
|
|
import { IAuthRequest } from '../unleash-types';
|
2021-04-16 15:29:23 +02:00
|
|
|
|
2021-08-13 10:50:48 +02:00
|
|
|
interface ICreateUserBody {
|
|
|
|
username: string;
|
|
|
|
email: string;
|
|
|
|
name: string;
|
|
|
|
rootRole: number;
|
|
|
|
sendEmail: boolean;
|
|
|
|
}
|
|
|
|
|
2021-04-22 10:07:10 +02:00
|
|
|
export default class UserAdminController extends Controller {
|
2021-04-09 13:46:53 +02:00
|
|
|
private userService: UserService;
|
|
|
|
|
|
|
|
private accessService: AccessService;
|
|
|
|
|
2021-04-22 10:07:10 +02:00
|
|
|
private readonly logger: Logger;
|
2021-04-09 13:46:53 +02:00
|
|
|
|
2021-04-23 10:58:47 +02:00
|
|
|
private emailService: EmailService;
|
|
|
|
|
|
|
|
private resetTokenService: ResetTokenService;
|
|
|
|
|
2021-04-27 09:16:44 +02:00
|
|
|
private sessionService: SessionService;
|
|
|
|
|
2021-04-23 10:58:47 +02:00
|
|
|
constructor(
|
|
|
|
config: IUnleashConfig,
|
2021-04-27 09:05:46 +02:00
|
|
|
{
|
|
|
|
userService,
|
|
|
|
accessService,
|
|
|
|
emailService,
|
|
|
|
resetTokenService,
|
2021-04-27 09:16:44 +02:00
|
|
|
sessionService,
|
2021-04-27 09:05:46 +02:00
|
|
|
}: Pick<
|
2021-05-11 12:15:20 +02:00
|
|
|
IUnleashServices,
|
|
|
|
| 'userService'
|
|
|
|
| 'accessService'
|
|
|
|
| 'emailService'
|
|
|
|
| 'resetTokenService'
|
|
|
|
| 'sessionService'
|
2021-04-27 09:05:46 +02:00
|
|
|
>,
|
2021-04-23 10:58:47 +02:00
|
|
|
) {
|
2021-04-09 13:46:53 +02:00
|
|
|
super(config);
|
|
|
|
this.userService = userService;
|
|
|
|
this.accessService = accessService;
|
2021-04-23 10:58:47 +02:00
|
|
|
this.emailService = emailService;
|
2021-04-27 20:47:11 +02:00
|
|
|
this.logger = config.getLogger('routes/user-controller.ts');
|
2021-04-23 10:58:47 +02:00
|
|
|
this.resetTokenService = resetTokenService;
|
2021-04-27 09:16:44 +02:00
|
|
|
this.sessionService = sessionService;
|
2021-04-09 13:46:53 +02:00
|
|
|
|
2021-04-22 12:13:41 +02:00
|
|
|
this.get('/', this.getUsers, ADMIN);
|
2021-04-09 13:46:53 +02:00
|
|
|
this.get('/search', this.search);
|
|
|
|
this.post('/', this.createUser, ADMIN);
|
2021-12-03 12:46:50 +01:00
|
|
|
this.post('/validate-password', this.validatePassword, NONE);
|
2021-10-28 14:24:09 +02:00
|
|
|
this.get('/:id', this.getUser, ADMIN);
|
2021-04-09 13:46:53 +02:00
|
|
|
this.put('/:id', this.updateUser, ADMIN);
|
|
|
|
this.post('/:id/change-password', this.changePassword, ADMIN);
|
|
|
|
this.delete('/:id', this.deleteUser, ADMIN);
|
2021-12-03 12:46:50 +01:00
|
|
|
this.post('/reset-password', this.resetPassword, ADMIN);
|
2021-04-27 09:16:44 +02:00
|
|
|
this.get('/active-sessions', this.getActiveSessions, ADMIN);
|
2021-04-16 15:29:23 +02:00
|
|
|
}
|
|
|
|
|
2021-04-22 10:07:10 +02:00
|
|
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
|
|
|
async resetPassword(req, res): Promise<void> {
|
2021-04-27 20:47:11 +02:00
|
|
|
const { user } = req;
|
2021-09-13 10:23:57 +02:00
|
|
|
const receiver = req.body.id;
|
|
|
|
const resetPasswordUrl =
|
|
|
|
await this.userService.createResetPasswordEmail(receiver, user);
|
|
|
|
res.json({ resetPasswordUrl });
|
2021-04-09 13:46:53 +02:00
|
|
|
}
|
|
|
|
|
2021-04-22 10:07:10 +02:00
|
|
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
2021-08-12 15:04:37 +02:00
|
|
|
async getUsers(req: Request, res: Response): Promise<void> {
|
2021-04-09 13:46:53 +02:00
|
|
|
try {
|
|
|
|
const users = await this.userService.getAll();
|
|
|
|
const rootRoles = await this.accessService.getRootRoles();
|
2021-08-12 15:04:37 +02:00
|
|
|
const inviteLinks =
|
|
|
|
await this.resetTokenService.getActiveInvitations();
|
2021-04-23 10:58:47 +02:00
|
|
|
|
2021-08-12 15:04:37 +02:00
|
|
|
const usersWithInviteLinks = users.map((user) => {
|
2021-04-23 10:58:47 +02:00
|
|
|
const inviteLink = inviteLinks[user.id] || '';
|
|
|
|
return { ...user, inviteLink };
|
|
|
|
});
|
2021-04-09 13:46:53 +02:00
|
|
|
|
2021-04-23 10:58:47 +02:00
|
|
|
res.json({ users: usersWithInviteLinks, rootRoles });
|
2021-04-09 13:46:53 +02:00
|
|
|
} catch (error) {
|
|
|
|
this.logger.error(error);
|
|
|
|
res.status(500).send({ msg: 'server errors' });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-27 09:16:44 +02:00
|
|
|
async getActiveSessions(req: Request, res: Response): Promise<void> {
|
2021-09-13 10:23:57 +02:00
|
|
|
const sessions = await this.sessionService.getActiveSessions();
|
|
|
|
res.json(sessions);
|
2021-04-27 09:16:44 +02:00
|
|
|
}
|
|
|
|
|
2021-04-22 10:07:10 +02:00
|
|
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
2021-08-12 15:04:37 +02:00
|
|
|
async search(req: Request, res: Response): Promise<void> {
|
|
|
|
const { q } = req.query as any;
|
2021-04-09 13:46:53 +02:00
|
|
|
try {
|
|
|
|
const users =
|
|
|
|
q && q.length > 1 ? await this.userService.search(q) : [];
|
|
|
|
res.json(users);
|
|
|
|
} catch (error) {
|
|
|
|
this.logger.error(error);
|
|
|
|
res.status(500).send({ msg: 'server errors' });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-28 14:24:09 +02:00
|
|
|
async getUser(req: Request, res: Response): Promise<void> {
|
|
|
|
const { id } = req.params;
|
|
|
|
const user = await this.userService.getUser(Number(id));
|
|
|
|
res.json(user);
|
|
|
|
}
|
|
|
|
|
2021-04-22 10:07:10 +02:00
|
|
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
2021-08-13 10:50:48 +02:00
|
|
|
async createUser(
|
|
|
|
req: IAuthRequest<any, any, ICreateUserBody, any>,
|
|
|
|
res: Response,
|
|
|
|
): Promise<void> {
|
|
|
|
const { username, email, name, rootRole, sendEmail } = req.body;
|
2021-04-23 10:58:47 +02:00
|
|
|
const { user } = req;
|
2021-04-09 13:46:53 +02:00
|
|
|
|
|
|
|
try {
|
2021-04-27 20:47:11 +02:00
|
|
|
const createdUser = await this.userService.createUser(
|
|
|
|
{
|
|
|
|
username,
|
|
|
|
email,
|
|
|
|
name,
|
2021-05-18 13:22:28 +02:00
|
|
|
rootRole,
|
2021-04-27 20:47:11 +02:00
|
|
|
},
|
|
|
|
user,
|
|
|
|
);
|
2021-04-23 10:58:47 +02:00
|
|
|
const inviteLink = await this.resetTokenService.createNewUserUrl(
|
|
|
|
createdUser.id,
|
|
|
|
user.email,
|
|
|
|
);
|
|
|
|
|
2021-05-11 12:15:20 +02:00
|
|
|
let emailSent = false;
|
2021-04-23 10:58:47 +02:00
|
|
|
const emailConfigured = this.emailService.configured();
|
2021-08-13 10:50:48 +02:00
|
|
|
const reallySendEmail =
|
|
|
|
emailConfigured && (sendEmail !== undefined ? sendEmail : true);
|
|
|
|
if (reallySendEmail) {
|
2021-05-11 12:15:20 +02:00
|
|
|
try {
|
|
|
|
await this.emailService.sendGettingStartedMail(
|
|
|
|
createdUser.name,
|
|
|
|
createdUser.email,
|
|
|
|
inviteLink.toString(),
|
|
|
|
);
|
|
|
|
emailSent = true;
|
|
|
|
} catch (e) {
|
|
|
|
this.logger.warn(
|
|
|
|
'email was configured, but sending failed due to: ',
|
|
|
|
e,
|
|
|
|
);
|
|
|
|
}
|
2021-04-23 10:58:47 +02:00
|
|
|
} else {
|
|
|
|
this.logger.warn(
|
|
|
|
'email was not sent to the user because email configuration is lacking',
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
res.status(201).send({
|
|
|
|
...createdUser,
|
|
|
|
inviteLink,
|
2021-05-11 12:15:20 +02:00
|
|
|
emailSent,
|
2021-04-23 10:58:47 +02:00
|
|
|
rootRole,
|
|
|
|
});
|
2021-04-09 13:46:53 +02:00
|
|
|
} catch (e) {
|
|
|
|
this.logger.warn(e.message);
|
|
|
|
res.status(400).send([{ msg: e.message }]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-12 15:04:37 +02:00
|
|
|
async updateUser(req: IAuthRequest, res: Response): Promise<void> {
|
2021-04-27 20:47:11 +02:00
|
|
|
const { user, params, body } = req;
|
|
|
|
|
|
|
|
const { id } = params;
|
|
|
|
const { name, email, rootRole } = body;
|
2021-04-09 13:46:53 +02:00
|
|
|
|
|
|
|
try {
|
2021-04-27 20:47:11 +02:00
|
|
|
const updateUser = await this.userService.updateUser(
|
|
|
|
{
|
|
|
|
id: Number(id),
|
|
|
|
name,
|
|
|
|
email,
|
2021-05-18 13:22:28 +02:00
|
|
|
rootRole,
|
2021-04-27 20:47:11 +02:00
|
|
|
},
|
|
|
|
user,
|
|
|
|
);
|
|
|
|
res.status(200).send({ ...updateUser, rootRole });
|
2021-04-09 13:46:53 +02:00
|
|
|
} catch (e) {
|
|
|
|
this.logger.warn(e.message);
|
|
|
|
res.status(400).send([{ msg: e.message }]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-12 15:04:37 +02:00
|
|
|
async deleteUser(req: IAuthRequest, res: Response): Promise<void> {
|
2021-04-27 20:47:11 +02:00
|
|
|
const { user, params } = req;
|
|
|
|
const { id } = params;
|
2021-04-09 13:46:53 +02:00
|
|
|
|
2021-09-13 10:23:57 +02:00
|
|
|
await this.userService.deleteUser(+id, user);
|
|
|
|
res.status(200).send();
|
2021-04-09 13:46:53 +02:00
|
|
|
}
|
|
|
|
|
2021-08-12 15:04:37 +02:00
|
|
|
async validatePassword(req: IAuthRequest, res: Response): Promise<void> {
|
2021-04-09 13:46:53 +02:00
|
|
|
const { password } = req.body;
|
|
|
|
|
2021-09-13 10:23:57 +02:00
|
|
|
this.userService.validatePassword(password);
|
|
|
|
res.status(200).send();
|
2021-04-09 13:46:53 +02:00
|
|
|
}
|
|
|
|
|
2021-08-12 15:04:37 +02:00
|
|
|
async changePassword(req: IAuthRequest, res: Response): Promise<void> {
|
2021-04-09 13:46:53 +02:00
|
|
|
const { id } = req.params;
|
|
|
|
const { password } = req.body;
|
|
|
|
|
2021-09-13 10:23:57 +02:00
|
|
|
await this.userService.changePassword(+id, password);
|
|
|
|
res.status(200).send();
|
2021-04-09 13:46:53 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = UserAdminController;
|