import { sql } from "drizzle-orm"; import { boolean, check, index, integer, inet, jsonb, pgEnum, pgTable, text, timestamp, uniqueIndex, uuid, varchar, } from "drizzle-orm/pg-core"; function timestamps() { return { createdAt: timestamp("created_at", { withTimezone: true, mode: "date", precision: 3 }) .notNull() .defaultNow(), updatedAt: timestamp("updated_at", { withTimezone: true, mode: "date", precision: 3 }) .notNull() .defaultNow(), }; } function createdAt() { return timestamp("created_at", { withTimezone: true, mode: "date", precision: 3 }) .notNull() .defaultNow(); } export const minecraftValidationStatus = pgEnum("minecraft_validation_status", [ "verified", "user_confirmed", ]); export const ipObservationSource = pgEnum("ip_observation_source", ["web", "game"]); export const ipClassification = pgEnum("ip_classification", [ "unknown", "clear", "vpn", "proxy", "hosting", "tor", ]); export const users = pgTable( "users", { id: uuid("id").primaryKey().defaultRandom(), discordUserId: text("discord_user_id").notNull(), discordUsername: text("discord_username").notNull(), discordGlobalName: text("discord_global_name"), firstName: text("first_name"), onboardingCompletedAt: timestamp("onboarding_completed_at", { withTimezone: true, mode: "date", precision: 3, }), ...timestamps(), }, (table) => [uniqueIndex("users_discord_user_id_uidx").on(table.discordUserId)], ); export const groups = pgTable( "groups", { id: uuid("id").primaryKey().defaultRandom(), name: varchar("name", { length: 50 }).notNull(), slug: varchar("slug", { length: 50 }).notNull(), description: text("description"), accessEnabled: boolean("access_enabled").notNull().default(false), anonymizedNetworksAllowed: boolean("anonymized_networks_allowed").notNull().default(false), isDefault: boolean("is_default").notNull().default(false), ...timestamps(), }, (table) => [ uniqueIndex("groups_slug_uidx").on(sql`lower(${table.slug})`), uniqueIndex("groups_one_default_uidx").on(table.isDefault).where(sql`${table.isDefault} = true`), ], ); export const groupAccessWindows = pgTable( "group_access_windows", { id: uuid("id").primaryKey().defaultRandom(), groupId: uuid("group_id") .notNull() .references(() => groups.id, { onDelete: "cascade" }), startMinuteOfWeek: integer("start_minute_of_week").notNull(), endMinuteOfWeek: integer("end_minute_of_week").notNull(), createdAt: createdAt(), }, (table) => [ index("group_access_windows_group_idx").on(table.groupId), check( "group_access_windows_minute_range_check", sql`${table.startMinuteOfWeek} >= 0 and ${table.startMinuteOfWeek} < 10080 and ${table.endMinuteOfWeek} >= 0 and ${table.endMinuteOfWeek} < 10080 and ${table.startMinuteOfWeek} <> ${table.endMinuteOfWeek}`, ), ], ); export const userGroupMemberships = pgTable( "user_group_memberships", { userId: uuid("user_id") .notNull() .references(() => users.id, { onDelete: "cascade" }), groupId: uuid("group_id") .notNull() .references(() => groups.id, { onDelete: "cascade" }), createdAt: createdAt(), }, (table) => [ uniqueIndex("user_group_memberships_user_uidx").on(table.userId), index("user_group_memberships_group_idx").on(table.groupId), ], ); export const minecraftAccounts = pgTable( "minecraft_accounts", { id: uuid("id").primaryKey().defaultRandom(), userId: uuid("user_id") .notNull() .references(() => users.id, { onDelete: "cascade" }), minecraftUuid: varchar("minecraft_uuid", { length: 32 }), username: varchar("username", { length: 16 }).notNull(), validationStatus: minecraftValidationStatus("validation_status").notNull(), isPrimary: boolean("is_primary").notNull().default(false), lastVerifiedAt: timestamp("last_verified_at", { withTimezone: true, mode: "date", precision: 3 }), deletedAt: timestamp("deleted_at", { withTimezone: true, mode: "date", precision: 3 }), ...timestamps(), }, (table) => [ index("minecraft_accounts_user_idx").on(table.userId), uniqueIndex("minecraft_accounts_active_uuid_uidx") .on(table.minecraftUuid) .where(sql`${table.deletedAt} is null and ${table.minecraftUuid} is not null`), uniqueIndex("minecraft_accounts_active_username_uidx") .on(sql`lower(${table.username})`) .where(sql`${table.deletedAt} is null`), uniqueIndex("minecraft_accounts_one_primary_per_user_uidx") .on(table.userId) .where(sql`${table.isPrimary} = true and ${table.deletedAt} is null`), ], ); export const loginCodes = pgTable( "login_codes", { id: uuid("id").primaryKey().defaultRandom(), tokenHash: text("token_hash").notNull(), discordUserId: text("discord_user_id").notNull(), discordUsername: text("discord_username").notNull(), discordGlobalName: text("discord_global_name"), expiresAt: timestamp("expires_at", { withTimezone: true, mode: "date", precision: 3 }).notNull(), consumedAt: timestamp("consumed_at", { withTimezone: true, mode: "date", precision: 3 }), createdAt: createdAt(), }, (table) => [ uniqueIndex("login_codes_token_hash_uidx").on(table.tokenHash), index("login_codes_discord_user_idx").on(table.discordUserId), index("login_codes_expires_idx").on(table.expiresAt), ], ); export const sessions = pgTable( "sessions", { id: uuid("id").primaryKey().defaultRandom(), userId: uuid("user_id") .notNull() .references(() => users.id, { onDelete: "cascade" }), tokenHash: text("token_hash").notNull(), expiresAt: timestamp("expires_at", { withTimezone: true, mode: "date", precision: 3 }).notNull(), lastSeenAt: timestamp("last_seen_at", { withTimezone: true, mode: "date", precision: 3 }) .notNull() .defaultNow(), revokedAt: timestamp("revoked_at", { withTimezone: true, mode: "date", precision: 3 }), createdAt: createdAt(), }, (table) => [ uniqueIndex("sessions_token_hash_uidx").on(table.tokenHash), index("sessions_user_idx").on(table.userId), index("sessions_expires_idx").on(table.expiresAt), ], ); export const appSettings = pgTable("app_settings", { id: text("id").primaryKey().default("default"), registrationMessage: text("registration_message") .notNull() .default("Please register your Minecraft account before joining."), groupAccessDeniedMessage: text("group_access_denied_message") .notNull() .default("Your account group does not currently have server access. Contact a host if you believe this is a mistake."), vpnDeniedMessage: text("vpn_denied_message") .notNull() .default("VPN, proxy, and Tor connections are not allowed. Contact a host to request an exception."), scheduledAccessDeniedMessage: text("scheduled_access_denied_message") .notNull() .default("Your group is only allowed access from {next_start} to {next_end}."), ...timestamps(), }); export const rconServers = pgTable( "rcon_servers", { id: uuid("id").primaryKey().defaultRandom(), name: varchar("name", { length: 100 }).notNull(), host: varchar("host", { length: 253 }).notNull(), port: integer("port").notNull().default(25575), encryptedPassword: text("encrypted_password").notNull(), enabled: boolean("enabled").notNull().default(false), ...timestamps(), }, (table) => [ uniqueIndex("rcon_servers_name_uidx").on(sql`lower(${table.name})`), check("rcon_servers_port_check", sql`${table.port} between 1 and 65535`), ], ); export const ipIntelligence = pgTable("ip_intelligence", { ipAddress: inet("ip_address").primaryKey(), classification: ipClassification("classification").notNull().default("unknown"), provider: text("provider"), rawResponse: jsonb("raw_response").$type>(), checkedAt: timestamp("checked_at", { withTimezone: true, mode: "date", precision: 3 }), expiresAt: timestamp("expires_at", { withTimezone: true, mode: "date", precision: 3 }), ...timestamps(), }); export const ipObservations = pgTable( "ip_observations", { id: uuid("id").primaryKey().defaultRandom(), userId: uuid("user_id").references(() => users.id, { onDelete: "set null" }), minecraftAccountId: uuid("minecraft_account_id").references(() => minecraftAccounts.id, { onDelete: "set null", }), source: ipObservationSource("source").notNull(), ipAddress: inet("ip_address").notNull(), minecraftUuid: varchar("minecraft_uuid", { length: 32 }), username: varchar("username", { length: 16 }), classification: ipClassification("classification").notNull().default("unknown"), observedAt: timestamp("observed_at", { withTimezone: true, mode: "date", precision: 3 }) .notNull() .defaultNow(), }, (table) => [ index("ip_observations_user_observed_idx").on(table.userId, table.observedAt), index("ip_observations_account_observed_idx").on(table.minecraftAccountId, table.observedAt), ], ); export const pluginCredentials = pgTable( "plugin_credentials", { id: uuid("id").primaryKey().defaultRandom(), serverId: text("server_id").notNull(), secretHash: text("secret_hash").notNull(), revokedAt: timestamp("revoked_at", { withTimezone: true, mode: "date", precision: 3 }), ...timestamps(), }, (table) => [uniqueIndex("plugin_credentials_server_id_uidx").on(table.serverId)], ); export const pluginRequests = pgTable( "plugin_requests", { requestId: uuid("request_id").primaryKey(), serverId: text("server_id") .notNull() .references(() => pluginCredentials.serverId, { onDelete: "cascade" }), receivedAt: timestamp("received_at", { withTimezone: true, mode: "date", precision: 3 }) .notNull() .defaultNow(), expiresAt: timestamp("expires_at", { withTimezone: true, mode: "date", precision: 3 }).notNull(), }, (table) => [index("plugin_requests_expires_idx").on(table.expiresAt)], ); export const events = pgTable( "events", { id: uuid("id").primaryKey(), specVersion: text("spec_version").notNull().default("1.0"), source: text("source").notNull(), type: text("type").notNull(), subject: text("subject"), time: timestamp("time", { withTimezone: true, mode: "date", precision: 3 }).notNull(), dataContentType: text("data_content_type").notNull().default("application/json"), dataSchema: text("data_schema"), data: jsonb("data").$type>().notNull(), actorUserId: uuid("actor_user_id").references(() => users.id, { onDelete: "set null" }), ipAddress: inet("ip_address"), correlationId: uuid("correlation_id"), publishedAt: timestamp("published_at", { withTimezone: true, mode: "date", precision: 3 }), createdAt: createdAt(), }, (table) => [ index("events_time_idx").on(table.time), index("events_type_time_idx").on(table.type, table.time), index("events_subject_time_idx").on(table.subject, table.time), index("events_unpublished_idx").on(table.createdAt).where(sql`${table.publishedAt} is null`), ], );