diff --git a/server/db/pg/schema/schema.ts b/server/db/pg/schema/schema.ts index b33360b1f..934dbb6da 100644 --- a/server/db/pg/schema/schema.ts +++ b/server/db/pg/schema/schema.ts @@ -661,7 +661,7 @@ export const resourceRules = pgTable("resourceRules", { value: varchar("value").notNull() }); -export const policyRules = pgTable("policyRules", { +export const resourcePolicyRules = pgTable("resourcePolicyRules", { ruleId: serial("ruleId").primaryKey(), resourcePolicyId: integer("resourcePolicyId") .notNull() diff --git a/server/routers/policy/getResourcePolicy.ts b/server/routers/policy/getResourcePolicy.ts index c5b567a16..2a975dde7 100644 --- a/server/routers/policy/getResourcePolicy.ts +++ b/server/routers/policy/getResourcePolicy.ts @@ -1,6 +1,7 @@ import { db, idp, + resourcePolicyRules, resourcePolicies, resourcePolicyHeaderAuth, resourcePolicyPassword, @@ -56,6 +57,7 @@ async function query(params: z.infer) { .select({ resourcePolicyId: resourcePolicies.resourcePolicyId, sso: resourcePolicies.sso, + applyRules: resourcePolicies.applyRules, emailWhitelistEnabled: resourcePolicies.emailWhitelistEnabled, idpId: resourcePolicies.idpId, niceId: resourcePolicies.niceId, @@ -134,11 +136,24 @@ async function query(params: z.infer) { eq(resourcePolicyWhiteList.resourcePolicyId, res.resourcePolicyId) ); + const policyRules = await db + .select({ + ruleId: resourcePolicyRules.ruleId, + enabled: resourcePolicyRules.enabled, + priority: resourcePolicyRules.priority, + action: resourcePolicyRules.action, + match: resourcePolicyRules.match, + value: resourcePolicyRules.value + }) + .from(resourcePolicyRules) + .where(eq(resourcePolicyRules.resourcePolicyId, res.resourcePolicyId)); + return { ...res, roles: policyRoles, users: policyUsers, - emailWhiteList: policyEmailWhiteList + emailWhiteList: policyEmailWhiteList, + rules: policyRules }; } diff --git a/server/routers/policy/setResourcePolicyRules.ts b/server/routers/policy/setResourcePolicyRules.ts index 61ed9bece..533e01c0e 100644 --- a/server/routers/policy/setResourcePolicyRules.ts +++ b/server/routers/policy/setResourcePolicyRules.ts @@ -1,6 +1,6 @@ import { Request, Response, NextFunction } from "express"; import { z } from "zod"; -import { db, policyRules, resourcePolicies } from "@server/db"; +import { db, resourcePolicyRules, resourcePolicies } from "@server/db"; import { eq } from "drizzle-orm"; import response from "@server/lib/response"; import HttpCode from "@server/types/HttpCode"; @@ -136,11 +136,13 @@ export async function setResourcePolicyRules( .where(eq(resourcePolicies.resourcePolicyId, resourcePolicyId)); await trx - .delete(policyRules) - .where(eq(policyRules.resourcePolicyId, resourcePolicyId)); + .delete(resourcePolicyRules) + .where( + eq(resourcePolicyRules.resourcePolicyId, resourcePolicyId) + ); if (rules.length > 0) { - await trx.insert(policyRules).values( + await trx.insert(resourcePolicyRules).values( rules.map((rule) => ({ resourcePolicyId, ...rule diff --git a/src/components/resource-policy/EditPolicyRulesSectionForm.tsx b/src/components/resource-policy/EditPolicyRulesSectionForm.tsx index 23c8a1dd9..cd6f39fe1 100644 --- a/src/components/resource-policy/EditPolicyRulesSectionForm.tsx +++ b/src/components/resource-policy/EditPolicyRulesSectionForm.tsx @@ -78,7 +78,12 @@ import { import { ArrowUpDown, Check, ChevronsUpDown, Plus } from "lucide-react"; import { useCallback, useMemo, useState, useTransition } from "react"; -import { UseFormReturn, useForm } from "react-hook-form"; +import { UseFormReturn, useForm, useWatch } from "react-hook-form"; +import { useResourcePolicyContext } from "@app/providers/ResourcePolicyProvider"; +import { createApiClient, formatAxiosError } from "@app/lib/api"; +import { useEnvContext } from "@app/hooks/useEnvContext"; +import type { AxiosResponse } from "axios"; +import { useRouter } from "next/navigation"; // ─── PolicyRulesSection ─────────────────────────────────────────────────────── @@ -111,17 +116,31 @@ export function EditPolicyRulesSectionForm({ }: PolicyRulesSectionProps) { const t = useTranslations(); + const { policy } = useResourcePolicyContext(); + const api = createApiClient(useEnvContext()); + const router = useRouter(); + const form = useForm({ resolver: zodResolver( createPolicySchema.pick({ rules: true, applyRules: true }) - ) + ), + defaultValues: { + applyRules: policy.applyRules, + rules: policy.rules + } }); - const [isExpanded, setIsExpanded] = useState(false); - const [rules, setRules] = useState([]); - const [rulesEnabled, setRulesEnabled] = useState(false); + + const rulesEnabled = useWatch({ + control: form.control, + name: "applyRules" + }); + + const [rules, setRules] = useState(policy.rules); + const [isExpanded, setIsExpanded] = useState(rulesEnabled); + const [openAddRuleCountrySelect, setOpenAddRuleCountrySelect] = useState(false); const [openAddRuleAsnSelect, setOpenAddRuleAsnSelect] = useState(false); @@ -618,6 +637,45 @@ export function EditPolicyRulesSectionForm({ const [isPending, startTransition] = useTransition(); + async function saveRules() { + const isValid = form.trigger(); + if (!isValid) return; + + const payload = form.getValues(); + console.log({ payload }); + + try { + const res = await api + .put< + AxiosResponse<{}> + >(`/resource-policy/${policy.resourcePolicyId}/rules`, payload) + .catch((e) => { + toast({ + variant: "destructive", + title: t("policyErrorUpdate"), + description: formatAxiosError( + e, + t("policyErrorUpdateDescription") + ) + }); + }); + + if (res && res.status === 200) { + toast({ + title: t("success"), + description: t("policyUpdatedSuccess") + }); + router.refresh(); + } + } catch (e) { + toast({ + variant: "destructive", + title: t("policyErrorUpdate"), + description: t("policyErrorUpdateMessageDescription") + }); + } + } + if (!isExpanded) { return ( @@ -659,9 +717,8 @@ export function EditPolicyRulesSectionForm({ { - setRulesEnabled(val); form.setValue("applyRules", val); }} /> @@ -1075,9 +1132,9 @@ export function EditPolicyRulesSectionForm({