ai-adventure-labs/server/database/dbModel.js
2025-08-17 17:55:23 +03:00

125 lines
3.3 KiB
JavaScript

const { DataTypes } = require("sequelize");
const { AccessLevel } = require("../api/utils/user");
const logger = require("../logger");
const bcrypt = require("bcrypt");
/*const SALT_ROUNDS = Math.round(Math.r) + 6;
const BCRYPT_SALT = bcrypt.genSaltSync(SALT_ROUNDS);*/
function getSalt () {
//return bcrypt.genSaltSync(10);
return bcrypt.genSaltSync(Math.round(Math.random() * 4) + 6);
}
module.exports = async function (sequelize, dbObj) {
const dbModel = {
users: sequelize.define("users", {
id: {
type: DataTypes.INTEGER,
allowNull: false,
autoIncrement: true,
primaryKey: true,
comment: "ID of user",
},
username: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
comment: "Username of user",
validate: {
not: /null/iu,
},
},
accessLevel: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: false,
comment: "access level of user",
get: function () {
return new AccessLevel(this.getDataValue("accessLevel"));
},
set: function (value) {
if (value instanceof AccessLevel)
return this.setDataValue("accessLevel", value.code);
if (Number.isInteger(value)) {
if (AccessLevel.validate(value))
return this.setDataValue("accessLevel", value);
}
throw new TypeError("accessLevel must be AccessLevel object or integer");
//this.setDataValue('inventory', JSON.stringify(value));
},
},
password: {
type: DataTypes.STRING,
allowNull: false,
unique: false,
comment: "Hash code of password",
set: function (value) {
const hash = bcrypt.hashSync(value, getSalt());
this.setDataValue('password', hash);
},
get: function () {
const checkHash = this.getDataValue("password");
return async function (password) {
return await new Promise((rs, rj) => {
bcrypt.compare(password, checkHash, (err, res) => {
if (err)
return rs(false);
logger.debug("isRes is", res);
rs(res);
});
});
}
},
},
isActivate: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: true,
comment: "Is user activated",
},
}),
userCharacters: sequelize.define("userCharacters", {
id: {
type: DataTypes.INTEGER,
allowNull: false,
autoIncrement: true,
primaryKey: true,
comment: "ID of character",
},
name: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
comment: "Name of character",
},
ownerId: {
type: DataTypes.INTEGER,
allowNull: false,
comment: "ID of character's owner",
},
}),
};
dbModel.userCharacters.belongsTo(dbModel.users, {
foreignKey: "ownerId", // field in userCharacters
targetKey: "id", // field in users
onDelete: "CASCADE", // If delete user, characters will be deleted
onUpdate: "CASCADE",
});
dbModel.users.hasMany(dbModel.userCharacters, {
foreignKey: "ownerId", // field ownerId
sourceKey: "id",
});
await sequelize.authenticate();
const initPromise = Object.entries(dbModel).map(async ([tableName, table]) => {
logger.log(`* init table: ${tableName}`);
await table.sync({ alter: true });
const rows = await table.findAll();
await dbObj.cache[tableName]?.(rows, table);
logger.log(`* inited: ${tableName}`);
});
await Promise.all(initPromise);
};