mirror of
https://github.com/rmoren97/mc-manager.git
synced 2026-03-28 17:26:47 -07:00
200 lines
7.1 KiB
TypeScript
200 lines
7.1 KiB
TypeScript
import mongoose, { Schema, Document, Model } from 'mongoose'
|
|
|
|
// ─── User ────────────────────────────────────────────────────────
|
|
|
|
export interface IUser extends Document {
|
|
username: string
|
|
email: string
|
|
passwordHash: string
|
|
roles: mongoose.Types.ObjectId[]
|
|
twoFactorCode: string | null
|
|
twoFactorExpiry: Date | null
|
|
loginAttempts: number
|
|
lockUntil: Date | null
|
|
status: 'active' | 'inactive' | 'locked'
|
|
lastLogin: Date | null
|
|
createdAt: Date
|
|
updatedAt: Date
|
|
}
|
|
|
|
const userSchema = new Schema<IUser>(
|
|
{
|
|
username: { type: String, required: true, unique: true, trim: true },
|
|
email: { type: String, required: true, unique: true, trim: true, lowercase: true },
|
|
passwordHash: { type: String, required: true },
|
|
roles: [{ type: Schema.Types.ObjectId, ref: 'Role' }],
|
|
twoFactorCode: { type: String, default: null },
|
|
twoFactorExpiry: { type: Date, default: null },
|
|
loginAttempts: { type: Number, default: 0 },
|
|
lockUntil: { type: Date, default: null },
|
|
status: { type: String, enum: ['active', 'inactive', 'locked'], default: 'active' },
|
|
lastLogin: { type: Date, default: null },
|
|
},
|
|
{ timestamps: true }
|
|
)
|
|
|
|
// ─── Role ────────────────────────────────────────────────────────
|
|
|
|
export interface IPermission {
|
|
resource: string
|
|
actions: string[]
|
|
}
|
|
|
|
export interface IRole extends Document {
|
|
name: string
|
|
permissions: IPermission[]
|
|
description: string
|
|
isDefault: boolean
|
|
createdAt: Date
|
|
updatedAt: Date
|
|
}
|
|
|
|
const roleSchema = new Schema<IRole>(
|
|
{
|
|
name: { type: String, required: true, unique: true, trim: true },
|
|
permissions: [
|
|
{
|
|
resource: { type: String, required: true },
|
|
actions: [{ type: String, required: true }],
|
|
},
|
|
],
|
|
description: { type: String, default: '' },
|
|
isDefault: { type: Boolean, default: false },
|
|
},
|
|
{ timestamps: true }
|
|
)
|
|
|
|
// ─── Server ──────────────────────────────────────────────────────
|
|
|
|
export interface IServer extends Document {
|
|
name: string
|
|
type: 'vanilla' | 'bukkit' | 'forge' | 'fabric'
|
|
version: string
|
|
dockerImage: string
|
|
containerId: string | null
|
|
containerName: string
|
|
port: number
|
|
rconPort: number | null
|
|
status: 'online' | 'offline' | 'starting' | 'stopping' | 'crashed'
|
|
maxPlayers: number
|
|
memory: { min: number; max: number }
|
|
jvmArgs: string[]
|
|
autoStart: boolean
|
|
autoRestart: boolean
|
|
backupSchedule: string | null
|
|
backupRetention: number
|
|
admins: mongoose.Types.ObjectId[]
|
|
createdBy: mongoose.Types.ObjectId
|
|
createdAt: Date
|
|
updatedAt: Date
|
|
}
|
|
|
|
const serverSchema = new Schema<IServer>(
|
|
{
|
|
name: { type: String, required: true, trim: true },
|
|
type: { type: String, required: true, enum: ['vanilla', 'bukkit', 'forge', 'fabric'] },
|
|
version: { type: String, required: true },
|
|
dockerImage: { type: String, default: 'itzg/minecraft-server' },
|
|
containerId: { type: String, default: null },
|
|
containerName: { type: String, required: true, unique: true },
|
|
port: { type: Number, required: true },
|
|
rconPort: { type: Number, default: null },
|
|
status: {
|
|
type: String,
|
|
enum: ['online', 'offline', 'starting', 'stopping', 'crashed'],
|
|
default: 'offline',
|
|
},
|
|
maxPlayers: { type: Number, default: 20 },
|
|
memory: {
|
|
min: { type: Number, default: 512 },
|
|
max: { type: Number, default: 1024 },
|
|
},
|
|
jvmArgs: [{ type: String }],
|
|
autoStart: { type: Boolean, default: false },
|
|
autoRestart: { type: Boolean, default: true },
|
|
backupSchedule: { type: String, default: null },
|
|
backupRetention: { type: Number, default: 5 },
|
|
admins: [{ type: Schema.Types.ObjectId, ref: 'User', default: [] }],
|
|
createdBy: { type: Schema.Types.ObjectId, ref: 'User', required: true },
|
|
},
|
|
{ timestamps: true }
|
|
)
|
|
|
|
// ─── Backup ──────────────────────────────────────────────────────
|
|
|
|
export interface IBackup extends Document {
|
|
serverId: mongoose.Types.ObjectId
|
|
filename: string
|
|
filePath: string
|
|
fileSize: number
|
|
type: 'manual' | 'scheduled'
|
|
status: 'completed' | 'in_progress' | 'failed'
|
|
createdBy: mongoose.Types.ObjectId
|
|
createdAt: Date
|
|
}
|
|
|
|
const backupSchema = new Schema<IBackup>(
|
|
{
|
|
serverId: { type: Schema.Types.ObjectId, ref: 'Server', required: true, index: true },
|
|
filename: { type: String, required: true },
|
|
filePath: { type: String, required: true },
|
|
fileSize: { type: Number, default: 0 },
|
|
type: { type: String, enum: ['manual', 'scheduled'], required: true },
|
|
status: {
|
|
type: String,
|
|
enum: ['completed', 'in_progress', 'failed'],
|
|
default: 'in_progress',
|
|
},
|
|
createdBy: { type: Schema.Types.ObjectId, ref: 'User' },
|
|
},
|
|
{ timestamps: true }
|
|
)
|
|
|
|
// ─── Audit Log ───────────────────────────────────────────────────
|
|
|
|
export interface IAuditLog extends Document {
|
|
action: string
|
|
entityType: string
|
|
entityId?: string
|
|
entityName?: string
|
|
userId?: string
|
|
userName?: string
|
|
userEmail?: string
|
|
previousValues: Record<string, unknown> | null
|
|
newValues: Record<string, unknown> | null
|
|
changes: Record<string, string> | null
|
|
clientIP: string
|
|
status: 'SUCCESS' | 'FAILED'
|
|
statusCode: number
|
|
errorMessage?: string
|
|
createdAt: Date
|
|
}
|
|
|
|
const auditLogSchema = new Schema<IAuditLog>(
|
|
{
|
|
action: { type: String, required: true, index: true },
|
|
entityType: { type: String, required: true, index: true },
|
|
entityId: { type: String, default: '' },
|
|
entityName: { type: String, default: '' },
|
|
userId: { type: String, default: '', index: true },
|
|
userName: { type: String, default: '' },
|
|
userEmail: { type: String, default: '' },
|
|
previousValues: { type: Schema.Types.Mixed, default: null },
|
|
newValues: { type: Schema.Types.Mixed, default: null },
|
|
changes: { type: Schema.Types.Mixed, default: null },
|
|
clientIP: { type: String, default: '' },
|
|
status: { type: String, enum: ['SUCCESS', 'FAILED'], required: true },
|
|
statusCode: { type: Number, required: true },
|
|
errorMessage: { type: String },
|
|
},
|
|
{ timestamps: true }
|
|
)
|
|
|
|
// ─── Model Exports (prevent re-compilation in dev) ───────────────
|
|
|
|
export const User: Model<IUser> = mongoose.models.User || mongoose.model<IUser>('User', userSchema)
|
|
export const Role: Model<IRole> = mongoose.models.Role || mongoose.model<IRole>('Role', roleSchema)
|
|
export const Server: Model<IServer> = mongoose.models.Server || mongoose.model<IServer>('Server', serverSchema)
|
|
export const Backup: Model<IBackup> = mongoose.models.Backup || mongoose.model<IBackup>('Backup', backupSchema)
|
|
export const AuditLog: Model<IAuditLog> = mongoose.models.AuditLog || mongoose.model<IAuditLog>('AuditLog', auditLogSchema)
|