feat: add phone frequency controls and modularize codebase
This commit is contained in:
@@ -0,0 +1,131 @@
|
||||
CREATE TABLE "PhoneFrequencyHit" (
|
||||
"id" TEXT NOT NULL,
|
||||
"tenantId" TEXT NOT NULL,
|
||||
"applicationId" TEXT NOT NULL,
|
||||
"ruleId" TEXT,
|
||||
"ruleCode" TEXT NOT NULL,
|
||||
"ruleName" TEXT NOT NULL,
|
||||
"phoneNumber" TEXT NOT NULL,
|
||||
"thresholdValue" INTEGER NOT NULL,
|
||||
"actualValue" INTEGER NOT NULL,
|
||||
"windowStartedAt" TIMESTAMP(3) NOT NULL,
|
||||
"windowEndsAt" TIMESTAMP(3) NOT NULL,
|
||||
"generation" INTEGER NOT NULL DEFAULT 0,
|
||||
"action" TEXT NOT NULL DEFAULT 'block',
|
||||
"sourceType" TEXT,
|
||||
"releasedAt" TIMESTAMP(3),
|
||||
"releasedById" TEXT,
|
||||
"releaseReason" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "PhoneFrequencyHit_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE TABLE "PhoneFrequencyState" (
|
||||
"id" TEXT NOT NULL,
|
||||
"tenantId" TEXT NOT NULL,
|
||||
"applicationId" TEXT NOT NULL,
|
||||
"ruleId" TEXT,
|
||||
"ruleCode" TEXT NOT NULL,
|
||||
"phoneNumber" TEXT NOT NULL,
|
||||
"windowStartedAt" TIMESTAMP(3) NOT NULL,
|
||||
"windowEndsAt" TIMESTAMP(3) NOT NULL,
|
||||
"count" INTEGER NOT NULL DEFAULT 0,
|
||||
"generation" INTEGER NOT NULL DEFAULT 0,
|
||||
"activeHitId" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "PhoneFrequencyState_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX "PhoneFrequencyHit_applicationId_ruleCode_phoneNumber_windowStartedAt_generation_key"
|
||||
ON "PhoneFrequencyHit"("applicationId", "ruleCode", "phoneNumber", "windowStartedAt", "generation");
|
||||
|
||||
CREATE INDEX "PhoneFrequencyHit_tenantId_applicationId_createdAt_idx"
|
||||
ON "PhoneFrequencyHit"("tenantId", "applicationId", "createdAt");
|
||||
|
||||
CREATE INDEX "PhoneFrequencyHit_applicationId_phoneNumber_createdAt_idx"
|
||||
ON "PhoneFrequencyHit"("applicationId", "phoneNumber", "createdAt");
|
||||
|
||||
CREATE INDEX "PhoneFrequencyHit_windowEndsAt_releasedAt_idx"
|
||||
ON "PhoneFrequencyHit"("windowEndsAt", "releasedAt");
|
||||
|
||||
CREATE INDEX "PhoneFrequencyHit_ruleId_idx" ON "PhoneFrequencyHit"("ruleId");
|
||||
CREATE INDEX "PhoneFrequencyHit_releasedById_idx" ON "PhoneFrequencyHit"("releasedById");
|
||||
|
||||
CREATE UNIQUE INDEX "PhoneFrequencyState_activeHitId_key" ON "PhoneFrequencyState"("activeHitId");
|
||||
|
||||
CREATE UNIQUE INDEX "PhoneFrequencyState_applicationId_ruleCode_phoneNumber_key"
|
||||
ON "PhoneFrequencyState"("applicationId", "ruleCode", "phoneNumber");
|
||||
|
||||
CREATE INDEX "PhoneFrequencyState_tenantId_applicationId_windowEndsAt_idx"
|
||||
ON "PhoneFrequencyState"("tenantId", "applicationId", "windowEndsAt");
|
||||
|
||||
CREATE INDEX "PhoneFrequencyState_ruleId_idx" ON "PhoneFrequencyState"("ruleId");
|
||||
|
||||
ALTER TABLE "PhoneFrequencyHit"
|
||||
ADD CONSTRAINT "PhoneFrequencyHit_tenantId_fkey"
|
||||
FOREIGN KEY ("tenantId") REFERENCES "Tenant"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "PhoneFrequencyHit"
|
||||
ADD CONSTRAINT "PhoneFrequencyHit_applicationId_fkey"
|
||||
FOREIGN KEY ("applicationId") REFERENCES "SmsApplication"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "PhoneFrequencyHit"
|
||||
ADD CONSTRAINT "PhoneFrequencyHit_ruleId_fkey"
|
||||
FOREIGN KEY ("ruleId") REFERENCES "RiskRule"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "PhoneFrequencyHit"
|
||||
ADD CONSTRAINT "PhoneFrequencyHit_releasedById_fkey"
|
||||
FOREIGN KEY ("releasedById") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "PhoneFrequencyState"
|
||||
ADD CONSTRAINT "PhoneFrequencyState_tenantId_fkey"
|
||||
FOREIGN KEY ("tenantId") REFERENCES "Tenant"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "PhoneFrequencyState"
|
||||
ADD CONSTRAINT "PhoneFrequencyState_applicationId_fkey"
|
||||
FOREIGN KEY ("applicationId") REFERENCES "SmsApplication"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "PhoneFrequencyState"
|
||||
ADD CONSTRAINT "PhoneFrequencyState_ruleId_fkey"
|
||||
FOREIGN KEY ("ruleId") REFERENCES "RiskRule"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "PhoneFrequencyState"
|
||||
ADD CONSTRAINT "PhoneFrequencyState_activeHitId_fkey"
|
||||
FOREIGN KEY ("activeHitId") REFERENCES "PhoneFrequencyHit"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
INSERT INTO "RiskRule" (
|
||||
"id", "tenantId", "applicationId", "code", "name", "description", "metric",
|
||||
"thresholdValue", "action", "status", "priority", "config", "createdAt", "updatedAt"
|
||||
)
|
||||
SELECT
|
||||
'default-phone-frequency-24h', NULL, NULL, 'PHONE_FREQUENCY_24H',
|
||||
'单号码24小时发送频次', '同一企业应用下,单个号码在北京时间自然日内最多允许10条业务短信。',
|
||||
'phoneFrequencyCount', 10, 'block', 'active', 40,
|
||||
'{"periodSeconds":86400,"timeZone":"Asia/Shanghai","alignment":"fixed"}'::jsonb,
|
||||
CURRENT_TIMESTAMP, CURRENT_TIMESTAMP
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM "RiskRule"
|
||||
WHERE "applicationId" IS NULL
|
||||
AND "code" = 'PHONE_FREQUENCY_24H'
|
||||
AND "status" <> 'deleted'
|
||||
);
|
||||
|
||||
INSERT INTO "RiskRule" (
|
||||
"id", "tenantId", "applicationId", "code", "name", "description", "metric",
|
||||
"thresholdValue", "action", "status", "priority", "config", "createdAt", "updatedAt"
|
||||
)
|
||||
SELECT
|
||||
'default-phone-frequency-5m', NULL, NULL, 'PHONE_FREQUENCY_5M',
|
||||
'单号码5分钟发送频次', '同一企业应用下,单个号码在固定5分钟周期内最多允许5条业务短信。',
|
||||
'phoneFrequencyCount', 5, 'block', 'active', 50,
|
||||
'{"periodSeconds":300,"timeZone":"Asia/Shanghai","alignment":"fixed"}'::jsonb,
|
||||
CURRENT_TIMESTAMP, CURRENT_TIMESTAMP
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM "RiskRule"
|
||||
WHERE "applicationId" IS NULL
|
||||
AND "code" = 'PHONE_FREQUENCY_5M'
|
||||
AND "status" <> 'deleted'
|
||||
);
|
||||
@@ -0,0 +1,34 @@
|
||||
CREATE TABLE "PhoneFrequencyWhitelist" (
|
||||
"id" TEXT NOT NULL,
|
||||
"phoneNumber" TEXT NOT NULL,
|
||||
"status" TEXT NOT NULL DEFAULT 'active',
|
||||
"reason" TEXT NOT NULL,
|
||||
"remark" TEXT,
|
||||
"createdById" TEXT NOT NULL,
|
||||
"updatedById" TEXT NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3),
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "PhoneFrequencyWhitelist_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX "PhoneFrequencyWhitelist_phoneNumber_key"
|
||||
ON "PhoneFrequencyWhitelist"("phoneNumber");
|
||||
|
||||
CREATE INDEX "PhoneFrequencyWhitelist_status_updatedAt_idx"
|
||||
ON "PhoneFrequencyWhitelist"("status", "updatedAt");
|
||||
|
||||
CREATE INDEX "PhoneFrequencyWhitelist_createdById_idx"
|
||||
ON "PhoneFrequencyWhitelist"("createdById");
|
||||
|
||||
CREATE INDEX "PhoneFrequencyWhitelist_updatedById_idx"
|
||||
ON "PhoneFrequencyWhitelist"("updatedById");
|
||||
|
||||
ALTER TABLE "PhoneFrequencyWhitelist"
|
||||
ADD CONSTRAINT "PhoneFrequencyWhitelist_createdById_fkey"
|
||||
FOREIGN KEY ("createdById") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE "PhoneFrequencyWhitelist"
|
||||
ADD CONSTRAINT "PhoneFrequencyWhitelist_updatedById_fkey"
|
||||
FOREIGN KEY ("updatedById") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
Reference in New Issue
Block a user