fix(security): resolve audit findings — secrets, env contract, migrations
Removes hardcoded fallback secrets and makes a misconfigured deploy fail loudly instead of silently falling back to development defaults. - Remove insecure JWT fallback secrets (messages.module, configuration) - Remove the 'default-secret' fallback for the 2FA TOTP encryption key and allow a dedicated TWO_FACTOR_ENCRYPTION_KEY so rotating JWT_SECRET no longer locks out every 2FA user (see docs/2fa-key-rotation.md) - Require EMAIL_API_URL; drop the hardcoded vendor email endpoint - Drive WebSocket CORS from CORS_ORIGINS instead of origin:'*' - Load .env before any Nest module is imported (src/load-env.ts). Decorator arguments evaluate at import time, so the gateway previously froze its CORS config to the localhost fallback even when CORS_ORIGINS was set - Add boot-time env validation: missing required vars, weak JWT_SECRET, and inverted access/refresh token lifetimes now abort startup - Enable Redis TLS certificate verification - Require ADMIN_EMAIL/ADMIN_PASSWORD for the seed; remove the published default super-admin credentials and stop printing them - Add the initial Prisma migration and stop gitignoring prisma/migrations - Make .env.example an accurate configuration contract (admin bootstrap, REDIS_TLS, S3_ENDPOINT, 2FA key, Firebase path; drop the dead SMTP block) - Add handover documentation: architecture, ER model, sequence and data-flow diagrams, 2FA key rotation runbook Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
793
prisma/migrations/20260721102313_init/migration.sql
Normal file
793
prisma/migrations/20260721102313_init/migration.sql
Normal file
@@ -0,0 +1,793 @@
|
||||
-- CreateEnum
|
||||
CREATE TYPE "UserRole" AS ENUM ('USER', 'AGENT', 'ADMIN', 'SUPER_ADMIN');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "UserStatus" AS ENUM ('ACTIVE', 'INACTIVE', 'SUSPENDED', 'PENDING_VERIFICATION');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "AuthProvider" AS ENUM ('LOCAL', 'GOOGLE', 'FACEBOOK', 'TWITTER', 'APPLE');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "FieldType" AS ENUM ('TEXT', 'TEXTAREA', 'CHECKBOX', 'CHECKBOX_GROUP', 'RADIO', 'SELECT', 'MULTI_SELECT', 'RANGE', 'NUMBER', 'DATE', 'TAG_INPUT', 'FILE', 'REPEATER');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "VerificationStatus" AS ENUM ('NONE', 'PENDING_REVIEW', 'APPROVED', 'REJECTED');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "ConnectionStatus" AS ENUM ('PENDING', 'ACCEPTED', 'REJECTED');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "MessageType" AS ENUM ('TEXT', 'FILE', 'IMAGE', 'SYSTEM');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "MessageStatus" AS ENUM ('SENT', 'DELIVERED', 'READ');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "SupportChatStatus" AS ENUM ('OPEN', 'CLOSED');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "SubscriptionStatus" AS ENUM ('ACTIVE', 'PAST_DUE', 'CANCELED', 'UNPAID', 'TRIALING', 'INCOMPLETE');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "ReportStatus" AS ENUM ('PENDING', 'REVIEWED', 'RESOLVED', 'DISMISSED');
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "users" (
|
||||
"id" TEXT NOT NULL,
|
||||
"email" TEXT NOT NULL,
|
||||
"password" TEXT,
|
||||
"role" "UserRole" NOT NULL DEFAULT 'USER',
|
||||
"status" "UserStatus" NOT NULL DEFAULT 'ACTIVE',
|
||||
"emailVerified" BOOLEAN NOT NULL DEFAULT false,
|
||||
"emailVerifiedAt" TIMESTAMP(3),
|
||||
"avatar" TEXT,
|
||||
"authProvider" "AuthProvider" NOT NULL DEFAULT 'LOCAL',
|
||||
"googleId" TEXT,
|
||||
"facebookId" TEXT,
|
||||
"twitterId" TEXT,
|
||||
"appleId" TEXT,
|
||||
"twoFactorEnabled" BOOLEAN NOT NULL DEFAULT false,
|
||||
"twoFactorSecret" TEXT,
|
||||
"twoFactorBackupCodes" TEXT,
|
||||
"twoFactorVerifiedAt" TIMESTAMP(3),
|
||||
"notificationPreferences" JSONB,
|
||||
"privacyPreferences" JSONB,
|
||||
"fcmTokens" JSONB,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"lastLoginAt" TIMESTAMP(3),
|
||||
"isOnline" BOOLEAN NOT NULL DEFAULT false,
|
||||
"lastSeenAt" TIMESTAMP(3),
|
||||
|
||||
CONSTRAINT "users_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "user_profiles" (
|
||||
"id" TEXT NOT NULL,
|
||||
"userId" TEXT NOT NULL,
|
||||
"firstName" TEXT,
|
||||
"lastName" TEXT,
|
||||
"phone" TEXT,
|
||||
"avatar" TEXT,
|
||||
"city" TEXT,
|
||||
"state" TEXT,
|
||||
"country" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "user_profiles_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "agent_profiles" (
|
||||
"id" TEXT NOT NULL,
|
||||
"userId" TEXT NOT NULL,
|
||||
"slug" TEXT NOT NULL,
|
||||
"agentTypeId" TEXT,
|
||||
"firstName" TEXT,
|
||||
"lastName" TEXT,
|
||||
"phone" TEXT,
|
||||
"avatar" TEXT,
|
||||
"bio" TEXT,
|
||||
"headline" TEXT,
|
||||
"city" TEXT,
|
||||
"state" TEXT,
|
||||
"country" TEXT,
|
||||
"address" TEXT,
|
||||
"zipCode" TEXT,
|
||||
"latitude" DOUBLE PRECISION,
|
||||
"longitude" DOUBLE PRECISION,
|
||||
"yearsOfExperience" INTEGER,
|
||||
"licenseNumber" TEXT,
|
||||
"companyName" TEXT,
|
||||
"website" TEXT,
|
||||
"facebookUrl" TEXT,
|
||||
"twitterUrl" TEXT,
|
||||
"linkedinUrl" TEXT,
|
||||
"instagramUrl" TEXT,
|
||||
"isVerified" BOOLEAN NOT NULL DEFAULT false,
|
||||
"verificationStatus" "VerificationStatus" NOT NULL DEFAULT 'NONE',
|
||||
"verificationNote" TEXT,
|
||||
"verifiedAt" TIMESTAMP(3),
|
||||
"verifiedBy" TEXT,
|
||||
"isProfileComplete" BOOLEAN NOT NULL DEFAULT false,
|
||||
"profileCompleteness" INTEGER NOT NULL DEFAULT 0,
|
||||
"isPublic" BOOLEAN NOT NULL DEFAULT true,
|
||||
"isFeatured" BOOLEAN NOT NULL DEFAULT false,
|
||||
"isAvailable" BOOLEAN NOT NULL DEFAULT true,
|
||||
"subscriptionStatus" TEXT,
|
||||
"totalReviews" INTEGER NOT NULL DEFAULT 0,
|
||||
"averageRating" DOUBLE PRECISION NOT NULL DEFAULT 0,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"testimonialToken" TEXT,
|
||||
|
||||
CONSTRAINT "agent_profiles_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "agent_types" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"description" TEXT,
|
||||
"icon" TEXT,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
"sortOrder" INTEGER NOT NULL DEFAULT 0,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "agent_types_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "profile_sections" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"slug" TEXT NOT NULL,
|
||||
"description" TEXT,
|
||||
"icon" TEXT,
|
||||
"sortOrder" INTEGER NOT NULL DEFAULT 0,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
"isGlobal" BOOLEAN NOT NULL DEFAULT false,
|
||||
"isSystem" BOOLEAN NOT NULL DEFAULT false,
|
||||
"isRepeatable" BOOLEAN NOT NULL DEFAULT false,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "profile_sections_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "agent_type_sections" (
|
||||
"id" TEXT NOT NULL,
|
||||
"agentTypeId" TEXT NOT NULL,
|
||||
"sectionId" TEXT NOT NULL,
|
||||
"sortOrder" INTEGER NOT NULL DEFAULT 0,
|
||||
"isRequired" BOOLEAN NOT NULL DEFAULT false,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "agent_type_sections_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "profile_fields" (
|
||||
"id" TEXT NOT NULL,
|
||||
"sectionId" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"slug" TEXT NOT NULL,
|
||||
"fieldType" "FieldType" NOT NULL,
|
||||
"description" TEXT,
|
||||
"placeholder" TEXT,
|
||||
"defaultValue" TEXT,
|
||||
"sortOrder" INTEGER NOT NULL DEFAULT 0,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
"isRequired" BOOLEAN NOT NULL DEFAULT false,
|
||||
"isSearchableOnly" BOOLEAN NOT NULL DEFAULT false,
|
||||
"validation" JSONB,
|
||||
"options" JSONB,
|
||||
"rangeConfig" JSONB,
|
||||
"uiConfig" JSONB,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "profile_fields_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "agent_profile_field_values" (
|
||||
"id" TEXT NOT NULL,
|
||||
"agentProfileId" TEXT NOT NULL,
|
||||
"fieldId" TEXT NOT NULL,
|
||||
"textValue" TEXT,
|
||||
"numberValue" DOUBLE PRECISION,
|
||||
"booleanValue" BOOLEAN,
|
||||
"jsonValue" JSONB,
|
||||
"dateValue" TIMESTAMP(3),
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "agent_profile_field_values_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "sessions" (
|
||||
"id" TEXT NOT NULL,
|
||||
"userId" TEXT NOT NULL,
|
||||
"token" TEXT NOT NULL,
|
||||
"refreshToken" TEXT,
|
||||
"userAgent" TEXT,
|
||||
"ipAddress" TEXT,
|
||||
"expiresAt" TIMESTAMP(3) NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "sessions_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "connection_requests" (
|
||||
"id" TEXT NOT NULL,
|
||||
"userId" TEXT NOT NULL,
|
||||
"agentProfileId" TEXT NOT NULL,
|
||||
"status" "ConnectionStatus" NOT NULL DEFAULT 'PENDING',
|
||||
"message" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"respondedAt" TIMESTAMP(3),
|
||||
|
||||
CONSTRAINT "connection_requests_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "conversations" (
|
||||
"id" TEXT NOT NULL,
|
||||
"userId" TEXT NOT NULL,
|
||||
"agentProfileId" TEXT NOT NULL,
|
||||
"lastMessageAt" TIMESTAMP(3),
|
||||
"lastMessageText" VARCHAR(255),
|
||||
"userUnreadCount" INTEGER NOT NULL DEFAULT 0,
|
||||
"agentUnreadCount" INTEGER NOT NULL DEFAULT 0,
|
||||
"userMuted" BOOLEAN NOT NULL DEFAULT false,
|
||||
"agentMuted" BOOLEAN NOT NULL DEFAULT false,
|
||||
"userFavorited" BOOLEAN NOT NULL DEFAULT false,
|
||||
"agentFavorited" BOOLEAN NOT NULL DEFAULT false,
|
||||
"userClearedAt" TIMESTAMP(3),
|
||||
"agentClearedAt" TIMESTAMP(3),
|
||||
"userDeletedAt" TIMESTAMP(3),
|
||||
"agentDeletedAt" TIMESTAMP(3),
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "conversations_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "messages" (
|
||||
"id" TEXT NOT NULL,
|
||||
"conversationId" TEXT NOT NULL,
|
||||
"senderId" TEXT NOT NULL,
|
||||
"content" TEXT NOT NULL,
|
||||
"messageType" "MessageType" NOT NULL DEFAULT 'TEXT',
|
||||
"fileUrl" TEXT,
|
||||
"fileName" TEXT,
|
||||
"fileSize" INTEGER,
|
||||
"mimeType" TEXT,
|
||||
"status" "MessageStatus" NOT NULL DEFAULT 'SENT',
|
||||
"deliveredAt" TIMESTAMP(3),
|
||||
"readAt" TIMESTAMP(3),
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "messages_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "notifications" (
|
||||
"id" TEXT NOT NULL,
|
||||
"userId" TEXT NOT NULL,
|
||||
"type" TEXT NOT NULL,
|
||||
"title" TEXT NOT NULL,
|
||||
"description" TEXT NOT NULL,
|
||||
"read" BOOLEAN NOT NULL DEFAULT false,
|
||||
"actionUrl" TEXT,
|
||||
"data" JSONB,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "notifications_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "cms_contents" (
|
||||
"id" TEXT NOT NULL,
|
||||
"pageSlug" TEXT NOT NULL,
|
||||
"sectionKey" TEXT NOT NULL,
|
||||
"content" JSONB NOT NULL,
|
||||
"isPublished" BOOLEAN NOT NULL DEFAULT true,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "cms_contents_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "testimonials" (
|
||||
"id" TEXT NOT NULL,
|
||||
"agentProfileId" TEXT NOT NULL,
|
||||
"rating" INTEGER NOT NULL,
|
||||
"text" TEXT NOT NULL,
|
||||
"authorName" TEXT NOT NULL,
|
||||
"authorRole" TEXT NOT NULL,
|
||||
"isPublished" BOOLEAN NOT NULL DEFAULT true,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "testimonials_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "support_chats" (
|
||||
"id" TEXT NOT NULL,
|
||||
"userId" TEXT NOT NULL,
|
||||
"status" "SupportChatStatus" NOT NULL DEFAULT 'OPEN',
|
||||
"lastMessageAt" TIMESTAMP(3),
|
||||
"lastMessageText" VARCHAR(255),
|
||||
"userUnreadCount" INTEGER NOT NULL DEFAULT 0,
|
||||
"adminUnreadCount" INTEGER NOT NULL DEFAULT 0,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "support_chats_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "support_messages" (
|
||||
"id" TEXT NOT NULL,
|
||||
"chatId" TEXT NOT NULL,
|
||||
"senderId" TEXT NOT NULL,
|
||||
"senderRole" TEXT NOT NULL,
|
||||
"content" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "support_messages_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "subscription_plans" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"description" TEXT,
|
||||
"stripePriceId" TEXT NOT NULL,
|
||||
"amount" INTEGER NOT NULL,
|
||||
"currency" TEXT NOT NULL DEFAULT 'usd',
|
||||
"interval" TEXT NOT NULL DEFAULT 'year',
|
||||
"features" JSONB,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
"sortOrder" INTEGER NOT NULL DEFAULT 0,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "subscription_plans_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "agent_subscriptions" (
|
||||
"id" TEXT NOT NULL,
|
||||
"userId" TEXT NOT NULL,
|
||||
"planId" TEXT NOT NULL,
|
||||
"stripeCustomerId" TEXT NOT NULL,
|
||||
"stripeSubscriptionId" TEXT,
|
||||
"status" "SubscriptionStatus" NOT NULL DEFAULT 'INCOMPLETE',
|
||||
"currentPeriodStart" TIMESTAMP(3),
|
||||
"currentPeriodEnd" TIMESTAMP(3),
|
||||
"cancelAtPeriodEnd" BOOLEAN NOT NULL DEFAULT false,
|
||||
"canceledAt" TIMESTAMP(3),
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "agent_subscriptions_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "payments" (
|
||||
"id" TEXT NOT NULL,
|
||||
"subscriptionId" TEXT,
|
||||
"userId" TEXT NOT NULL,
|
||||
"stripePaymentIntentId" TEXT,
|
||||
"stripeInvoiceId" TEXT,
|
||||
"amount" INTEGER NOT NULL,
|
||||
"currency" TEXT NOT NULL DEFAULT 'usd',
|
||||
"status" TEXT NOT NULL,
|
||||
"receiptUrl" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "payments_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "user_reports" (
|
||||
"id" TEXT NOT NULL,
|
||||
"reporterId" TEXT NOT NULL,
|
||||
"reportedUserId" TEXT NOT NULL,
|
||||
"conversationId" TEXT,
|
||||
"reason" TEXT NOT NULL,
|
||||
"description" TEXT,
|
||||
"status" "ReportStatus" NOT NULL DEFAULT 'PENDING',
|
||||
"adminNotes" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "user_reports_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "contact_messages" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"email" TEXT NOT NULL,
|
||||
"phone" TEXT,
|
||||
"message" TEXT NOT NULL,
|
||||
"isRead" BOOLEAN NOT NULL DEFAULT false,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "contact_messages_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "verification_history" (
|
||||
"id" TEXT NOT NULL,
|
||||
"agentProfileId" TEXT NOT NULL,
|
||||
"status" "VerificationStatus" NOT NULL,
|
||||
"note" TEXT,
|
||||
"adminId" TEXT,
|
||||
"submittedData" JSONB,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "verification_history_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "audit_logs" (
|
||||
"id" TEXT NOT NULL,
|
||||
"actorId" TEXT,
|
||||
"actorRole" TEXT,
|
||||
"action" TEXT NOT NULL,
|
||||
"resourceType" TEXT,
|
||||
"resourceId" TEXT,
|
||||
"metadata" JSONB,
|
||||
"ipAddress" TEXT,
|
||||
"userAgent" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "audit_logs_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "users_email_key" ON "users"("email");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "users_googleId_key" ON "users"("googleId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "users_facebookId_key" ON "users"("facebookId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "users_twitterId_key" ON "users"("twitterId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "users_appleId_key" ON "users"("appleId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "users_email_idx" ON "users"("email");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "users_role_idx" ON "users"("role");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "users_status_idx" ON "users"("status");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "users_isOnline_idx" ON "users"("isOnline");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "user_profiles_userId_key" ON "user_profiles"("userId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "user_profiles_userId_idx" ON "user_profiles"("userId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "agent_profiles_userId_key" ON "agent_profiles"("userId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "agent_profiles_slug_key" ON "agent_profiles"("slug");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "agent_profiles_testimonialToken_key" ON "agent_profiles"("testimonialToken");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "agent_profiles_userId_idx" ON "agent_profiles"("userId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "agent_profiles_agentTypeId_idx" ON "agent_profiles"("agentTypeId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "agent_profiles_slug_idx" ON "agent_profiles"("slug");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "agent_profiles_city_state_idx" ON "agent_profiles"("city", "state");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "agent_profiles_isVerified_idx" ON "agent_profiles"("isVerified");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "agent_profiles_verificationStatus_idx" ON "agent_profiles"("verificationStatus");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "agent_profiles_isPublic_idx" ON "agent_profiles"("isPublic");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "agent_profiles_isFeatured_idx" ON "agent_profiles"("isFeatured");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "agent_profiles_isAvailable_idx" ON "agent_profiles"("isAvailable");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "agent_types_name_key" ON "agent_types"("name");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "agent_types_isActive_idx" ON "agent_types"("isActive");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "profile_sections_slug_key" ON "profile_sections"("slug");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "profile_sections_isActive_idx" ON "profile_sections"("isActive");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "profile_sections_isSystem_idx" ON "profile_sections"("isSystem");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "profile_sections_sortOrder_idx" ON "profile_sections"("sortOrder");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "agent_type_sections_agentTypeId_idx" ON "agent_type_sections"("agentTypeId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "agent_type_sections_sectionId_idx" ON "agent_type_sections"("sectionId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "agent_type_sections_agentTypeId_sectionId_key" ON "agent_type_sections"("agentTypeId", "sectionId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "profile_fields_sectionId_idx" ON "profile_fields"("sectionId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "profile_fields_isActive_idx" ON "profile_fields"("isActive");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "profile_fields_sectionId_slug_key" ON "profile_fields"("sectionId", "slug");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "agent_profile_field_values_agentProfileId_idx" ON "agent_profile_field_values"("agentProfileId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "agent_profile_field_values_fieldId_idx" ON "agent_profile_field_values"("fieldId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "agent_profile_field_values_agentProfileId_fieldId_key" ON "agent_profile_field_values"("agentProfileId", "fieldId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "sessions_token_key" ON "sessions"("token");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "sessions_refreshToken_key" ON "sessions"("refreshToken");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "sessions_userId_idx" ON "sessions"("userId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "sessions_token_idx" ON "sessions"("token");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "connection_requests_agentProfileId_status_idx" ON "connection_requests"("agentProfileId", "status");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "connection_requests_userId_status_idx" ON "connection_requests"("userId", "status");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "connection_requests_status_idx" ON "connection_requests"("status");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "connection_requests_userId_agentProfileId_key" ON "connection_requests"("userId", "agentProfileId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "conversations_userId_lastMessageAt_idx" ON "conversations"("userId", "lastMessageAt");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "conversations_agentProfileId_lastMessageAt_idx" ON "conversations"("agentProfileId", "lastMessageAt");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "conversations_userId_agentProfileId_key" ON "conversations"("userId", "agentProfileId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "messages_conversationId_createdAt_idx" ON "messages"("conversationId", "createdAt");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "messages_senderId_idx" ON "messages"("senderId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "messages_status_idx" ON "messages"("status");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "notifications_userId_read_idx" ON "notifications"("userId", "read");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "notifications_userId_createdAt_idx" ON "notifications"("userId", "createdAt");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "cms_contents_pageSlug_idx" ON "cms_contents"("pageSlug");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "cms_contents_pageSlug_sectionKey_key" ON "cms_contents"("pageSlug", "sectionKey");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "testimonials_agentProfileId_idx" ON "testimonials"("agentProfileId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "support_chats_userId_idx" ON "support_chats"("userId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "support_chats_status_idx" ON "support_chats"("status");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "support_messages_chatId_idx" ON "support_messages"("chatId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "subscription_plans_stripePriceId_key" ON "subscription_plans"("stripePriceId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "subscription_plans_isActive_idx" ON "subscription_plans"("isActive");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "agent_subscriptions_stripeSubscriptionId_key" ON "agent_subscriptions"("stripeSubscriptionId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "agent_subscriptions_userId_idx" ON "agent_subscriptions"("userId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "agent_subscriptions_status_idx" ON "agent_subscriptions"("status");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "agent_subscriptions_stripeCustomerId_idx" ON "agent_subscriptions"("stripeCustomerId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "payments_stripePaymentIntentId_key" ON "payments"("stripePaymentIntentId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "payments_stripeInvoiceId_key" ON "payments"("stripeInvoiceId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "payments_userId_idx" ON "payments"("userId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "payments_subscriptionId_idx" ON "payments"("subscriptionId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "payments_status_idx" ON "payments"("status");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "user_reports_reporterId_idx" ON "user_reports"("reporterId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "user_reports_reportedUserId_idx" ON "user_reports"("reportedUserId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "user_reports_status_idx" ON "user_reports"("status");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "contact_messages_isRead_idx" ON "contact_messages"("isRead");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "contact_messages_createdAt_idx" ON "contact_messages"("createdAt");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "verification_history_agentProfileId_idx" ON "verification_history"("agentProfileId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "verification_history_createdAt_idx" ON "verification_history"("createdAt");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "audit_logs_actorId_createdAt_idx" ON "audit_logs"("actorId", "createdAt");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "audit_logs_resourceType_resourceId_idx" ON "audit_logs"("resourceType", "resourceId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "audit_logs_action_createdAt_idx" ON "audit_logs"("action", "createdAt");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "audit_logs_createdAt_idx" ON "audit_logs"("createdAt");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "user_profiles" ADD CONSTRAINT "user_profiles_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "agent_profiles" ADD CONSTRAINT "agent_profiles_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "agent_profiles" ADD CONSTRAINT "agent_profiles_agentTypeId_fkey" FOREIGN KEY ("agentTypeId") REFERENCES "agent_types"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "agent_type_sections" ADD CONSTRAINT "agent_type_sections_agentTypeId_fkey" FOREIGN KEY ("agentTypeId") REFERENCES "agent_types"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "agent_type_sections" ADD CONSTRAINT "agent_type_sections_sectionId_fkey" FOREIGN KEY ("sectionId") REFERENCES "profile_sections"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "profile_fields" ADD CONSTRAINT "profile_fields_sectionId_fkey" FOREIGN KEY ("sectionId") REFERENCES "profile_sections"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "agent_profile_field_values" ADD CONSTRAINT "agent_profile_field_values_agentProfileId_fkey" FOREIGN KEY ("agentProfileId") REFERENCES "agent_profiles"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "agent_profile_field_values" ADD CONSTRAINT "agent_profile_field_values_fieldId_fkey" FOREIGN KEY ("fieldId") REFERENCES "profile_fields"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "sessions" ADD CONSTRAINT "sessions_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "connection_requests" ADD CONSTRAINT "connection_requests_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "connection_requests" ADD CONSTRAINT "connection_requests_agentProfileId_fkey" FOREIGN KEY ("agentProfileId") REFERENCES "agent_profiles"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "conversations" ADD CONSTRAINT "conversations_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "conversations" ADD CONSTRAINT "conversations_agentProfileId_fkey" FOREIGN KEY ("agentProfileId") REFERENCES "agent_profiles"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "messages" ADD CONSTRAINT "messages_conversationId_fkey" FOREIGN KEY ("conversationId") REFERENCES "conversations"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "messages" ADD CONSTRAINT "messages_senderId_fkey" FOREIGN KEY ("senderId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "notifications" ADD CONSTRAINT "notifications_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "testimonials" ADD CONSTRAINT "testimonials_agentProfileId_fkey" FOREIGN KEY ("agentProfileId") REFERENCES "agent_profiles"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "support_chats" ADD CONSTRAINT "support_chats_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "support_messages" ADD CONSTRAINT "support_messages_chatId_fkey" FOREIGN KEY ("chatId") REFERENCES "support_chats"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "agent_subscriptions" ADD CONSTRAINT "agent_subscriptions_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "agent_subscriptions" ADD CONSTRAINT "agent_subscriptions_planId_fkey" FOREIGN KEY ("planId") REFERENCES "subscription_plans"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "payments" ADD CONSTRAINT "payments_subscriptionId_fkey" FOREIGN KEY ("subscriptionId") REFERENCES "agent_subscriptions"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "payments" ADD CONSTRAINT "payments_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "user_reports" ADD CONSTRAINT "user_reports_reporterId_fkey" FOREIGN KEY ("reporterId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "user_reports" ADD CONSTRAINT "user_reports_reportedUserId_fkey" FOREIGN KEY ("reportedUserId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "verification_history" ADD CONSTRAINT "verification_history_agentProfileId_fkey" FOREIGN KEY ("agentProfileId") REFERENCES "agent_profiles"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "verification_history" ADD CONSTRAINT "verification_history_adminId_fkey" FOREIGN KEY ("adminId") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "audit_logs" ADD CONSTRAINT "audit_logs_actorId_fkey" FOREIGN KEY ("actorId") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
3
prisma/migrations/migration_lock.toml
Normal file
3
prisma/migrations/migration_lock.toml
Normal file
@@ -0,0 +1,3 @@
|
||||
# Please do not edit this file manually
|
||||
# It should be added in your version-control system (e.g., Git)
|
||||
provider = "postgresql"
|
||||
@@ -20,6 +20,22 @@ async function main() {
|
||||
|
||||
const prisma = new PrismaClient({ adapter });
|
||||
|
||||
// Validate up front so a misconfigured run fails before it writes anything.
|
||||
// No defaults: a seed run without these would create a super-admin whose
|
||||
// credentials are published in this file.
|
||||
const adminEmail = process.env.ADMIN_EMAIL;
|
||||
const adminPassword = process.env.ADMIN_PASSWORD;
|
||||
|
||||
if (!adminEmail || !adminPassword) {
|
||||
throw new Error(
|
||||
'ADMIN_EMAIL and ADMIN_PASSWORD must be set to seed the super-admin account',
|
||||
);
|
||||
}
|
||||
|
||||
if (adminPassword.length < 12) {
|
||||
throw new Error('ADMIN_PASSWORD must be at least 12 characters');
|
||||
}
|
||||
|
||||
console.log('🌱 Starting database seeding...\n');
|
||||
|
||||
// =============================================
|
||||
@@ -1256,9 +1272,7 @@ async function main() {
|
||||
// =============================================
|
||||
console.log('👤 Seeding Admin User...');
|
||||
|
||||
const adminEmail = process.env.ADMIN_EMAIL || 'admin@re-quest.com';
|
||||
const adminPassword = process.env.ADMIN_PASSWORD || 'Admin@123456';
|
||||
|
||||
// adminEmail / adminPassword are validated at the top of main().
|
||||
// Hash password with Argon2 (more secure than bcrypt)
|
||||
const hashedPassword = await argon2.hash(adminPassword);
|
||||
|
||||
@@ -1286,7 +1300,6 @@ async function main() {
|
||||
console.log(' ✅ Admin user created successfully!');
|
||||
console.log(' ───────────────────────────────');
|
||||
console.log(` 📧 Email: ${adminEmail}`);
|
||||
console.log(` 🔑 Password: ${adminPassword}`);
|
||||
console.log(` 👤 Role: ${admin.role}`);
|
||||
console.log(` 🆔 ID: ${admin.id}`);
|
||||
console.log(' ───────────────────────────────\n');
|
||||
|
||||
Reference in New Issue
Block a user