mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
feat: completed request list page
This commit is contained in:
@@ -68,6 +68,12 @@ export const ROUTE_PATHS = Object.freeze({
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/networking"
|
||||
)
|
||||
},
|
||||
Pam: {
|
||||
ApprovalRequestDetailPage: setRoute(
|
||||
"/organizations/$orgId/projects/pam/$projectId/approval-requests/$approvalRequestId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/pam/$projectId/_pam-layout/approval-requests/$approvalRequestId"
|
||||
)
|
||||
},
|
||||
SecretManager: {
|
||||
ApprovalPage: setRoute(
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/approval",
|
||||
|
||||
@@ -23,7 +23,7 @@ export type PamAccessPolicyConditions = {
|
||||
}[];
|
||||
|
||||
export type PamAccessPolicyConstraints = {
|
||||
requestDurationHours: {
|
||||
requestDurationSeconds: {
|
||||
min: number;
|
||||
max: number;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
export const ApprovalRequestDetailPage = () => {
|
||||
return <div>Request detail</div>;
|
||||
};
|
||||
19
frontend/src/pages/pam/ApprovalRequestDetailPage/route.tsx
Normal file
19
frontend/src/pages/pam/ApprovalRequestDetailPage/route.tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
import { createFileRoute } from "@tanstack/react-router";
|
||||
|
||||
import { ApprovalRequestDetailPage } from "./ApprovalRequestDetailPage";
|
||||
|
||||
export const Route = createFileRoute(
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/pam/$projectId/_pam-layout/approval-requests/$approvalRequestId"
|
||||
)({
|
||||
component: ApprovalRequestDetailPage,
|
||||
beforeLoad: ({ context }) => {
|
||||
return {
|
||||
breadcrumbs: [
|
||||
...context.breadcrumbs,
|
||||
{
|
||||
label: "Approval Request"
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
});
|
||||
@@ -5,6 +5,7 @@ import { useOrganization, useProject } from "@app/context";
|
||||
import { ApprovalControlTabs } from "@app/types/project";
|
||||
import { useNavigate, useSearch } from "@tanstack/react-router";
|
||||
import { PolicyTab } from "./components/PolicyTab";
|
||||
import { ApprovalRequestTab } from "./components/ApprovalRequestTab";
|
||||
|
||||
const Page = () => {
|
||||
const navigate = useNavigate();
|
||||
@@ -47,7 +48,7 @@ const Page = () => {
|
||||
</Tab>
|
||||
</TabList>
|
||||
<TabPanel value={ApprovalControlTabs.Requests}>
|
||||
<div>Hello</div>
|
||||
<ApprovalRequestTab />
|
||||
</TabPanel>
|
||||
<TabPanel value={ApprovalControlTabs.Policies}>
|
||||
<PolicyTab />
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
import { RequestsSection } from "./components";
|
||||
|
||||
export const ApprovalRequestTab = () => {
|
||||
return <RequestsSection />;
|
||||
};
|
||||
@@ -0,0 +1,12 @@
|
||||
import { RequestsTable } from "./RequestsTable";
|
||||
|
||||
export const RequestsSection = () => {
|
||||
return (
|
||||
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
||||
<div className="mb-4 flex items-center justify-between">
|
||||
<p className="text-xl font-medium text-mineshaft-100">Approval Requests</p>
|
||||
</div>
|
||||
<RequestsTable />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,387 @@
|
||||
import { useCallback, useMemo, useState } from "react";
|
||||
import {
|
||||
faCheckCircle,
|
||||
faChevronRight,
|
||||
faExclamationCircle,
|
||||
faFileCircleQuestion,
|
||||
faFilter,
|
||||
faMagnifyingGlass,
|
||||
faSearch
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { useNavigate } from "@tanstack/react-router";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { formatDistance } from "date-fns";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuTrigger,
|
||||
DropdownSubMenu,
|
||||
DropdownSubMenuContent,
|
||||
DropdownSubMenuTrigger,
|
||||
EmptyState,
|
||||
IconButton,
|
||||
Input,
|
||||
Pagination,
|
||||
Table,
|
||||
TableContainer,
|
||||
TableSkeleton,
|
||||
TBody,
|
||||
Td,
|
||||
Th,
|
||||
THead,
|
||||
Tr
|
||||
} from "@app/components/v2";
|
||||
import { Badge } from "@app/components/v3";
|
||||
import { useOrganization, useProject, useUser } from "@app/context";
|
||||
import { usePagination } from "@app/hooks";
|
||||
import { ApprovalPolicyType } from "@app/hooks/api/approvalPolicies";
|
||||
import {
|
||||
approvalRequestQuery,
|
||||
ApprovalRequestStatus,
|
||||
ApprovalRequestStepStatus,
|
||||
TApprovalRequest
|
||||
} from "@app/hooks/api/approvalRequests";
|
||||
import { ApproverType } from "@app/hooks/api/approvalPolicies";
|
||||
|
||||
type Filter = {
|
||||
status: "open" | "closed";
|
||||
closedStatuses: ApprovalRequestStatus[];
|
||||
};
|
||||
|
||||
const getStatusBadgeColor = (status: ApprovalRequestStatus) => {
|
||||
switch (status) {
|
||||
case ApprovalRequestStatus.Pending:
|
||||
return "project";
|
||||
case ApprovalRequestStatus.Approved:
|
||||
return "success";
|
||||
case ApprovalRequestStatus.Rejected:
|
||||
return "danger";
|
||||
case ApprovalRequestStatus.Expired:
|
||||
return "neutral";
|
||||
default:
|
||||
return "neutral";
|
||||
}
|
||||
};
|
||||
|
||||
const formatDuration = (seconds: number) => {
|
||||
const hours = Math.floor(seconds / 3600);
|
||||
const minutes = Math.floor((seconds % 3600) / 60);
|
||||
|
||||
if (hours > 0) {
|
||||
return `${hours}h${minutes > 0 ? ` ${minutes}m` : ""}`;
|
||||
}
|
||||
return `${minutes}m`;
|
||||
};
|
||||
|
||||
const checkIfUserNeedsToApprove = (request: TApprovalRequest, userId: string): boolean => {
|
||||
const currentStep = request.steps.find(
|
||||
(step) => step.status === ApprovalRequestStepStatus.InProgress
|
||||
);
|
||||
|
||||
if (!currentStep) return false;
|
||||
|
||||
const isApprover = currentStep.approvers.some(
|
||||
(approver) => approver.type === ApproverType.User && approver.id === userId
|
||||
);
|
||||
|
||||
if (!isApprover) return false;
|
||||
|
||||
const hasAlreadyApproved = currentStep.approvals.some(
|
||||
(approval) => approval.approverId === userId
|
||||
);
|
||||
|
||||
return !hasAlreadyApproved;
|
||||
};
|
||||
|
||||
export const RequestsTable = () => {
|
||||
const navigate = useNavigate();
|
||||
const { currentOrg } = useOrganization();
|
||||
const { currentProject } = useProject();
|
||||
const { user } = useUser();
|
||||
const [search, setSearch] = useState("");
|
||||
const [filter, setFilter] = useState<Filter>({
|
||||
status: "open",
|
||||
closedStatuses: []
|
||||
});
|
||||
|
||||
const projectId = currentProject?.id || "";
|
||||
const userId = user?.id || "";
|
||||
|
||||
const { data: requests = [], isPending: isRequestsLoading } = useQuery(
|
||||
approvalRequestQuery.list({
|
||||
policyType: ApprovalPolicyType.PamAccess,
|
||||
projectId
|
||||
})
|
||||
);
|
||||
|
||||
const { page, perPage, setPage, setPerPage, offset } = usePagination();
|
||||
|
||||
const filteredRequests = useMemo(() => {
|
||||
let filtered = requests;
|
||||
|
||||
// Apply search filter
|
||||
if (search) {
|
||||
filtered = filtered.filter(
|
||||
(request) =>
|
||||
request.requesterName?.toLowerCase().includes(search.toLowerCase()) ||
|
||||
request.requesterEmail?.toLowerCase().includes(search.toLowerCase()) ||
|
||||
request.justification?.toLowerCase().includes(search.toLowerCase()) ||
|
||||
request.requestData.requestData.resourceId.toLowerCase().includes(search.toLowerCase()) ||
|
||||
request.requestData.requestData.accountPath.toLowerCase().includes(search.toLowerCase())
|
||||
);
|
||||
}
|
||||
|
||||
// Apply open/closed filter
|
||||
if (filter.status === "open") {
|
||||
filtered = filtered.filter((req) => req.status === ApprovalRequestStatus.Pending);
|
||||
} else {
|
||||
const closedStatuses = [
|
||||
ApprovalRequestStatus.Approved,
|
||||
ApprovalRequestStatus.Rejected,
|
||||
ApprovalRequestStatus.Expired
|
||||
];
|
||||
filtered = filtered.filter((req) => closedStatuses.includes(req.status));
|
||||
|
||||
// Apply specific closed status filter
|
||||
if (filter.closedStatuses.length > 0) {
|
||||
filtered = filtered.filter((req) => filter.closedStatuses.includes(req.status));
|
||||
}
|
||||
}
|
||||
|
||||
return filtered;
|
||||
}, [requests, search, filter]);
|
||||
|
||||
const paginatedRequests = useMemo(
|
||||
() => filteredRequests.slice(offset, offset + perPage),
|
||||
[filteredRequests, offset, perPage]
|
||||
);
|
||||
|
||||
const handleRowClick = (requestId: string) => {
|
||||
navigate({
|
||||
to: "/organizations/$orgId/projects/pam/$projectId/approval-requests/$approvalRequestId",
|
||||
params: {
|
||||
orgId: currentOrg.id,
|
||||
projectId: currentProject.id,
|
||||
approvalRequestId: requestId
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const handleStatusFilterToggle = useCallback(
|
||||
() =>
|
||||
setFilter((state) => ({
|
||||
...state,
|
||||
status: state.status === "open" ? "closed" : "open",
|
||||
closedStatuses: []
|
||||
})),
|
||||
[]
|
||||
);
|
||||
|
||||
const handleClosedStatusToggle = useCallback(
|
||||
(status: ApprovalRequestStatus) =>
|
||||
setFilter((state) => {
|
||||
const closedStatuses = state.closedStatuses || [];
|
||||
|
||||
if (closedStatuses.includes(status)) {
|
||||
return { ...state, closedStatuses: closedStatuses.filter((s) => s !== status) };
|
||||
}
|
||||
return { ...state, closedStatuses: [...closedStatuses, status] };
|
||||
}),
|
||||
[]
|
||||
);
|
||||
|
||||
const isTableFiltered = filter.status === "closed" || filter.closedStatuses.length > 0;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="flex gap-2">
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<IconButton
|
||||
ariaLabel="Filter Requests"
|
||||
variant="plain"
|
||||
size="sm"
|
||||
className={twMerge(
|
||||
"flex h-9.5 w-[2.6rem] items-center justify-center overflow-hidden border border-mineshaft-600 bg-mineshaft-800 p-0 transition-all hover:border-primary/60 hover:bg-primary/10",
|
||||
isTableFiltered && "border-primary/50 text-primary"
|
||||
)}
|
||||
>
|
||||
<FontAwesomeIcon icon={faFilter} />
|
||||
</IconButton>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="start" className="p-0">
|
||||
<DropdownMenuLabel>Filter By</DropdownMenuLabel>
|
||||
<DropdownMenuItem
|
||||
onClick={(evt) => {
|
||||
evt.preventDefault();
|
||||
handleStatusFilterToggle();
|
||||
}}
|
||||
icon={filter.status === "open" && <FontAwesomeIcon icon={faCheckCircle} />}
|
||||
iconPos="right"
|
||||
>
|
||||
Open Requests
|
||||
</DropdownMenuItem>
|
||||
<DropdownSubMenu>
|
||||
<DropdownSubMenuTrigger
|
||||
iconPos="right"
|
||||
icon={<FontAwesomeIcon icon={faChevronRight} size="sm" />}
|
||||
>
|
||||
Closed Requests
|
||||
</DropdownSubMenuTrigger>
|
||||
<DropdownSubMenuContent className="max-h-80 thin-scrollbar overflow-y-auto rounded-l-none">
|
||||
<DropdownMenuLabel className="sticky top-0 bg-mineshaft-900">
|
||||
Filter by Status
|
||||
</DropdownMenuLabel>
|
||||
<DropdownMenuItem
|
||||
onClick={(evt) => {
|
||||
evt.preventDefault();
|
||||
handleClosedStatusToggle(ApprovalRequestStatus.Approved);
|
||||
}}
|
||||
icon={
|
||||
filter.closedStatuses.includes(ApprovalRequestStatus.Approved) && (
|
||||
<FontAwesomeIcon icon={faCheckCircle} />
|
||||
)
|
||||
}
|
||||
iconPos="right"
|
||||
>
|
||||
Approved
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
onClick={(evt) => {
|
||||
evt.preventDefault();
|
||||
handleClosedStatusToggle(ApprovalRequestStatus.Rejected);
|
||||
}}
|
||||
icon={
|
||||
filter.closedStatuses.includes(ApprovalRequestStatus.Rejected) && (
|
||||
<FontAwesomeIcon icon={faCheckCircle} />
|
||||
)
|
||||
}
|
||||
iconPos="right"
|
||||
>
|
||||
Rejected
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
onClick={(evt) => {
|
||||
evt.preventDefault();
|
||||
handleClosedStatusToggle(ApprovalRequestStatus.Expired);
|
||||
}}
|
||||
icon={
|
||||
filter.closedStatuses.includes(ApprovalRequestStatus.Expired) && (
|
||||
<FontAwesomeIcon icon={faCheckCircle} />
|
||||
)
|
||||
}
|
||||
iconPos="right"
|
||||
>
|
||||
Expired
|
||||
</DropdownMenuItem>
|
||||
</DropdownSubMenuContent>
|
||||
</DropdownSubMenu>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
<Input
|
||||
value={search}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
leftIcon={<FontAwesomeIcon icon={faMagnifyingGlass} />}
|
||||
placeholder="Search approval requests..."
|
||||
/>
|
||||
</div>
|
||||
<TableContainer className="mt-4">
|
||||
<Table>
|
||||
<THead>
|
||||
<Tr>
|
||||
<Th>Requester</Th>
|
||||
<Th>Resource / Path</Th>
|
||||
<Th>Duration</Th>
|
||||
<Th>Status</Th>
|
||||
<Th>Requested</Th>
|
||||
</Tr>
|
||||
</THead>
|
||||
<TBody>
|
||||
{isRequestsLoading && <TableSkeleton columns={5} innerKey="approval-requests" />}
|
||||
{!isRequestsLoading &&
|
||||
paginatedRequests.map((request) => {
|
||||
const needsApproval = checkIfUserNeedsToApprove(request, userId);
|
||||
const { resourceId, accountPath, requestDurationSeconds } =
|
||||
request.requestData.requestData;
|
||||
|
||||
return (
|
||||
<Tr
|
||||
key={request.id}
|
||||
className={twMerge(
|
||||
"cursor-pointer transition-colors hover:bg-mineshaft-700",
|
||||
needsApproval && "bg-primary/5 hover:bg-primary/10"
|
||||
)}
|
||||
onClick={() => handleRowClick(request.id)}
|
||||
>
|
||||
<Td>
|
||||
<div>
|
||||
<div className="text-sm font-medium text-mineshaft-100">
|
||||
{request.requesterName || "Unknown"}
|
||||
</div>
|
||||
<div className="text-xs text-mineshaft-400">{request.requesterEmail}</div>
|
||||
</div>
|
||||
</Td>
|
||||
<Td>
|
||||
<div>
|
||||
<div className="text-sm text-mineshaft-200">{accountPath}</div>
|
||||
<div className="font-mono text-xs text-mineshaft-400">
|
||||
{resourceId.slice(0, 8)}...
|
||||
</div>
|
||||
</div>
|
||||
</Td>
|
||||
<Td>
|
||||
<span className="text-sm text-mineshaft-200">
|
||||
{formatDuration(requestDurationSeconds)}
|
||||
</span>
|
||||
</Td>
|
||||
<Td>
|
||||
<div className="flex items-center gap-2">
|
||||
<Badge variant={getStatusBadgeColor(request.status)}>
|
||||
{request.status}
|
||||
</Badge>
|
||||
{needsApproval && (
|
||||
<div className="flex items-center gap-1 rounded bg-primary/20 px-2 py-0.5 text-xs text-primary">
|
||||
<FontAwesomeIcon icon={faExclamationCircle} className="h-3 w-3" />
|
||||
<span>Approval Required</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Td>
|
||||
<Td>
|
||||
<span className="text-sm text-mineshaft-400">
|
||||
{formatDistance(new Date(request.createdAt), new Date(), {
|
||||
addSuffix: true
|
||||
})}
|
||||
</span>
|
||||
</Td>
|
||||
</Tr>
|
||||
);
|
||||
})}
|
||||
</TBody>
|
||||
</Table>
|
||||
{Boolean(filteredRequests.length) && (
|
||||
<Pagination
|
||||
count={filteredRequests.length}
|
||||
page={page}
|
||||
perPage={perPage}
|
||||
onChangePage={setPage}
|
||||
onChangePerPage={setPerPage}
|
||||
/>
|
||||
)}
|
||||
{!isRequestsLoading && !filteredRequests?.length && (
|
||||
<EmptyState
|
||||
title={
|
||||
requests.length ? "No approval requests match search..." : "No approval requests found"
|
||||
}
|
||||
icon={requests.length ? faSearch : faFileCircleQuestion}
|
||||
/>
|
||||
)}
|
||||
</TableContainer>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,2 @@
|
||||
export { RequestsSection } from "./RequestsSection";
|
||||
export { RequestsTable } from "./RequestsTable";
|
||||
@@ -0,0 +1 @@
|
||||
export { ApprovalRequestTab } from "./ApprovalRequestTab";
|
||||
@@ -48,9 +48,9 @@ export const PolicyModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
maxRequestTtlSeconds: null,
|
||||
conditions: [{ resourceIds: [], accountPaths: [] }],
|
||||
constraints: {
|
||||
requestDurationHours: {
|
||||
min: 1,
|
||||
max: 24
|
||||
requestDurationSeconds: {
|
||||
min: 30,
|
||||
max: 604800
|
||||
}
|
||||
},
|
||||
steps: [
|
||||
@@ -88,9 +88,9 @@ export const PolicyModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
maxRequestTtlSeconds: null,
|
||||
conditions: [{ resourceIds: [], accountPaths: [] }],
|
||||
constraints: {
|
||||
requestDurationHours: {
|
||||
min: 1,
|
||||
max: 24
|
||||
requestDurationSeconds: {
|
||||
min: 30,
|
||||
max: 604800
|
||||
}
|
||||
},
|
||||
steps: [
|
||||
|
||||
@@ -12,9 +12,9 @@ export const PolicyFormSchema = z.object({
|
||||
.array()
|
||||
.min(1, "At least one condition is required"),
|
||||
constraints: z.object({
|
||||
requestDurationHours: z.object({
|
||||
min: z.number().min(0).max(168),
|
||||
max: z.number().min(1).max(168)
|
||||
requestDurationSeconds: z.object({
|
||||
min: z.number().min(0).max(604800),
|
||||
max: z.number().min(1).max(604800)
|
||||
})
|
||||
}),
|
||||
steps: z
|
||||
|
||||
@@ -51,19 +51,19 @@ export const PolicyDetailsStep = () => {
|
||||
Request Duration Constraints
|
||||
</p>
|
||||
<p className="text-xs text-mineshaft-400">
|
||||
Set minimum and maximum duration (in hours) for access requests
|
||||
Set minimum and maximum duration (in seconds) for access requests
|
||||
</p>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<Controller
|
||||
control={control}
|
||||
name="constraints.requestDurationHours.min"
|
||||
name="constraints.requestDurationSeconds.min"
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<FormControl
|
||||
label="Minimum Hours"
|
||||
isError={Boolean(error)}
|
||||
errorText={error?.message}
|
||||
helperText="0-168 hours"
|
||||
helperText="30-604800 hours"
|
||||
>
|
||||
<Input
|
||||
{...field}
|
||||
@@ -77,13 +77,13 @@ export const PolicyDetailsStep = () => {
|
||||
/>
|
||||
<Controller
|
||||
control={control}
|
||||
name="constraints.requestDurationHours.max"
|
||||
name="constraints.requestDurationSeconds.max"
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<FormControl
|
||||
label="Maximum Hours"
|
||||
isError={Boolean(error)}
|
||||
errorText={error?.message}
|
||||
helperText="1-168 hours (7 days)"
|
||||
helperText="30-604800 hours (7 days)"
|
||||
>
|
||||
<Input
|
||||
{...field}
|
||||
|
||||
@@ -70,11 +70,11 @@ export const PolicyReviewStep = () => {
|
||||
<div className="space-y-2">
|
||||
<ReviewField
|
||||
label="Minimum Duration"
|
||||
value={`${constraints.requestDurationHours.min} hour${constraints.requestDurationHours.min !== 1 ? "s" : ""}`}
|
||||
value={`${constraints.requestDurationSeconds.min} second${constraints.requestDurationSeconds.min !== 1 ? "s" : ""}`}
|
||||
/>
|
||||
<ReviewField
|
||||
label="Maximum Duration"
|
||||
value={`${constraints.requestDurationHours.max} hour${constraints.requestDurationHours.max !== 1 ? "s" : ""}`}
|
||||
value={`${constraints.requestDurationSeconds.max} second${constraints.requestDurationSeconds.max !== 1 ? "s" : ""}`}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -151,6 +151,7 @@ import { Route as secretManagerSecretDashboardPageRouteImport } from './pages/se
|
||||
import { Route as secretManagerIntegrationsSelectIntegrationAuthPageRouteImport } from './pages/secret-manager/integrations/SelectIntegrationAuthPage/route'
|
||||
import { Route as secretManagerIntegrationsDetailsByIDPageRouteImport } from './pages/secret-manager/IntegrationsDetailsByIDPage/route'
|
||||
import { Route as pamPamSessionsByIDPageRouteImport } from './pages/pam/PamSessionsByIDPage/route'
|
||||
import { Route as pamApprovalRequestDetailPageRouteImport } from './pages/pam/ApprovalRequestDetailPage/route'
|
||||
import { Route as certManagerPkiSubscriberDetailsByIDPageRouteImport } from './pages/cert-manager/PkiSubscriberDetailsByIDPage/route'
|
||||
import { Route as certManagerPkiSyncDetailsByIDPageRouteImport } from './pages/cert-manager/PkiSyncDetailsByIDPage/route'
|
||||
import { Route as certManagerCertAuthDetailsByIDPageRouteImport } from './pages/cert-manager/CertAuthDetailsByIDPage/route'
|
||||
@@ -1504,6 +1505,13 @@ const pamPamSessionsByIDPageRouteRoute =
|
||||
AuthenticateInjectOrgDetailsOrgLayoutOrganizationsOrgIdProjectsPamProjectIdPamLayoutSessionsRoute,
|
||||
} as any)
|
||||
|
||||
const pamApprovalRequestDetailPageRouteRoute =
|
||||
pamApprovalRequestDetailPageRouteImport.update({
|
||||
id: '/approval-requests/$approvalRequestId',
|
||||
path: '/approval-requests/$approvalRequestId',
|
||||
getParentRoute: () => pamLayoutRoute,
|
||||
} as any)
|
||||
|
||||
const certManagerPkiSubscriberDetailsByIDPageRouteRoute =
|
||||
certManagerPkiSubscriberDetailsByIDPageRouteImport.update({
|
||||
id: '/$subscriberName',
|
||||
@@ -3217,6 +3225,13 @@ declare module '@tanstack/react-router' {
|
||||
preLoaderRoute: typeof certManagerPkiSubscriberDetailsByIDPageRouteImport
|
||||
parentRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationsOrgIdProjectsCertManagementProjectIdCertManagerLayoutSubscribersImport
|
||||
}
|
||||
'/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/pam/$projectId/_pam-layout/approval-requests/$approvalRequestId': {
|
||||
id: '/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/pam/$projectId/_pam-layout/approval-requests/$approvalRequestId'
|
||||
path: '/approval-requests/$approvalRequestId'
|
||||
fullPath: '/organizations/$orgId/projects/pam/$projectId/approval-requests/$approvalRequestId'
|
||||
preLoaderRoute: typeof pamApprovalRequestDetailPageRouteImport
|
||||
parentRoute: typeof pamLayoutImport
|
||||
}
|
||||
'/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/pam/$projectId/_pam-layout/sessions/$sessionId': {
|
||||
id: '/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/pam/$projectId/_pam-layout/sessions/$sessionId'
|
||||
path: '/$sessionId'
|
||||
@@ -4234,6 +4249,7 @@ interface pamLayoutRouteChildren {
|
||||
projectAccessControlPageRoutePamRoute: typeof projectAccessControlPageRoutePamRoute
|
||||
projectAuditLogsPageRoutePamRoute: typeof projectAuditLogsPageRoutePamRoute
|
||||
AuthenticateInjectOrgDetailsOrgLayoutOrganizationsOrgIdProjectsPamProjectIdPamLayoutSessionsRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationsOrgIdProjectsPamProjectIdPamLayoutSessionsRouteWithChildren
|
||||
pamApprovalRequestDetailPageRouteRoute: typeof pamApprovalRequestDetailPageRouteRoute
|
||||
projectGroupDetailsByIDPageRoutePamRoute: typeof projectGroupDetailsByIDPageRoutePamRoute
|
||||
projectIdentityDetailsByIDPageRoutePamRoute: typeof projectIdentityDetailsByIDPageRoutePamRoute
|
||||
projectMemberDetailsByIDPageRoutePamRoute: typeof projectMemberDetailsByIDPageRoutePamRoute
|
||||
@@ -4249,6 +4265,8 @@ const pamLayoutRouteChildren: pamLayoutRouteChildren = {
|
||||
projectAuditLogsPageRoutePamRoute: projectAuditLogsPageRoutePamRoute,
|
||||
AuthenticateInjectOrgDetailsOrgLayoutOrganizationsOrgIdProjectsPamProjectIdPamLayoutSessionsRoute:
|
||||
AuthenticateInjectOrgDetailsOrgLayoutOrganizationsOrgIdProjectsPamProjectIdPamLayoutSessionsRouteWithChildren,
|
||||
pamApprovalRequestDetailPageRouteRoute:
|
||||
pamApprovalRequestDetailPageRouteRoute,
|
||||
projectGroupDetailsByIDPageRoutePamRoute:
|
||||
projectGroupDetailsByIDPageRoutePamRoute,
|
||||
projectIdentityDetailsByIDPageRoutePamRoute:
|
||||
@@ -5219,6 +5237,7 @@ export interface FileRoutesByFullPath {
|
||||
'/organizations/$orgId/projects/cert-management/$projectId/ca/$caId': typeof certManagerCertAuthDetailsByIDPageRouteRoute
|
||||
'/organizations/$orgId/projects/cert-management/$projectId/integrations/$syncId': typeof certManagerPkiSyncDetailsByIDPageRouteRoute
|
||||
'/organizations/$orgId/projects/cert-management/$projectId/subscribers/$subscriberName': typeof certManagerPkiSubscriberDetailsByIDPageRouteRoute
|
||||
'/organizations/$orgId/projects/pam/$projectId/approval-requests/$approvalRequestId': typeof pamApprovalRequestDetailPageRouteRoute
|
||||
'/organizations/$orgId/projects/pam/$projectId/sessions/$sessionId': typeof pamPamSessionsByIDPageRouteRoute
|
||||
'/organizations/$orgId/projects/secret-management/$projectId/integrations/$integrationId': typeof secretManagerIntegrationsDetailsByIDPageRouteRoute
|
||||
'/organizations/$orgId/projects/secret-management/$projectId/integrations/select-integration-auth': typeof secretManagerIntegrationsSelectIntegrationAuthPageRouteRoute
|
||||
@@ -5450,6 +5469,7 @@ export interface FileRoutesByTo {
|
||||
'/organizations/$orgId/projects/cert-management/$projectId/ca/$caId': typeof certManagerCertAuthDetailsByIDPageRouteRoute
|
||||
'/organizations/$orgId/projects/cert-management/$projectId/integrations/$syncId': typeof certManagerPkiSyncDetailsByIDPageRouteRoute
|
||||
'/organizations/$orgId/projects/cert-management/$projectId/subscribers/$subscriberName': typeof certManagerPkiSubscriberDetailsByIDPageRouteRoute
|
||||
'/organizations/$orgId/projects/pam/$projectId/approval-requests/$approvalRequestId': typeof pamApprovalRequestDetailPageRouteRoute
|
||||
'/organizations/$orgId/projects/pam/$projectId/sessions/$sessionId': typeof pamPamSessionsByIDPageRouteRoute
|
||||
'/organizations/$orgId/projects/secret-management/$projectId/integrations/$integrationId': typeof secretManagerIntegrationsDetailsByIDPageRouteRoute
|
||||
'/organizations/$orgId/projects/secret-management/$projectId/integrations/select-integration-auth': typeof secretManagerIntegrationsSelectIntegrationAuthPageRouteRoute
|
||||
@@ -5704,6 +5724,7 @@ export interface FileRoutesById {
|
||||
'/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/ca/$caId': typeof certManagerCertAuthDetailsByIDPageRouteRoute
|
||||
'/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/integrations/$syncId': typeof certManagerPkiSyncDetailsByIDPageRouteRoute
|
||||
'/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/subscribers/$subscriberName': typeof certManagerPkiSubscriberDetailsByIDPageRouteRoute
|
||||
'/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/pam/$projectId/_pam-layout/approval-requests/$approvalRequestId': typeof pamApprovalRequestDetailPageRouteRoute
|
||||
'/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/pam/$projectId/_pam-layout/sessions/$sessionId': typeof pamPamSessionsByIDPageRouteRoute
|
||||
'/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/$integrationId': typeof secretManagerIntegrationsDetailsByIDPageRouteRoute
|
||||
'/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/select-integration-auth': typeof secretManagerIntegrationsSelectIntegrationAuthPageRouteRoute
|
||||
@@ -5950,6 +5971,7 @@ export interface FileRouteTypes {
|
||||
| '/organizations/$orgId/projects/cert-management/$projectId/ca/$caId'
|
||||
| '/organizations/$orgId/projects/cert-management/$projectId/integrations/$syncId'
|
||||
| '/organizations/$orgId/projects/cert-management/$projectId/subscribers/$subscriberName'
|
||||
| '/organizations/$orgId/projects/pam/$projectId/approval-requests/$approvalRequestId'
|
||||
| '/organizations/$orgId/projects/pam/$projectId/sessions/$sessionId'
|
||||
| '/organizations/$orgId/projects/secret-management/$projectId/integrations/$integrationId'
|
||||
| '/organizations/$orgId/projects/secret-management/$projectId/integrations/select-integration-auth'
|
||||
@@ -6180,6 +6202,7 @@ export interface FileRouteTypes {
|
||||
| '/organizations/$orgId/projects/cert-management/$projectId/ca/$caId'
|
||||
| '/organizations/$orgId/projects/cert-management/$projectId/integrations/$syncId'
|
||||
| '/organizations/$orgId/projects/cert-management/$projectId/subscribers/$subscriberName'
|
||||
| '/organizations/$orgId/projects/pam/$projectId/approval-requests/$approvalRequestId'
|
||||
| '/organizations/$orgId/projects/pam/$projectId/sessions/$sessionId'
|
||||
| '/organizations/$orgId/projects/secret-management/$projectId/integrations/$integrationId'
|
||||
| '/organizations/$orgId/projects/secret-management/$projectId/integrations/select-integration-auth'
|
||||
@@ -6432,6 +6455,7 @@ export interface FileRouteTypes {
|
||||
| '/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/ca/$caId'
|
||||
| '/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/integrations/$syncId'
|
||||
| '/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/subscribers/$subscriberName'
|
||||
| '/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/pam/$projectId/_pam-layout/approval-requests/$approvalRequestId'
|
||||
| '/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/pam/$projectId/_pam-layout/sessions/$sessionId'
|
||||
| '/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/$integrationId'
|
||||
| '/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/select-integration-auth'
|
||||
@@ -7086,6 +7110,7 @@ export const routeTree = rootRoute
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/pam/$projectId/_pam-layout/access-management",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/pam/$projectId/_pam-layout/audit-logs",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/pam/$projectId/_pam-layout/sessions",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/pam/$projectId/_pam-layout/approval-requests/$approvalRequestId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/pam/$projectId/_pam-layout/groups/$groupId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/pam/$projectId/_pam-layout/identities/$identityId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/pam/$projectId/_pam-layout/members/$membershipId",
|
||||
@@ -7454,6 +7479,10 @@ export const routeTree = rootRoute
|
||||
"filePath": "cert-manager/PkiSubscriberDetailsByIDPage/route.tsx",
|
||||
"parent": "/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/subscribers"
|
||||
},
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/pam/$projectId/_pam-layout/approval-requests/$approvalRequestId": {
|
||||
"filePath": "pam/ApprovalRequestDetailPage/route.tsx",
|
||||
"parent": "/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/pam/$projectId/_pam-layout"
|
||||
},
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/pam/$projectId/_pam-layout/sessions/$sessionId": {
|
||||
"filePath": "pam/PamSessionsByIDPage/route.tsx",
|
||||
"parent": "/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/pam/$projectId/_pam-layout/sessions"
|
||||
|
||||
@@ -358,10 +358,11 @@ const pamRoutes = route("/organizations/$orgId/projects/pam/$projectId", [
|
||||
route("/resources", "pam/PamResourcesPage/route.tsx"),
|
||||
route("/audit-logs", "project/AuditLogsPage/route-pam.tsx"),
|
||||
route("/settings", "pam/SettingsPage/route.tsx"),
|
||||
route("/approvals", "pam/ApprovalsPage/route.tsx"),
|
||||
route("/approval-requests/$approvalRequestId", "pam/ApprovalRequestDetailPage/route.tsx"),
|
||||
|
||||
// Access Management
|
||||
route("/access-management", "project/AccessControlPage/route-pam.tsx"),
|
||||
route("/approvals", "pam/ApprovalsPage/route.tsx"),
|
||||
route("/roles/$roleSlug", "project/RoleDetailsBySlugPage/route-pam.tsx"),
|
||||
route("/identities/$identityId", "project/IdentityDetailsByIDPage/route-pam.tsx"),
|
||||
route("/members/$membershipId", "project/MemberDetailsByIDPage/route-pam.tsx"),
|
||||
|
||||
Reference in New Issue
Block a user