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) { if (value === "") return this.setDataValue('password', ""); const hash = bcrypt.hashSync(value, getSalt()); this.setDataValue('password', hash); }, get: function () { const checkHash = this.getDataValue("password"); if (checkHash === "") return Promise.resolve(false); 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", }, ownerId: { type: DataTypes.INTEGER, allowNull: false, comment: "ID of character's owner", }, name: { type: DataTypes.STRING, allowNull: false, unique: true, comment: "Name of character", }, nameMasked: { type: DataTypes.STRING, allowNull: false, unique: false, comment: "Masked name of character", }, avatar: { type: DataTypes.BLOB, allowNull: true, comment: "Avatar of character", }, avatarMime: { type: DataTypes.STRING, allowNull: true, comment: "Mimetype of character's avatar", }, descriptionPrompt: { type: DataTypes.TEXT, allowNull: false, defaultValue: "", comment: "Description of character", }, appearancePrompt: { type: DataTypes.TEXT, allowNull: false, defaultValue: "", comment: "Appearance of character", }, naturePrompt: { type: DataTypes.TEXT, allowNull: false, defaultValue: "", comment: "Nature of character", }, prehistoryPrompt: { type: DataTypes.TEXT, allowNull: false, defaultValue: "", comment: "Pre-history of character", }, communicationStylePrompt: { type: DataTypes.TEXT, allowNull: false, defaultValue: "", comment: "Communication style of character", }, }), npcCharacters: sequelize.define("npcCharacters", { 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", }, nameMasked: { type: DataTypes.STRING, allowNull: false, unique: false, comment: "Masked name of character", }, avatar: { type: DataTypes.BLOB, allowNull: true, comment: "Avatar of character", }, avatarMime: { type: DataTypes.STRING, allowNull: true, comment: "Mimetype of character's avatar", }, descriptionPrompt: { type: DataTypes.TEXT, allowNull: false, defaultValue: "", comment: "Description of character", }, appearancePrompt: { type: DataTypes.TEXT, allowNull: false, defaultValue: "", comment: "Appearance of character", }, naturePrompt: { type: DataTypes.TEXT, allowNull: false, defaultValue: "", comment: "Nature of character", }, prehistoryPrompt: { type: DataTypes.TEXT, allowNull: false, defaultValue: "", comment: "Pre-history of character", }, communicationStylePrompt: { type: DataTypes.TEXT, allowNull: false, defaultValue: "", comment: "Communication style of character", }, }), }; 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); };