@fdm-monster/server
Version:
FDM Monster is a bulk OctoPrint manager to set up, configure and monitor 3D printers. Our aim is to provide extremely optimized websocket performance and reliability.
179 lines (178 loc) • 7.1 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "UserService", {
enumerable: true,
get: function() {
return UserService;
}
});
const _baseservice = require("./base.service");
const _userdto = require("../interfaces/user.dto");
const _entities = require("../../entities");
const _typeorm = require("typeorm");
const _runtimeexceptions = require("../../exceptions/runtime.exceptions");
const _validators = require("../../handlers/validators");
const _userservicevalidation = require("../validators/user-service.validation");
const _cryptoutils = require("../../utils/crypto.utils");
const _authorizationconstants = require("../../constants/authorization.constants");
class UserService extends (0, _baseservice.BaseService)(_entities.User, _userdto.UserDto) {
userRoleService;
roleService;
constructor(typeormService, userRoleService, roleService){
super(typeormService), this.userRoleService = userRoleService, this.roleService = roleService;
}
toDto(user) {
return {
id: user.id,
createdAt: user.createdAt,
isVerified: user.isVerified,
isDemoUser: user.isDemoUser,
isRootUser: user.isRootUser,
username: user.username,
needsPasswordChange: user.needsPasswordChange,
roles: (user.roles ?? []).map((r)=>r.roleId)
};
}
listUsers(limit) {
return this.list({
take: limit
});
}
async getUser(userId) {
return this.get(userId);
}
async getUserRoleIds(userId) {
const userRoles = await this.userRoleService.listUserRoles(userId);
return userRoles.map((ur)=>ur.roleId);
}
findRootUsers() {
return this.repository.findBy({
isRootUser: true
});
}
async findUsersByRoleId(roleId) {
const userRoles = await this.userRoleService.listByRoleId(roleId);
const ids = userRoles.map((u)=>u.id);
return this.repository.findBy({
id: (0, _typeorm.In)(ids)
});
}
findVerifiedUsers() {
return this.repository.findBy({
isVerified: true
});
}
async isUserRootUser(userId) {
const entity = await this.get(userId);
return entity.isRootUser;
}
async deleteUser(userId) {
const user = await this.getUser(userId);
if (user.isRootUser) {
throw new _runtimeexceptions.InternalServerException("Cannot delete a root user");
}
if (!user.roles?.length) {
throw new _runtimeexceptions.InternalServerException("User:roles relation not loaded, cannot perform deletion role check");
}
const role = this.roleService.getRoleByName(_authorizationconstants.ROLES.ADMIN);
if (user.roles.find((r)=>r.roleId == role.id)) {
const administrators = await this.findUsersByRoleId(role.id);
if (administrators?.length === 1 && administrators[0].id === userId) {
throw new _runtimeexceptions.InternalServerException("Cannot delete the last user with ADMIN role");
}
}
await this.delete(userId);
}
findRawByUsername(username) {
return this.repository.findOneBy({
username
});
}
async getDemoUserId() {
return (await this.repository.findOneBy({
isDemoUser: true
}))?.id;
}
async setIsRootUserById(userId, isRootUser) {
const user = await this.getUser(userId);
if (!user) throw new _runtimeexceptions.NotFoundException("User not found");
if (!isRootUser) {
const rootUsers = await this.findRootUsers();
if (rootUsers.length === 1 && rootUsers[0].id === userId) {
throw new _runtimeexceptions.InternalServerException("Cannot set the last root user to non-root user");
}
}
await this.update(userId, {
isRootUser
});
}
async setUserRoleIds(userId, roleIds) {
await this.userRoleService.setUserRoles(userId, roleIds);
return await this.get(userId);
}
async setVerifiedById(userId, isVerified) {
const user = await this.getUser(userId);
if (!user) throw new _runtimeexceptions.NotFoundException("User not found");
if (!isVerified) {
if (user.isRootUser) {
throw new _runtimeexceptions.InternalServerException("Cannot set a owner (root user) to unverified");
}
const verifiedUsers = await this.findVerifiedUsers();
if (verifiedUsers.length === 1) {
throw new _runtimeexceptions.InternalServerException("Cannot set the last user to unverified");
}
}
await this.update(userId, {
isVerified
});
}
async updatePasswordById(userId, oldPassword, newPassword) {
const user = await this.getUser(userId);
if (!user) throw new _runtimeexceptions.NotFoundException("User not found");
if (!(0, _cryptoutils.comparePasswordHash)(oldPassword, user.passwordHash)) {
throw new _runtimeexceptions.NotFoundException("User old password incorrect");
}
const { password } = await (0, _validators.validateInput)({
password: newPassword
}, _userservicevalidation.newPasswordSchema);
const passwordHash = (0, _cryptoutils.hashPassword)(password);
return await this.update(userId, {
passwordHash,
needsPasswordChange: false
});
}
async updatePasswordUnsafeByUsername(username, newPassword) {
const { password } = await (0, _validators.validateInput)({
password: newPassword
}, _userservicevalidation.newPasswordSchema);
const passwordHash = (0, _cryptoutils.hashPassword)(password);
const user = await this.findRawByUsername(username);
if (!user) throw new _runtimeexceptions.NotFoundException("User not found");
return await this.update(user.id, {
passwordHash,
needsPasswordChange: false
});
}
updateUsernameById(userId, newUsername) {
return this.update(userId, {
username: newUsername
});
}
async register(input) {
const { username, password, roles, isDemoUser, isRootUser, needsPasswordChange, isVerified } = await (0, _validators.validateInput)(input, (0, _userservicevalidation.registerUserSchema)(true));
const passwordHash = (0, _cryptoutils.hashPassword)(password);
const result = await this.create({
username,
passwordHash,
isVerified: isVerified ?? false,
isDemoUser: isDemoUser ?? false,
isRootUser: isRootUser ?? false,
needsPasswordChange: needsPasswordChange ?? true
});
await this.userRoleService.setUserRoles(result.id, roles);
return this.get(result.id);
}
}
//# sourceMappingURL=user.service.js.map