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