import { DataTypes } from 'sequelize'; import { env } from '$env/dynamic/private'; import { building, dev } from '$app/environment'; import * as bcrypt from 'bcrypt'; import { BeforeCreate, BeforeUpdate, BelongsTo, Column, ForeignKey, Index, Model, Sequelize, Table } from 'sequelize-typescript'; import { Permissions } from '$lib/permissions'; @Table({ modelName: 'user', underscored: true }) export class User extends Model { @Column({ type: DataTypes.STRING, allowNull: false }) declare firstname: string; @Column({ type: DataTypes.STRING, allowNull: false }) declare lastname: string; @Column({ type: DataTypes.DATE, allowNull: false }) declare birthday: Date; @Column({ type: DataTypes.STRING }) declare telephone: string; @Column({ type: DataTypes.STRING, allowNull: false }) declare username: string; @Column({ type: DataTypes.ENUM('java', 'bedrock', 'noauth'), allowNull: false }) declare playertype: 'java' | 'bedrock' | 'noauth'; @Column({ type: DataTypes.STRING }) declare password: string; @Column({ type: DataTypes.UUID, unique: true }) @Index declare uuid: string; } @Table({ modelName: 'report', underscored: true }) export class Report extends Model { @Column({ type: DataTypes.STRING, allowNull: false, unique: true }) @Index declare url_hash: string; @Column({ type: DataTypes.STRING, allowNull: false }) declare subject: string; @Column({ type: DataTypes.STRING }) declare body: string; @Column({ type: DataTypes.BOOLEAN, allowNull: false }) declare draft: boolean; @Column({ type: DataTypes.ENUM('none', 'review', 'reviewed'), allowNull: false }) declare status: 'none' | 'review' | 'reviewed'; @Column({ type: DataTypes.STRING }) declare notice: string; @Column({ type: DataTypes.STRING }) declare statement: string; @Column({ type: DataTypes.INTEGER, allowNull: false }) @ForeignKey(() => User) declare reporter_id: number; @Column({ type: DataTypes.INTEGER }) @ForeignKey(() => User) declare reported_id: number; @Column({ type: DataTypes.INTEGER }) @ForeignKey(() => Admin) declare auditor_id: number; @Column({ type: DataTypes.INTEGER }) @ForeignKey(() => StrikeReason) declare strike_reason_id: number | null; @BelongsTo(() => User, 'reporter_id') declare reporter: User; @BelongsTo(() => User, 'reported_id') declare reported: User; @BelongsTo(() => Admin, 'auditor_id') declare auditor: Admin; @BelongsTo(() => StrikeReason, 'strike_reason_id') declare strike_reason: StrikeReason; } @Table({ modelName: 'strike_reason', underscored: true, createdAt: false, updatedAt: false }) export class StrikeReason extends Model { @Column({ type: DataTypes.INTEGER, allowNull: false }) declare weight: number; @Column({ type: DataTypes.STRING, allowNull: false }) declare name: string; } @Table({ modelName: 'strike_punishment', underscored: true, createdAt: false, updatedAt: false }) export class StrikePunishment extends Model { @Column({ type: DataTypes.INTEGER, allowNull: false }) declare weight: number; @Column({ type: DataTypes.INTEGER, allowNull: false }) declare ban_in_seconds: number; } @Table({ modelName: 'strike', underscored: true }) export class Strike extends Model { @Column({ type: DataTypes.INTEGER, allowNull: false, defaultValue: 0 }) declare weight: number; @Column({ type: DataTypes.DATE, allowNull: false, defaultValue: 0 }) declare ban_until: Date; @Column({ type: DataTypes.INTEGER, allowNull: false }) @ForeignKey(() => User) declare user_id: number; @BelongsTo(() => User, 'user_id') declare user: User; } @Table({ modelName: 'admin', underscored: true }) export class Admin extends Model { @Column({ type: DataTypes.STRING, allowNull: false, unique: true }) declare username: string; @Column({ type: DataTypes.STRING, allowNull: false }) declare password: string; @Column({ type: DataTypes.BIGINT, allowNull: false, get(this: Admin): Permissions | null { const permissions = this.getDataValue('permissions'); return permissions != null ? new Permissions(permissions) : null; }, set(this: Admin, value: Permissions) { this.setDataValue('permissions', value.value); } }) declare permissions: Permissions; @BeforeCreate @BeforeUpdate static hashPassword(instance: Admin) { if ((instance.changed() || []).indexOf('password') != -1) { instance.password = bcrypt.hashSync(instance.password, 10); } } validatePassword(password: string): boolean { return bcrypt.compareSync(password, this.password); } } @Table({ modelName: 'settings', underscored: true }) export class Settings extends Model { @Column({ type: DataTypes.STRING, allowNull: false, unique: true }) declare key: string; @Column({ type: DataTypes.STRING, allowNull: false, // eslint-disable-next-line @typescript-eslint/no-explicit-any get(this: Settings): any { const value = this.getDataValue('value'); return value != null ? JSON.parse(value) : null; } }) declare value: string; } export const sequelize = new Sequelize(building ? 'sqlite::memory:' : env.DATABASE_URI, { // only log sql queries in dev mode logging: dev ? console.log : false, models: [User, Report, StrikeReason, StrikePunishment, Strike, Admin, Settings] });