TorbatYar/frontend/modules/commercial/adapters/policies.ts
2026-07-28 20:39:10 +03:30

69 lines
2.6 KiB
TypeScript

import type { AdapterResult, CommercialPolicy, DomainPolicyResult } from "../types";
import { commercialGet, commercialPost, extractItems, failResult, listResult } from "./http";
export async function loadCommercialPolicies(): Promise<AdapterResult<CommercialPolicy[]>> {
const res = await commercialGet<unknown>("/api/v1/commercial/policies");
if (!res.ok) {
return failResult(res.availability, res.message || "رجیستری سیاست در دسترس نیست", []);
}
const items = extractItems<CommercialPolicy>(res.data, ["items", "policies"]);
return listResult(items, "commercial.policies", "سیاستی ثبت نشده است");
}
function enrichDomainPolicy(data: DomainPolicyResult): DomainPolicyResult {
const params = data.parameters || {};
return {
...data,
ssl_ready:
data.ssl_ready ?? (typeof params.ssl_ready === "boolean" ? params.ssl_ready : undefined),
dns_instructions:
data.dns_instructions ??
(Array.isArray(params.dns_instructions)
? (params.dns_instructions as DomainPolicyResult["dns_instructions"])
: undefined),
verification_state:
data.verification_state ??
(typeof params.verification_state === "string" ? params.verification_state : null),
grace_period_days:
data.grace_period_days ??
(typeof params.grace_period_days === "number" ? params.grace_period_days : null),
};
}
/**
* Domain unlock from policy API only — never hardcode subscription rules in UI.
* Fallback: if policy API unavailable, deny custom domain (safe default).
*/
export async function evaluateDomainPolicy(input: {
tenant_id: string;
subscription_status?: string | null;
}): Promise<AdapterResult<DomainPolicyResult>> {
const res = await commercialPost<DomainPolicyResult>("/api/v1/commercial/policies/evaluate", {
policy_kind: "domain",
tenant_id: input.tenant_id,
context: { subscription_status: input.subscription_status },
});
if (res.ok) {
return {
availability: "ready",
data: enrichDomainPolicy(res.data),
source: "commercial.policies.evaluate",
};
}
return {
availability: res.availability,
data: {
custom_domain_allowed: false,
subdomain_only: true,
reason: res.message || "سیاست دامنه در دسترس نیست؛ دامنه اختصاصی قفل می‌ماند",
source: "deny_on_unavailable",
ssl_ready: false,
dns_instructions: [],
verification_state: "locked",
},
message: res.message,
source: "none",
};
}