362 lines
13 KiB
TypeScript
362 lines
13 KiB
TypeScript
import {
|
|
sqliteTable,
|
|
text,
|
|
integer,
|
|
real,
|
|
uniqueIndex,
|
|
} from "drizzle-orm/sqlite-core";
|
|
import { createInsertSchema, createSelectSchema } from "drizzle-zod";
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Better Auth core tables
|
|
// ---------------------------------------------------------------------------
|
|
|
|
export const users = sqliteTable("users", {
|
|
id: text("id").primaryKey(),
|
|
name: text("name").notNull(),
|
|
email: text("email").notNull().unique(),
|
|
emailVerified: integer("email_verified", { mode: "boolean" })
|
|
.notNull()
|
|
.default(false),
|
|
image: text("image"),
|
|
role: text("role", {
|
|
enum: ["superadmin", "admin", "moderator"],
|
|
})
|
|
.notNull()
|
|
.default("moderator"),
|
|
createdAt: integer("created_at", { mode: "timestamp_ms" }).notNull(),
|
|
updatedAt: integer("updated_at", { mode: "timestamp_ms" }).notNull(),
|
|
});
|
|
|
|
export const sessions = sqliteTable("sessions", {
|
|
id: text("id").primaryKey(),
|
|
userId: text("user_id")
|
|
.notNull()
|
|
.references(() => users.id, { onDelete: "cascade" }),
|
|
token: text("token").notNull().unique(),
|
|
expiresAt: integer("expires_at", { mode: "timestamp_ms" }).notNull(),
|
|
ipAddress: text("ip_address"),
|
|
userAgent: text("user_agent"),
|
|
createdAt: integer("created_at", { mode: "timestamp_ms" }).notNull(),
|
|
updatedAt: integer("updated_at", { mode: "timestamp_ms" }).notNull(),
|
|
});
|
|
|
|
export const accounts = sqliteTable("accounts", {
|
|
id: text("id").primaryKey(),
|
|
userId: text("user_id")
|
|
.notNull()
|
|
.references(() => users.id, { onDelete: "cascade" }),
|
|
accountId: text("account_id").notNull(),
|
|
providerId: text("provider_id").notNull(),
|
|
accessToken: text("access_token"),
|
|
refreshToken: text("refresh_token"),
|
|
idToken: text("id_token"),
|
|
expiresAt: integer("expires_at", { mode: "timestamp_ms" }),
|
|
password: text("password"), // hashed password for email/password auth
|
|
createdAt: integer("created_at", { mode: "timestamp_ms" }).notNull(),
|
|
updatedAt: integer("updated_at", { mode: "timestamp_ms" }).notNull(),
|
|
});
|
|
|
|
export const verifications = sqliteTable("verifications", {
|
|
id: text("id").primaryKey(),
|
|
identifier: text("identifier").notNull(),
|
|
value: text("value").notNull(),
|
|
expiresAt: integer("expires_at", { mode: "timestamp_ms" }).notNull(),
|
|
createdAt: integer("created_at", { mode: "timestamp_ms" }).notNull(),
|
|
updatedAt: integer("updated_at", { mode: "timestamp_ms" }).notNull(),
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Invitation system
|
|
// ---------------------------------------------------------------------------
|
|
|
|
export const invitations = sqliteTable("invitations", {
|
|
id: text("id").primaryKey(),
|
|
email: text("email").notNull(),
|
|
role: text("role", {
|
|
enum: ["superadmin", "admin", "moderator"],
|
|
})
|
|
.notNull()
|
|
.default("moderator"),
|
|
invitedBy: text("invited_by")
|
|
.notNull()
|
|
.references(() => users.id, { onDelete: "cascade" }),
|
|
token: text("token").notNull().unique(),
|
|
expiresAt: integer("expires_at").notNull(),
|
|
acceptedAt: integer("accepted_at"),
|
|
createdAt: integer("created_at").notNull(),
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Minecraft player management
|
|
// ---------------------------------------------------------------------------
|
|
|
|
export const mcPlayers = sqliteTable(
|
|
"mc_players",
|
|
{
|
|
id: text("id").primaryKey(), // uuid
|
|
uuid: text("uuid").notNull(), // Minecraft UUID
|
|
username: text("username").notNull(),
|
|
firstSeen: integer("first_seen"),
|
|
lastSeen: integer("last_seen"),
|
|
isOnline: integer("is_online", { mode: "boolean" }).notNull().default(false),
|
|
playTime: integer("play_time").notNull().default(0), // minutes
|
|
role: text("role"),
|
|
isBanned: integer("is_banned", { mode: "boolean" })
|
|
.notNull()
|
|
.default(false),
|
|
notes: text("notes"),
|
|
},
|
|
(table) => [uniqueIndex("mc_players_uuid_idx").on(table.uuid)],
|
|
);
|
|
|
|
export const playerBans = sqliteTable("player_bans", {
|
|
id: text("id").primaryKey(),
|
|
playerId: text("player_id")
|
|
.notNull()
|
|
.references(() => mcPlayers.id, { onDelete: "cascade" }),
|
|
reason: text("reason"),
|
|
bannedBy: text("banned_by").references(() => users.id, {
|
|
onDelete: "set null",
|
|
}),
|
|
bannedAt: integer("banned_at").notNull(),
|
|
expiresAt: integer("expires_at"),
|
|
isActive: integer("is_active", { mode: "boolean" }).notNull().default(true),
|
|
unbannedBy: text("unbanned_by").references(() => users.id, {
|
|
onDelete: "set null",
|
|
}),
|
|
unbannedAt: integer("unbanned_at"),
|
|
});
|
|
|
|
export const playerChatHistory = sqliteTable("player_chat_history", {
|
|
id: text("id").primaryKey(),
|
|
playerId: text("player_id")
|
|
.notNull()
|
|
.references(() => mcPlayers.id, { onDelete: "cascade" }),
|
|
message: text("message").notNull(),
|
|
channel: text("channel"),
|
|
timestamp: integer("timestamp").notNull(),
|
|
serverId: text("server_id"),
|
|
});
|
|
|
|
export const playerSpawnPoints = sqliteTable("player_spawn_points", {
|
|
id: text("id").primaryKey(),
|
|
playerId: text("player_id")
|
|
.notNull()
|
|
.references(() => mcPlayers.id, { onDelete: "cascade" }),
|
|
name: text("name").notNull(),
|
|
world: text("world").notNull(),
|
|
x: real("x").notNull(),
|
|
y: real("y").notNull(),
|
|
z: real("z").notNull(),
|
|
createdAt: integer("created_at").notNull(),
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Plugin management
|
|
// ---------------------------------------------------------------------------
|
|
|
|
export const plugins = sqliteTable("plugins", {
|
|
id: text("id").primaryKey(),
|
|
name: text("name").notNull(),
|
|
version: text("version"),
|
|
description: text("description"),
|
|
isEnabled: integer("is_enabled", { mode: "boolean" })
|
|
.notNull()
|
|
.default(true),
|
|
jarFile: text("jar_file"),
|
|
config: text("config"), // JSON blob
|
|
installedAt: integer("installed_at").notNull(),
|
|
updatedAt: integer("updated_at").notNull(),
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Backup management
|
|
// ---------------------------------------------------------------------------
|
|
|
|
export const backups = sqliteTable("backups", {
|
|
id: text("id").primaryKey(),
|
|
name: text("name").notNull(),
|
|
type: text("type", {
|
|
enum: ["worlds", "plugins", "config", "full"],
|
|
}).notNull(),
|
|
size: integer("size"), // bytes
|
|
path: text("path"),
|
|
createdAt: integer("created_at").notNull(),
|
|
status: text("status", {
|
|
enum: ["pending", "running", "completed", "failed"],
|
|
})
|
|
.notNull()
|
|
.default("pending"),
|
|
triggeredBy: text("triggered_by").references(() => users.id, {
|
|
onDelete: "set null",
|
|
}),
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Scheduled tasks
|
|
// ---------------------------------------------------------------------------
|
|
|
|
export const scheduledTasks = sqliteTable("scheduled_tasks", {
|
|
id: text("id").primaryKey(),
|
|
name: text("name").notNull(),
|
|
description: text("description"),
|
|
cronExpression: text("cron_expression").notNull(),
|
|
command: text("command").notNull(), // MC command to run
|
|
isEnabled: integer("is_enabled", { mode: "boolean" })
|
|
.notNull()
|
|
.default(true),
|
|
lastRun: integer("last_run"),
|
|
nextRun: integer("next_run"),
|
|
createdAt: integer("created_at").notNull(),
|
|
updatedAt: integer("updated_at").notNull(),
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Audit logs
|
|
// ---------------------------------------------------------------------------
|
|
|
|
export const auditLogs = sqliteTable("audit_logs", {
|
|
id: text("id").primaryKey(),
|
|
userId: text("user_id").references(() => users.id, { onDelete: "set null" }),
|
|
action: text("action").notNull(),
|
|
target: text("target"),
|
|
targetId: text("target_id"),
|
|
details: text("details"), // JSON blob
|
|
ipAddress: text("ip_address"),
|
|
createdAt: integer("created_at").notNull(),
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Server settings (singleton row, id = 1)
|
|
// ---------------------------------------------------------------------------
|
|
|
|
export const serverSettings = sqliteTable("server_settings", {
|
|
id: integer("id").primaryKey().default(1),
|
|
minecraftPath: text("minecraft_path"),
|
|
serverJar: text("server_jar"),
|
|
serverVersion: text("server_version"),
|
|
serverType: text("server_type", {
|
|
enum: ["vanilla", "paper", "spigot", "bukkit", "fabric", "forge", "bedrock"],
|
|
}),
|
|
maxRam: integer("max_ram").default(4096),
|
|
minRam: integer("min_ram").default(1024),
|
|
rconEnabled: integer("rcon_enabled", { mode: "boolean" })
|
|
.notNull()
|
|
.default(false),
|
|
rconPort: integer("rcon_port").default(25575),
|
|
rconPassword: text("rcon_password"), // stored encrypted
|
|
javaArgs: text("java_args"),
|
|
autoStart: integer("auto_start", { mode: "boolean" })
|
|
.notNull()
|
|
.default(false),
|
|
restartOnCrash: integer("restart_on_crash", { mode: "boolean" })
|
|
.notNull()
|
|
.default(false),
|
|
backupEnabled: integer("backup_enabled", { mode: "boolean" })
|
|
.notNull()
|
|
.default(false),
|
|
backupSchedule: text("backup_schedule"),
|
|
bluemapEnabled: integer("bluemap_enabled", { mode: "boolean" })
|
|
.notNull()
|
|
.default(false),
|
|
bluemapUrl: text("bluemap_url"),
|
|
updatedAt: integer("updated_at").notNull(),
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Zod schemas (insert + select) for each table
|
|
// ---------------------------------------------------------------------------
|
|
|
|
export const insertUserSchema = createInsertSchema(users);
|
|
export const selectUserSchema = createSelectSchema(users);
|
|
|
|
export const insertSessionSchema = createInsertSchema(sessions);
|
|
export const selectSessionSchema = createSelectSchema(sessions);
|
|
|
|
export const insertAccountSchema = createInsertSchema(accounts);
|
|
export const selectAccountSchema = createSelectSchema(accounts);
|
|
|
|
export const insertVerificationSchema = createInsertSchema(verifications);
|
|
export const selectVerificationSchema = createSelectSchema(verifications);
|
|
|
|
export const insertInvitationSchema = createInsertSchema(invitations);
|
|
export const selectInvitationSchema = createSelectSchema(invitations);
|
|
|
|
export const insertMcPlayerSchema = createInsertSchema(mcPlayers);
|
|
export const selectMcPlayerSchema = createSelectSchema(mcPlayers);
|
|
|
|
export const insertPlayerBanSchema = createInsertSchema(playerBans);
|
|
export const selectPlayerBanSchema = createSelectSchema(playerBans);
|
|
|
|
export const insertPlayerChatHistorySchema =
|
|
createInsertSchema(playerChatHistory);
|
|
export const selectPlayerChatHistorySchema =
|
|
createSelectSchema(playerChatHistory);
|
|
|
|
export const insertPlayerSpawnPointSchema =
|
|
createInsertSchema(playerSpawnPoints);
|
|
export const selectPlayerSpawnPointSchema =
|
|
createSelectSchema(playerSpawnPoints);
|
|
|
|
export const insertPluginSchema = createInsertSchema(plugins);
|
|
export const selectPluginSchema = createSelectSchema(plugins);
|
|
|
|
export const insertBackupSchema = createInsertSchema(backups);
|
|
export const selectBackupSchema = createSelectSchema(backups);
|
|
|
|
export const insertScheduledTaskSchema = createInsertSchema(scheduledTasks);
|
|
export const selectScheduledTaskSchema = createSelectSchema(scheduledTasks);
|
|
|
|
export const insertAuditLogSchema = createInsertSchema(auditLogs);
|
|
export const selectAuditLogSchema = createSelectSchema(auditLogs);
|
|
|
|
export const insertServerSettingsSchema = createInsertSchema(serverSettings);
|
|
export const selectServerSettingsSchema = createSelectSchema(serverSettings);
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Inferred TypeScript types
|
|
// ---------------------------------------------------------------------------
|
|
|
|
export type User = typeof users.$inferSelect;
|
|
export type NewUser = typeof users.$inferInsert;
|
|
|
|
export type Session = typeof sessions.$inferSelect;
|
|
export type NewSession = typeof sessions.$inferInsert;
|
|
|
|
export type Account = typeof accounts.$inferSelect;
|
|
export type NewAccount = typeof accounts.$inferInsert;
|
|
|
|
export type Verification = typeof verifications.$inferSelect;
|
|
export type NewVerification = typeof verifications.$inferInsert;
|
|
|
|
export type Invitation = typeof invitations.$inferSelect;
|
|
export type NewInvitation = typeof invitations.$inferInsert;
|
|
|
|
export type McPlayer = typeof mcPlayers.$inferSelect;
|
|
export type NewMcPlayer = typeof mcPlayers.$inferInsert;
|
|
|
|
export type PlayerBan = typeof playerBans.$inferSelect;
|
|
export type NewPlayerBan = typeof playerBans.$inferInsert;
|
|
|
|
export type PlayerChatHistory = typeof playerChatHistory.$inferSelect;
|
|
export type NewPlayerChatHistory = typeof playerChatHistory.$inferInsert;
|
|
|
|
export type PlayerSpawnPoint = typeof playerSpawnPoints.$inferSelect;
|
|
export type NewPlayerSpawnPoint = typeof playerSpawnPoints.$inferInsert;
|
|
|
|
export type Plugin = typeof plugins.$inferSelect;
|
|
export type NewPlugin = typeof plugins.$inferInsert;
|
|
|
|
export type Backup = typeof backups.$inferSelect;
|
|
export type NewBackup = typeof backups.$inferInsert;
|
|
|
|
export type ScheduledTask = typeof scheduledTasks.$inferSelect;
|
|
export type NewScheduledTask = typeof scheduledTasks.$inferInsert;
|
|
|
|
export type AuditLog = typeof auditLogs.$inferSelect;
|
|
export type NewAuditLog = typeof auditLogs.$inferInsert;
|
|
|
|
export type ServerSettings = typeof serverSettings.$inferSelect;
|
|
export type NewServerSettings = typeof serverSettings.$inferInsert;
|