db/models/user.jsjavascript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const sequelize_1 = require("sequelize");
const userAccess_1 = __importDefault(require("./userAccess"));
const db_1 = __importDefault(require("../db"));
const passport_1 = require("../../plugins/passport.js");
const bcrypt = require("bcrypt");
/**
* @openapi
* components:
* schemas:
* User:
* type: object
* required:
* - id
* - username
* properties:
* id:
* type: string
* format: uuid
* username:
* type: string
* email:
* type: string
* format: email
* emailConfirmed:
* type: boolean
* default: false
* profilePictureExtension:
* type: string
* example: .png
* password:
* type: string
* format: password
* lastLoggedIn:
* type: string
* format: date-time
*/
/**
* @typedef User
* @property {UUID} id
* @property {string} username
* @property {string} [email]
* @property {boolean} [emailConfirmed]
* @property {string} [profilePictureExtension]
* @property {string} password
* @property {Date} [lastLoggedIn]
* @memberof module:Models
*/
class User extends sequelize_1.Model {
}
User.init({
id: {
type: sequelize_1.DataTypes.UUID,
defaultValue: sequelize_1.DataTypes.UUIDV4,
primaryKey: true,
},
username: {
type: sequelize_1.DataTypes.STRING,
allowNull: true,
validate: {
len: {
args: [6, 999],
msg: "Username has to be at least 6 characters",
},
},
},
email: {
type: sequelize_1.DataTypes.STRING,
allowNull: true,
unique: true,
validate: {
isEmail: {
msg: "Email has to be correct email format, e.g. info@choreo-planer.de",
},
},
},
emailConfirmed: {
type: sequelize_1.DataTypes.BOOLEAN,
defaultValue: false,
allowNull: false,
},
profilePictureExtension: {
type: sequelize_1.DataTypes.STRING,
allowNull: true,
},
password: {
type: sequelize_1.DataTypes.STRING,
allowNull: true,
set(value) {
if (value == null) {
this.setDataValue("password", undefined);
}
else {
const salt = bcrypt.genSaltSync(10, "a");
this.setDataValue("password", bcrypt.hashSync(value, salt));
}
},
},
provider: {
type: sequelize_1.DataTypes.ENUM(...Object.values(passport_1.AuthProvider)),
allowNull: false,
defaultValue: passport_1.AuthProvider.LOCAL,
validate: {
isIn: {
args: [Object.values(passport_1.AuthProvider)],
msg: "Provider must be one of: local, google, github, facebook",
},
},
},
socialId: {
type: sequelize_1.DataTypes.STRING,
allowNull: true,
},
lastLoggedIn: {
type: sequelize_1.DataTypes.DATE,
allowNull: true,
},
createdAt: sequelize_1.DataTypes.DATE,
updatedAt: sequelize_1.DataTypes.DATE,
deletedAt: sequelize_1.DataTypes.DATE,
}, {
sequelize: db_1.default,
defaultScope: {
attributes: {
exclude: ["password"],
},
},
scopes: {
withPasswordHash: {
attributes: {
exclude: [],
},
},
includingDeleted: {
paranoid: false,
},
},
paranoid: true,
hooks: {
beforeValidate: function (instance) {
if (instance.getDataValue("provider") === "local") {
if (instance.getDataValue("username") == null) {
throw new Error("Username is required for local users");
}
if (instance.getDataValue("password") === null) {
throw new Error("Password is required for local users");
}
}
},
afterDestroy: async function (instance, _options) {
const clubList = await instance.getClubs();
await Promise.all(clubList.map((club) => club.destroy()));
await userAccess_1.default.destroy({
where: {
[sequelize_1.Op.or]: [
{ ownerUserId: instance.id },
{ childUserId: instance.id },
],
},
});
},
},
indexes: [
// Enforce username uniqueness only for local provider users.
{
unique: true,
fields: ["username"],
where: {
provider: passport_1.AuthProvider.LOCAL,
},
},
{
unique: true,
fields: ["email", "provider"],
},
{
unique: true,
fields: ["socialId", "provider"],
},
],
});
exports.default = User;