mirror of
https://github.com/fosrl/pangolin.git
synced 2026-05-06 16:38:48 +00:00
🚧 wip
This commit is contained in:
@@ -735,6 +735,7 @@
|
||||
"resourcePolicyOtpEmpty": "No one time password",
|
||||
"resourcePolicyTypeSave": "Save Resource type",
|
||||
"resourcePolicySelect": "Select resource policy",
|
||||
"resourcePolicyNotFound": "Policy not found",
|
||||
"resourcePolicyRulesEmpty": "No authentication rules",
|
||||
"resourceAuthMethodsDescriptions": "Allow access to the resource via additional auth methods",
|
||||
"resourceAuthSettingsSave": "Saved successfully",
|
||||
|
||||
@@ -637,10 +637,10 @@ authenticated.get(
|
||||
);
|
||||
|
||||
authenticated.get(
|
||||
"/resource/:resourceId/default-policy",
|
||||
"/resource/:resourceId/policies",
|
||||
verifyResourceAccess,
|
||||
verifyUserHasAction(ActionsEnum.getResourcePolicy),
|
||||
resource.getDefaultResourcePolicy
|
||||
resource.getResourcePolicies
|
||||
);
|
||||
|
||||
authenticated.put(
|
||||
|
||||
@@ -454,10 +454,10 @@ authenticated.get(
|
||||
);
|
||||
|
||||
authenticated.get(
|
||||
"/resource/:resourceId/default-policy",
|
||||
"/resource/:resourceId/policies",
|
||||
verifyApiKeyResourceAccess,
|
||||
verifyApiKeyHasAction(ActionsEnum.getResourcePolicy),
|
||||
resource.getDefaultResourcePolicy
|
||||
resource.getResourcePolicies
|
||||
);
|
||||
|
||||
authenticated.post(
|
||||
|
||||
@@ -17,12 +17,15 @@ const getResourcePoliciesParamsSchema = z.strictObject({
|
||||
resourceId: z.string().transform(Number).pipe(z.int().positive())
|
||||
});
|
||||
|
||||
export type GetDefaultResourcePolicyResponse = GetResourcePolicyResponse;
|
||||
export type GetResourcePoliciesResponse = {
|
||||
defaultPolicy: GetResourcePolicyResponse;
|
||||
sharedPolicy: GetResourcePolicyResponse | null;
|
||||
};
|
||||
|
||||
registry.registerPath({
|
||||
method: "get",
|
||||
path: "/resource/{resourceId}/default-policy",
|
||||
description: "Get the default policy for a resource.",
|
||||
path: "/resource/{resourceId}/policies",
|
||||
description: "Get the inline and shared policies associated with a resource.",
|
||||
tags: [OpenAPITags.PublicResource, OpenAPITags.Policy],
|
||||
request: {
|
||||
params: getResourcePoliciesParamsSchema
|
||||
@@ -30,7 +33,7 @@ registry.registerPath({
|
||||
responses: {}
|
||||
});
|
||||
|
||||
export async function getDefaultResourcePolicy(
|
||||
export async function getResourcePolicies(
|
||||
req: Request,
|
||||
res: Response,
|
||||
next: NextFunction
|
||||
@@ -52,7 +55,8 @@ export async function getDefaultResourcePolicy(
|
||||
|
||||
const [resource] = await db
|
||||
.select({
|
||||
defaultResourcePolicyId: resources.defaultResourcePolicyId
|
||||
defaultResourcePolicyId: resources.defaultResourcePolicyId,
|
||||
resourcePolicyId: resources.resourcePolicyId
|
||||
})
|
||||
.from(resources)
|
||||
.where(eq(resources.resourceId, resourceId))
|
||||
@@ -73,11 +77,24 @@ export async function getDefaultResourcePolicy(
|
||||
);
|
||||
}
|
||||
|
||||
const defaultPolicy = await queryResourcePolicy({
|
||||
resourcePolicyId: resource.defaultResourcePolicyId
|
||||
});
|
||||
return response<GetDefaultResourcePolicyResponse>(res, {
|
||||
data: defaultPolicy,
|
||||
const [defaultPolicy, sharedPolicy] = await Promise.all([
|
||||
queryResourcePolicy({
|
||||
resourcePolicyId: resource.defaultResourcePolicyId
|
||||
}),
|
||||
resource.resourcePolicyId
|
||||
? queryResourcePolicy({
|
||||
resourcePolicyId: resource.resourcePolicyId
|
||||
})
|
||||
: null
|
||||
]);
|
||||
|
||||
return response<GetResourcePoliciesResponse>(res, {
|
||||
data: {
|
||||
defaultPolicy:
|
||||
// the policy will always be non nullable
|
||||
defaultPolicy as unknown as GetResourcePolicyResponse,
|
||||
sharedPolicy
|
||||
},
|
||||
success: true,
|
||||
error: false,
|
||||
message: "Resource policies retrieved successfully",
|
||||
@@ -31,4 +31,4 @@ export * from "./addUserToResource";
|
||||
export * from "./removeUserFromResource";
|
||||
export * from "./listAllResourceNames";
|
||||
export * from "./removeEmailFromResourceWhitelist";
|
||||
export * from "./getDefaultResourcePolicy";
|
||||
export * from "./getResourcePolicies";
|
||||
|
||||
@@ -79,7 +79,7 @@ import SetResourcePasswordForm from "components/SetResourcePasswordForm";
|
||||
import { Binary, Bot, CheckIcon, InfoIcon, Key } from "lucide-react";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { useRouter } from "next/navigation";
|
||||
import {
|
||||
import React, {
|
||||
useActionState,
|
||||
useEffect,
|
||||
useMemo,
|
||||
@@ -105,8 +105,7 @@ type ResourcePolicyType = StrategyOption<"inline" | "shared">;
|
||||
|
||||
export default function ResourceAuthenticationPage() {
|
||||
const { org } = useOrgContext();
|
||||
const { resource, updateResource, authInfo, updateAuthInfo } =
|
||||
useResourceContext();
|
||||
const { resource, updateResource } = useResourceContext();
|
||||
|
||||
const { env } = useEnvContext();
|
||||
|
||||
@@ -125,7 +124,7 @@ export default function ResourceAuthenticationPage() {
|
||||
const form = useForm({
|
||||
resolver: zodResolver(resourceTypeSchema),
|
||||
defaultValues: {
|
||||
type: "inline"
|
||||
type: resource.resourcePolicyId ? "shared" : "inline"
|
||||
}
|
||||
});
|
||||
|
||||
@@ -145,7 +144,7 @@ export default function ResourceAuthenticationPage() {
|
||||
enabled: selectedResourceType === "shared"
|
||||
});
|
||||
|
||||
const { data: sharedPolicy } = useQuery({
|
||||
const { data: sharedPolicy, isLoading: isLoadingSharedPolicy } = useQuery({
|
||||
...resourcePolicyQueries.single({
|
||||
resourcePolicyId: resource.resourcePolicyId ?? 1
|
||||
}),
|
||||
@@ -157,17 +156,6 @@ export default function ResourceAuthenticationPage() {
|
||||
id: number;
|
||||
} | null>(null);
|
||||
|
||||
const pageLoading = isLoadingPolicies || !defaultPolicy;
|
||||
|
||||
const [
|
||||
loadingRemoveResourceHeaderAuth,
|
||||
setLoadingRemoveResourceHeaderAuth
|
||||
] = useState(false);
|
||||
|
||||
const [isSetPasswordOpen, setIsSetPasswordOpen] = useState(false);
|
||||
const [isSetPincodeOpen, setIsSetPincodeOpen] = useState(false);
|
||||
const [isSetHeaderAuthOpen, setIsSetHeaderAuthOpen] = useState(false);
|
||||
|
||||
const resourcePolicyTypes: Array<ResourcePolicyType> = [
|
||||
{
|
||||
id: "inline",
|
||||
@@ -181,6 +169,49 @@ export default function ResourceAuthenticationPage() {
|
||||
}
|
||||
];
|
||||
|
||||
useEffect(() => {
|
||||
if (!isLoadingSharedPolicy && sharedPolicy) {
|
||||
setSelectedPolicy({
|
||||
id: sharedPolicy.resourcePolicyId,
|
||||
name: sharedPolicy.name
|
||||
});
|
||||
}
|
||||
}, [isLoadingSharedPolicy, sharedPolicy]);
|
||||
|
||||
const [isUpdatingResource, startTransition] = useTransition();
|
||||
|
||||
async function handleSaveResourcePolicyType() {
|
||||
try {
|
||||
if (selectedResourceType === "inline") {
|
||||
await api.post(`/resource/${resource.resourceId}`, {
|
||||
resourcePolicyId: null
|
||||
});
|
||||
} else {
|
||||
if (!selectedPolicy) {
|
||||
toast({
|
||||
title: t("error"),
|
||||
description: t("resourcePolicySelectError"),
|
||||
variant: "destructive"
|
||||
});
|
||||
return;
|
||||
}
|
||||
await api.post(`/resource/${resource.resourceId}`, {
|
||||
resourcePolicyId: selectedPolicy.id
|
||||
});
|
||||
}
|
||||
router.refresh();
|
||||
} catch (e) {
|
||||
toast({
|
||||
title: t("error"),
|
||||
description: formatAxiosError(e),
|
||||
variant: "destructive"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const pageLoading =
|
||||
isLoadingPolicies || !defaultPolicy || isLoadingSharedPolicy;
|
||||
|
||||
if (pageLoading) {
|
||||
return <></>;
|
||||
}
|
||||
@@ -214,9 +245,6 @@ export default function ResourceAuthenticationPage() {
|
||||
role="combobox"
|
||||
className={
|
||||
"w-full md:w-1/2 justify-between"
|
||||
// "w-45 justify-between text-sm border-r pr-4 rounded-none h-8 hover:bg-transparent",
|
||||
// "rounded-l-md rounded-r-xs"
|
||||
// !proxyTarget.siteId && "text-muted-foreground"
|
||||
}
|
||||
>
|
||||
<span className="truncate max-w-37.5">
|
||||
@@ -238,7 +266,7 @@ export default function ResourceAuthenticationPage() {
|
||||
/>
|
||||
<CommandList>
|
||||
<CommandEmpty>
|
||||
{t("siteNotFound")}
|
||||
{t("resourcePolicyNotFound")}
|
||||
</CommandEmpty>
|
||||
<CommandGroup>
|
||||
{policiesList.map((policy) => (
|
||||
@@ -275,9 +303,10 @@ export default function ResourceAuthenticationPage() {
|
||||
</SettingsSectionBody>
|
||||
<SettingsSectionFooter className="justify-start">
|
||||
<Button
|
||||
onClick={() => {
|
||||
//...
|
||||
}}
|
||||
onClick={() =>
|
||||
startTransition(handleSaveResourcePolicyType)
|
||||
}
|
||||
loading={isUpdatingResource}
|
||||
>
|
||||
{t("resourcePolicyTypeSave")}
|
||||
</Button>
|
||||
|
||||
@@ -4,7 +4,7 @@ import type { ListClientsResponse } from "@server/routers/client";
|
||||
import type { ListDomainsResponse } from "@server/routers/domain";
|
||||
import type {
|
||||
GetResourceWhitelistResponse,
|
||||
GetDefaultResourcePolicyResponse,
|
||||
GetResourcePoliciesResponse,
|
||||
ListResourceNamesResponse,
|
||||
ListResourcesResponse,
|
||||
ListResourceRolesResponse,
|
||||
@@ -31,6 +31,7 @@ import { remote } from "./api";
|
||||
import { durationToMs } from "./durationToMs";
|
||||
import { wait } from "./wait";
|
||||
import type { ListResourcePoliciesResponse } from "@server/routers/resource/types";
|
||||
import type { GetResourcePolicyResponse } from "@server/routers/policy";
|
||||
|
||||
export type ProductUpdate = {
|
||||
link: string | null;
|
||||
@@ -227,7 +228,7 @@ export const resourcePolicyQueries = {
|
||||
queryKey: ["RESOURCE_POLICIES", resourcePolicyId] as const,
|
||||
queryFn: async ({ signal, meta }) => {
|
||||
const res = await meta!.api.get<
|
||||
AxiosResponse<GetDefaultResourcePolicyResponse>
|
||||
AxiosResponse<GetResourcePolicyResponse>
|
||||
>(`/resource-policy/${resourcePolicyId}`, { signal });
|
||||
|
||||
return res.data.data;
|
||||
@@ -364,8 +365,8 @@ export const resourceQueries = {
|
||||
queryKey: ["RESOURCES", resourceId, "DEFAULT_POLICY"] as const,
|
||||
queryFn: async ({ signal, meta }) => {
|
||||
const res = await meta!.api.get<
|
||||
AxiosResponse<GetDefaultResourcePolicyResponse>
|
||||
>(`/resource/${resourceId}/default-policy`, { signal });
|
||||
AxiosResponse<GetResourcePoliciesResponse>
|
||||
>(`/resource/${resourceId}/policies`, { signal });
|
||||
|
||||
return res.data.data;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user