import mongoose, { PopulatedDoc, Document, Model } from "mongoose"; import SequenceFactory from "mongoose-sequence"; import bcrypt from "bcryptjs"; import md5 from "blueimp-md5"; import jwt from "jsonwebtoken"; import { hasMigrated } from "@dbconfig"; import { IBand } from "./band"; import { IStory } from "./stories/index"; import { QuickMenuItem, QuickMenuSchema } from "./quickMenu"; import { FilterPick, PopulatedDocKeys, PopulatedPick } from "~/utils/filter"; const AutoIncrement = SequenceFactory(mongoose); interface IIPLogEntry { lastAccess: Date; ip: string; } export interface IUser extends Document { _id?: number; username: string; email: string; password: string; auth: { emailVerified: boolean; activationKey: string | null; passwordResetToken: string | null; }; ts: { created: Date; updated: Date; }; ipLog: IIPLogEntry[]; lastLogin: Date; lastVisit: Date; profile: { avatar?: string; isAdmin: boolean; nightMode: boolean; bio: string; location: string; occupation: string; website: string; blog: string; views: number; lastWhere: string | null; hidden: boolean; disclaimer: string; showEmail: boolean; }; biffno: { years: string[]; wins: number; }; favs: { authors: PopulatedDoc[]; stories: PopulatedDoc[]; }; subscriptions: { authors: PopulatedDoc[]; bands: PopulatedDoc[]; stories: PopulatedDoc[]; }; //@ts-ignore SHUT UP hiddenAuthors: PopulatedDoc[]; hiddenBands: PopulatedDoc[]; //@ts-ignore SHUT UP blocked: PopulatedDoc[]; sessionId: string | null; banned: boolean; quickMenuConfig: QuickMenuItem[]; notifyOnReviewReply?: boolean; validPassword(password: string): boolean; generateJWT(jwtSecret: string): string; } // type iut = IUser; interface UModel extends Model { generateHash(pwd: string): string; } const UserSchema = new mongoose.Schema({ _id: { type: Number, }, username: { type: String, }, email: { type: String, }, password: { type: String, }, auth: { emailVerified: { type: Boolean, default: false, }, activationKey: { type: String, }, passwordResetToken: { type: String, default: null, }, }, ts: { created: { type: Date, default: new Date(), }, updated: { type: Date, default: new Date(), }, }, ipLog: [ { ip: { type: String, }, lastAccess: { type: Date, default: new Date(), }, }, ], lastLogin: { type: Date, default: null, }, lastVisit: { type: Date, default: null, }, profile: { avatar: { type: String, default: "", }, isAdmin: { type: Boolean, default: false, }, nightMode: { type: Boolean, default: false, }, bio: { type: String, default: "", }, location: { type: String, default: "", }, occupation: { type: String, default: "", }, website: { type: String, default: "", }, blog: { type: String, default: "", }, views: { type: Number, min: 0, default: 0, }, lastWhere: { type: String, default: null, }, hidden: { type: Boolean, default: false, }, disclaimer: { type: String, default: "", }, showEmail: { type: Boolean, default: false, }, }, biffno: { years: [ { type: String, }, ], wins: { type: Number, default: 0, }, }, favs: { authors: [ { type: Number, ref: "User", }, ], stories: [ { type: Number, ref: "Story", }, ], }, subscriptions: { authors: [ { type: Number, ref: "User", }, ], stories: [ { type: Number, ref: "Story", }, ], bands: [ { type: Number, ref: "Band", }, ], }, hiddenBands: [ { type: Number, ref: "Band", }, ], hiddenAuthors: [ { type: Number, ref: "User", }, ], notifyOnReviewReply: { type: Boolean, default: true, }, blocked: [ { type: Number, ref: "User", }, ], sessionId: { type: String, default: null, }, banned: { type: Boolean, default: false, }, quickMenuConfig: [QuickMenuSchema], }); UserSchema.static("generateHash", function (password: string): string { return bcrypt.hashSync(password, bcrypt.genSaltSync(8)); }); UserSchema.methods.validPassword = function (password: string): boolean { return md5(password) === this.password || bcrypt.compareSync(password, this.password) || false; }; UserSchema.methods.generateJWT = function (jwtKey: string): string { let token = jwt.sign({ id: this._id, isAdmin: this.profile.isAdmin }, jwtKey, { expiresIn: "14 days", }); return token; }; hasMigrated && !mongoose.models.User && UserSchema.plugin(AutoIncrement, { id: "userid", inc_field: "_id" }); export const User = mongoose.model("User", UserSchema, "users");