2023-10-03 01:02:05 -04:00
|
|
|
import mongoose, {
|
|
|
|
Schema,
|
|
|
|
connect,
|
|
|
|
PopulatedDoc,
|
|
|
|
Document,
|
|
|
|
Model,
|
|
|
|
} from "mongoose";
|
2023-09-25 19:41:32 -04:00
|
|
|
import SequenceFactory from "mongoose-sequence";
|
|
|
|
import bcrypt from "bcryptjs";
|
|
|
|
import md5 from "blueimp-md5";
|
2023-10-03 01:02:05 -04:00
|
|
|
import jwt from "jsonwebtoken";
|
2023-12-20 17:23:31 -05:00
|
|
|
import { hasMigrated } from "@dbconfig";
|
2023-09-25 19:41:32 -04:00
|
|
|
import { IBand } from "./band";
|
2023-10-03 01:02:05 -04:00
|
|
|
import { IStory } from "./stories/index";
|
2023-09-25 19:41:32 -04:00
|
|
|
import { QuickMenuItem, QuickMenuSchema } from "./quickMenu";
|
|
|
|
|
|
|
|
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;
|
2023-10-03 01:02:05 -04:00
|
|
|
};
|
2023-09-25 19:41:32 -04:00
|
|
|
ts: {
|
|
|
|
created: Date;
|
|
|
|
updated: Date;
|
2023-10-03 01:02:05 -04:00
|
|
|
};
|
2023-09-25 19:41:32 -04:00
|
|
|
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;
|
2023-10-03 01:02:05 -04:00
|
|
|
};
|
2023-09-25 19:41:32 -04:00
|
|
|
biffno: {
|
|
|
|
years: string[];
|
|
|
|
wins: number;
|
2023-10-03 01:02:05 -04:00
|
|
|
};
|
2023-09-25 19:41:32 -04:00
|
|
|
favs: {
|
|
|
|
authors: PopulatedDoc<IUser & Document>[];
|
|
|
|
stories: PopulatedDoc<IStory & Document>[];
|
2023-10-03 01:02:05 -04:00
|
|
|
};
|
2023-09-25 19:41:32 -04:00
|
|
|
subscriptions: {
|
|
|
|
authors: PopulatedDoc<IUser & Document>[];
|
|
|
|
bands: PopulatedDoc<IBand & Document>[];
|
|
|
|
stories: PopulatedDoc<IStory & Document>[];
|
2023-10-03 01:02:05 -04:00
|
|
|
};
|
2023-09-25 19:41:32 -04:00
|
|
|
//@ts-ignore SHUT UP
|
|
|
|
hiddenAuthors: PopulatedDoc<IUser & Document>[];
|
|
|
|
hiddenBands: PopulatedDoc<IBand & Document>[];
|
|
|
|
//@ts-ignore SHUT UP
|
|
|
|
blocked: PopulatedDoc<IUser & Document>[];
|
|
|
|
sessionId: string | null;
|
|
|
|
banned: boolean;
|
2023-10-03 01:02:05 -04:00
|
|
|
quickMenuConfig: QuickMenuItem[];
|
|
|
|
notifyOnReviewReply?: boolean;
|
2023-09-25 19:41:32 -04:00
|
|
|
validPassword(password: string): boolean;
|
2023-12-20 19:56:33 -05:00
|
|
|
generateJWT(jwtSecret: string): string;
|
2023-09-25 19:41:32 -04:00
|
|
|
}
|
|
|
|
// type iut = IUser;
|
|
|
|
interface UModel extends Model<IUser> {
|
|
|
|
generateHash(pwd: string): string;
|
|
|
|
}
|
|
|
|
|
2023-10-03 01:02:05 -04:00
|
|
|
const UserSchema = new mongoose.Schema<IUser>({
|
2023-09-25 19:41:32 -04:00
|
|
|
_id: {
|
2023-10-03 01:02:05 -04:00
|
|
|
type: Number,
|
2023-09-25 19:41:32 -04:00
|
|
|
},
|
|
|
|
username: {
|
2023-10-03 01:02:05 -04:00
|
|
|
type: String,
|
2023-09-25 19:41:32 -04:00
|
|
|
},
|
|
|
|
email: {
|
2023-10-03 01:02:05 -04:00
|
|
|
type: String,
|
2023-09-25 19:41:32 -04:00
|
|
|
},
|
|
|
|
password: {
|
2023-10-03 01:02:05 -04:00
|
|
|
type: String,
|
2023-09-25 19:41:32 -04:00
|
|
|
},
|
|
|
|
auth: {
|
|
|
|
emailVerified: {
|
|
|
|
type: Boolean,
|
2023-10-03 01:02:05 -04:00
|
|
|
default: false,
|
2023-09-25 19:41:32 -04:00
|
|
|
},
|
|
|
|
activationKey: {
|
2023-10-03 01:02:05 -04:00
|
|
|
type: String,
|
2023-09-25 19:41:32 -04:00
|
|
|
},
|
|
|
|
passwordResetToken: {
|
|
|
|
type: String,
|
2023-10-03 01:02:05 -04:00
|
|
|
default: null,
|
|
|
|
},
|
2023-09-25 19:41:32 -04:00
|
|
|
},
|
|
|
|
ts: {
|
|
|
|
created: {
|
|
|
|
type: Date,
|
2023-10-03 01:02:05 -04:00
|
|
|
default: new Date(),
|
2023-09-25 19:41:32 -04:00
|
|
|
},
|
|
|
|
updated: {
|
|
|
|
type: Date,
|
2023-10-03 01:02:05 -04:00
|
|
|
default: new Date(),
|
|
|
|
},
|
2023-09-25 19:41:32 -04:00
|
|
|
},
|
2023-10-03 01:02:05 -04:00
|
|
|
ipLog: [
|
|
|
|
{
|
|
|
|
ip: {
|
|
|
|
type: String,
|
|
|
|
},
|
|
|
|
lastAccess: {
|
|
|
|
type: Date,
|
|
|
|
default: new Date(),
|
|
|
|
},
|
2023-09-25 19:41:32 -04:00
|
|
|
},
|
2023-10-03 01:02:05 -04:00
|
|
|
],
|
2023-09-25 19:41:32 -04:00
|
|
|
lastLogin: {
|
|
|
|
type: Date,
|
2023-10-03 01:02:05 -04:00
|
|
|
default: null,
|
2023-09-25 19:41:32 -04:00
|
|
|
},
|
|
|
|
lastVisit: {
|
|
|
|
type: Date,
|
2023-10-03 01:02:05 -04:00
|
|
|
default: null,
|
2023-09-25 19:41:32 -04:00
|
|
|
},
|
|
|
|
profile: {
|
|
|
|
avatar: {
|
|
|
|
type: String,
|
2023-10-03 01:02:05 -04:00
|
|
|
default: "",
|
2023-09-25 19:41:32 -04:00
|
|
|
},
|
|
|
|
isAdmin: {
|
|
|
|
type: Boolean,
|
2023-10-03 01:02:05 -04:00
|
|
|
default: false,
|
2023-09-25 19:41:32 -04:00
|
|
|
},
|
|
|
|
nightMode: {
|
|
|
|
type: Boolean,
|
2023-10-03 01:02:05 -04:00
|
|
|
default: false,
|
2023-09-25 19:41:32 -04:00
|
|
|
},
|
|
|
|
bio: {
|
|
|
|
type: String,
|
2023-10-03 01:02:05 -04:00
|
|
|
default: "",
|
2023-09-25 19:41:32 -04:00
|
|
|
},
|
|
|
|
location: {
|
|
|
|
type: String,
|
2023-10-03 01:02:05 -04:00
|
|
|
default: "",
|
2023-09-25 19:41:32 -04:00
|
|
|
},
|
|
|
|
occupation: {
|
|
|
|
type: String,
|
2023-10-03 01:02:05 -04:00
|
|
|
default: "",
|
2023-09-25 19:41:32 -04:00
|
|
|
},
|
|
|
|
website: {
|
|
|
|
type: String,
|
2023-10-03 01:02:05 -04:00
|
|
|
default: "",
|
2023-09-25 19:41:32 -04:00
|
|
|
},
|
|
|
|
blog: {
|
|
|
|
type: String,
|
2023-10-03 01:02:05 -04:00
|
|
|
default: "",
|
2023-09-25 19:41:32 -04:00
|
|
|
},
|
|
|
|
views: {
|
|
|
|
type: Number,
|
|
|
|
min: 0,
|
2023-10-03 01:02:05 -04:00
|
|
|
default: 0,
|
2023-09-25 19:41:32 -04:00
|
|
|
},
|
|
|
|
lastWhere: {
|
|
|
|
type: String,
|
2023-10-03 01:02:05 -04:00
|
|
|
default: null,
|
2023-09-25 19:41:32 -04:00
|
|
|
},
|
|
|
|
hidden: {
|
|
|
|
type: Boolean,
|
2023-10-03 01:02:05 -04:00
|
|
|
default: false,
|
2023-09-25 19:41:32 -04:00
|
|
|
},
|
|
|
|
disclaimer: {
|
|
|
|
type: String,
|
2023-10-03 01:02:05 -04:00
|
|
|
default: "",
|
2023-09-25 19:41:32 -04:00
|
|
|
},
|
|
|
|
showEmail: {
|
|
|
|
type: Boolean,
|
2023-10-03 01:02:05 -04:00
|
|
|
default: false,
|
|
|
|
},
|
2023-09-25 19:41:32 -04:00
|
|
|
},
|
|
|
|
biffno: {
|
2023-10-03 01:02:05 -04:00
|
|
|
years: [
|
|
|
|
{
|
|
|
|
type: String,
|
|
|
|
},
|
|
|
|
],
|
2023-09-25 19:41:32 -04:00
|
|
|
wins: {
|
|
|
|
type: Number,
|
2023-10-03 01:02:05 -04:00
|
|
|
default: 0,
|
|
|
|
},
|
2023-09-25 19:41:32 -04:00
|
|
|
},
|
|
|
|
favs: {
|
2023-10-03 01:02:05 -04:00
|
|
|
authors: [
|
|
|
|
{
|
|
|
|
type: Number,
|
|
|
|
ref: "User",
|
|
|
|
},
|
|
|
|
],
|
|
|
|
stories: [
|
|
|
|
{
|
|
|
|
type: Number,
|
|
|
|
ref: "Story",
|
|
|
|
},
|
|
|
|
],
|
2023-09-25 19:41:32 -04:00
|
|
|
},
|
|
|
|
subscriptions: {
|
2023-10-03 01:02:05 -04:00
|
|
|
authors: [
|
|
|
|
{
|
|
|
|
type: Number,
|
|
|
|
ref: "User",
|
|
|
|
},
|
|
|
|
],
|
|
|
|
stories: [
|
|
|
|
{
|
|
|
|
type: Number,
|
|
|
|
ref: "Story",
|
|
|
|
},
|
|
|
|
],
|
|
|
|
bands: [
|
|
|
|
{
|
|
|
|
type: Number,
|
|
|
|
ref: "Band",
|
|
|
|
},
|
|
|
|
],
|
|
|
|
},
|
|
|
|
hiddenBands: [
|
|
|
|
{
|
2023-09-25 19:41:32 -04:00
|
|
|
type: Number,
|
2023-10-03 01:02:05 -04:00
|
|
|
ref: "Band",
|
|
|
|
},
|
|
|
|
],
|
|
|
|
hiddenAuthors: [
|
|
|
|
{
|
2023-09-25 19:41:32 -04:00
|
|
|
type: Number,
|
2023-10-03 01:02:05 -04:00
|
|
|
ref: "User",
|
|
|
|
},
|
|
|
|
],
|
|
|
|
notifyOnReviewReply: {
|
|
|
|
type: Boolean,
|
|
|
|
default: true,
|
2023-09-25 19:41:32 -04:00
|
|
|
},
|
2023-10-03 01:02:05 -04:00
|
|
|
blocked: [
|
|
|
|
{
|
|
|
|
type: Number,
|
|
|
|
ref: "User",
|
|
|
|
},
|
|
|
|
],
|
2023-09-25 19:41:32 -04:00
|
|
|
sessionId: {
|
|
|
|
type: String,
|
2023-10-03 01:02:05 -04:00
|
|
|
default: null,
|
2023-09-25 19:41:32 -04:00
|
|
|
},
|
|
|
|
banned: {
|
|
|
|
type: Boolean,
|
2023-10-03 01:02:05 -04:00
|
|
|
default: false,
|
2023-09-25 19:41:32 -04:00
|
|
|
},
|
2023-10-03 01:02:05 -04:00
|
|
|
quickMenuConfig: [QuickMenuSchema],
|
|
|
|
});
|
2023-09-25 19:41:32 -04:00
|
|
|
|
2023-10-03 01:02:05 -04:00
|
|
|
UserSchema.static("generateHash", function (password: string): string {
|
2023-09-25 19:41:32 -04:00
|
|
|
return bcrypt.hashSync(password, bcrypt.genSaltSync(8));
|
|
|
|
});
|
2023-10-03 01:02:05 -04:00
|
|
|
UserSchema.methods.validPassword = function (password: string): boolean {
|
|
|
|
return (
|
|
|
|
md5(password) === this.password ||
|
|
|
|
bcrypt.compareSync(password, this.password) ||
|
|
|
|
false
|
|
|
|
);
|
|
|
|
};
|
2023-09-25 19:41:32 -04:00
|
|
|
|
2023-12-20 19:56:33 -05:00
|
|
|
UserSchema.methods.generateJWT = function (jwtKey: string): string {
|
2023-10-03 01:02:05 -04:00
|
|
|
let token = jwt.sign(
|
|
|
|
{ id: this._id, isAdmin: this.profile.isAdmin },
|
|
|
|
jwtKey,
|
|
|
|
{
|
|
|
|
expiresIn: "14 days",
|
|
|
|
},
|
|
|
|
);
|
|
|
|
return token;
|
|
|
|
};
|
2023-09-25 19:41:32 -04:00
|
|
|
|
2023-10-03 01:02:05 -04:00
|
|
|
hasMigrated &&
|
2023-10-12 22:28:37 -04:00
|
|
|
!mongoose.models.User &&
|
2023-10-03 01:02:05 -04:00
|
|
|
UserSchema.plugin(AutoIncrement, { id: "userid", inc_field: "_id" });
|
|
|
|
export const User = mongoose.model<IUser, UModel>("User", UserSchema, "users");
|