gpstracker/src/models/User.ts

132 lines
3 KiB
TypeScript

import bcrypt from 'bcryptjs';
import { Op } from 'sequelize';
import { Optional } from '~/types';
import Role from './Role';
import RoleName from './RoleName';
class User {
public id: number;
public username: string;
public password: string;
public email: string;
public firstName: Optional<string>;
public lastName: Optional<string>;
public createdAt: Optional<Date>;
constructor({
id,
username,
email,
password,
firstName = null,
lastName = null,
createdAt = null,
}: User) {
this.id = id;
this.username = username;
this.email = email;
this.password = password;
this.firstName = firstName;
this.lastName = lastName;
this.createdAt = createdAt;
}
public static hashPassword(password: string): string {
return bcrypt.hashSync(password, bcrypt.genSaltSync(10));
}
public checkPassword(password: string): boolean {
return bcrypt.compareSync(password, this.password);
}
public async roles(): Promise<Role[]> {
return (
await $db.UserRole().findAll({
where: {
userId: this.id,
},
})
).map((role) => new Role(role.dataValues));
}
public async setRoles(roles: (Role | RoleName | number | string)[]): Promise<void> {
const inputRoleIds = new Set(
roles.filter((role) => {
role instanceof Role || typeof role === 'number'
}).map((role) => {
if (role instanceof Role) {
return role.id;
}
return role;
})
);
const inputRoleNames = new Set(
roles.filter((role) => {
typeof role === 'string'
}).map((role) => {
return role;
})
);
if (!inputRoleIds.size && !inputRoleNames.size) {
return; // No roles to set
}
const query: Record<string, any> = {}
if (inputRoleIds.size) {
query['id'] = [...inputRoleIds];
}
if (inputRoleNames.size) {
query['name'] = [...inputRoleNames];
}
const roleIds = new Set(
(
await $db.Role().findAll({
where: {
[Op.or]: query,
},
})
).map((role) => (role as any).id)
);
const userRoles = await $db.UserRole().findAll({
where: {
userId: this.id,
},
});
const userRoleIds = new Set(userRoles.map((role) => (role as any).roleId));
const toAdd = [...roleIds].filter((roleId) => !userRoleIds.has(roleId));
const toRemove = userRoles.filter((role) => !roleIds.has((role as any).roleId)).map((role) => (role as any).roleId);
await $db.UserRole().bulkCreate(
toAdd.map((roleId) => ({
userId: this.id,
roleId: roleId,
})),
);
await $db.UserRole().destroy({
where: {
userId: this.id,
roleId: toRemove,
},
});
}
public async save(): Promise<void> {
this.password = User.hashPassword(this.password);
await $db.User().update(this, {
where: {
id: this.id,
},
});
}
}
export default User;