235 lines
5.8 KiB
JavaScript
235 lines
5.8 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) {
|
|
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);
|
|
};
|