import { DataTypes, Model, InferAttributes, InferCreationAttributes, CreationOptional, HasManyAddAssociationMixin, HasManyCountAssociationsMixin, HasManyCreateAssociationMixin, HasManyGetAssociationsMixin, HasManyHasAssociationMixin, HasManySetAssociationsMixin, HasManyAddAssociationsMixin, HasManyHasAssociationsMixin, HasManyRemoveAssociationMixin, HasManyRemoveAssociationsMixin, NonAttribute, Association } from "sequelize"; import { UserRole } from "./User/UserRole"; import { UserAvatarColor } from "./User/UserAvatarColor"; import { UserAvatarType } from "./User/UserAvatarType"; import News from "./News"; import Session from "./Session"; import { ObjectIdType } from "@/modules/DataModule"; export class User extends Model< // eslint-disable-next-line no-use-before-define InferAttributes, // eslint-disable-next-line no-use-before-define InferCreationAttributes > { declare _id: CreationOptional; declare username: string; declare role: UserRole; declare emailVerified: CreationOptional; declare emailVerificationToken: CreationOptional; declare emailAddress: string; declare avatarType: UserAvatarType; declare avatarUrl: CreationOptional; declare avatarColor: CreationOptional; // Services declare password: string; declare passwordResetCode: CreationOptional; declare passwordResetExpiresAt: CreationOptional; declare passwordSetCode: CreationOptional; declare passwordSetExpiresAt: CreationOptional; declare githubId: CreationOptional; declare githubAccessToken: CreationOptional; // End services // Statistics declare songsRequested: CreationOptional; // End statistics // declare likedSongsPlaylist: Types.ObjectId; // declare dislikedSongsPlaylist: Types.ObjectId; // declare favoriteStations: Types.ObjectId[]; declare name: string; declare location: CreationOptional; declare bio: CreationOptional; // Preferences // declare orderOfPlaylists: Types.ObjectId[]; declare nightmode: CreationOptional; declare autoSkipDisliked: CreationOptional; declare activityLogPublic: CreationOptional; declare anonymousSongRequests: CreationOptional; declare activityWatch: CreationOptional; // End preferences declare createdAt: CreationOptional; declare updatedAt: CreationOptional; declare getSessionModels: HasManyGetAssociationsMixin; declare addSessionModel: HasManyAddAssociationMixin; declare addSessionModels: HasManyAddAssociationsMixin; declare setSessionModels: HasManySetAssociationsMixin; declare removeSessionModel: HasManyRemoveAssociationMixin; declare removeSessionModels: HasManyRemoveAssociationsMixin< Session, number >; declare hasSessionModel: HasManyHasAssociationMixin; declare hasSessionModels: HasManyHasAssociationsMixin; declare countSessionModels: HasManyCountAssociationsMixin; declare createSessionModel: HasManyCreateAssociationMixin< Session, "userId" >; declare sessionModels?: NonAttribute; declare getCreatedNewsModels: HasManyGetAssociationsMixin; declare addCreatedNewsModel: HasManyAddAssociationMixin; declare addCreatedNewsModels: HasManyAddAssociationsMixin; declare setCreatedNewsModels: HasManySetAssociationsMixin; declare removeCreatedNewsModel: HasManyRemoveAssociationMixin; declare removeCreatedNewsModels: HasManyRemoveAssociationsMixin< News, number >; declare hasCreatedNewsModel: HasManyHasAssociationMixin; declare hasCreatedNewsModels: HasManyHasAssociationsMixin; declare countCreatedNewsModels: HasManyCountAssociationsMixin; declare createCreatedNewsModel: HasManyCreateAssociationMixin< News, "createdBy" >; declare createdNewsModels?: NonAttribute; declare static associations: { // eslint-disable-next-line no-use-before-define sessionModels: Association; // eslint-disable-next-line no-use-before-define createdNewsModels: Association; }; } // TODO add validation export const schema = { _id: { type: DataTypes.OBJECTID, autoNull: false, primaryKey: true }, username: { type: DataTypes.STRING, allowNull: false }, role: { type: DataTypes.ENUM(...Object.values(UserRole)), allowNull: false }, emailVerified: { type: DataTypes.BOOLEAN, allowNull: true, defaultValue: false }, emailVerificationToken: { type: DataTypes.STRING, allowNull: true }, emailAddress: { type: DataTypes.STRING, allowNull: false }, avatarType: { type: DataTypes.ENUM(...Object.values(UserAvatarType)), allowNull: false }, avatarUrl: { type: DataTypes.STRING, allowNull: true }, avatarColor: { type: DataTypes.ENUM(...Object.values(UserAvatarColor)), allowNull: true }, password: { type: DataTypes.STRING, allowNull: false }, passwordResetCode: { type: DataTypes.STRING, allowNull: true }, passwordResetExpiresAt: { type: DataTypes.DATE, allowNull: true }, passwordSetCode: { type: DataTypes.STRING, allowNull: true }, passwordSetExpiresAt: { type: DataTypes.DATE, allowNull: true }, githubId: { type: DataTypes.BIGINT, allowNull: true }, githubAccessToken: { type: DataTypes.STRING, allowNull: true }, songsRequested: { type: DataTypes.BIGINT, allowNull: false, defaultValue: 0 }, name: { type: DataTypes.STRING, allowNull: false }, location: { type: DataTypes.STRING, allowNull: true }, bio: { type: DataTypes.STRING, allowNull: true }, nightmode: { type: DataTypes.BOOLEAN, allowNull: false, defaultValue: false }, autoSkipDisliked: { type: DataTypes.BOOLEAN, allowNull: false, defaultValue: true }, activityLogPublic: { type: DataTypes.BOOLEAN, allowNull: false, defaultValue: false }, anonymousSongRequests: { type: DataTypes.BOOLEAN, allowNull: false, defaultValue: false }, activityWatch: { type: DataTypes.BOOLEAN, allowNull: false, defaultValue: false }, createdAt: DataTypes.DATE, updatedAt: DataTypes.DATE, hasPassword: { type: DataTypes.BOOLEAN, readonly: true }, _name: { type: DataTypes.VIRTUAL, get() { return `users`; } }, // Temporary favoriteStations: { type: DataTypes.VIRTUAL, get() { return []; } } }; export const options = { defaultScope: { attributes: { exclude: [ "emailVerificationToken", "password", "passwordResetCode", "passwordSetCode", "githubAccessToken" ] } } }; export const setup = async () => { User.hasMany(Session, { as: "sessionModels", foreignKey: { name: "userId", type: DataTypes.OBJECTID, allowNull: false }, onDelete: "RESTRICT", onUpdate: "RESTRICT" }); User.hasMany(News, { as: "createdNewsModels", foreignKey: { name: "createdBy", type: DataTypes.OBJECTID, allowNull: false }, onDelete: "RESTRICT", onUpdate: "RESTRICT" }); // User.afterSave(async record => {}); // User.afterDestroy(async record => {}); }; export default User;