feat: fixed migration issues and resolved all routes in frontend

This commit is contained in:
=
2024-12-13 21:38:42 +05:30
parent 69bf9dc20f
commit a857375cc1
69 changed files with 547 additions and 265 deletions
@@ -1,11 +1,12 @@
import slugify from "@sindresorhus/slugify";
import { Knex } from "knex"; import { Knex } from "knex";
import { v4 as uuidV4 } from "uuid"; import { v4 as uuidV4 } from "uuid";
import slugify from "@sindresorhus/slugify";
import { ProjectType, TableName } from "../schemas";
import { alphaNumericNanoId } from "@app/lib/nanoid"; import { alphaNumericNanoId } from "@app/lib/nanoid";
/* eslint-disable no-await-in-loop,no-param-reassign,@typescript-eslint/ban-ts-comment */ import { ProjectType, TableName } from "../schemas";
/* eslint-disable no-await-in-loop,@typescript-eslint/ban-ts-comment */
const newProject = async (knex: Knex, projectId: string, projectType: ProjectType) => { const newProject = async (knex: Knex, projectId: string, projectType: ProjectType) => {
const newProjectId = uuidV4(); const newProjectId = uuidV4();
const project = await knex(TableName.Project).where("id", projectId).first(); const project = await knex(TableName.Project).where("id", projectId).first();
@@ -24,10 +25,12 @@ const newProject = async (knex: Knex, projectId: string, projectType: ProjectTyp
projectCustomRoles.map((el) => { projectCustomRoles.map((el) => {
const id = uuidV4(); const id = uuidV4();
customRoleMapping[el.id] = id; customRoleMapping[el.id] = id;
el.id = id; return {
el.projectId = newProjectId; ...el,
el.permissions = el.permissions ? JSON.stringify(el.permissions) : el.permissions; id,
return el; projectId: newProjectId,
permissions: el.permissions ? JSON.stringify(el.permissions) : el.permissions
};
}) })
); );
} }
@@ -38,9 +41,7 @@ const newProject = async (knex: Knex, projectId: string, projectType: ProjectTyp
groupMemberships.map((el) => { groupMemberships.map((el) => {
const id = uuidV4(); const id = uuidV4();
groupMembershipMapping[el.id] = id; groupMembershipMapping[el.id] = id;
el.id = id; return { ...el, id, projectId: newProjectId };
el.projectId = newProjectId;
return el;
}) })
); );
} }
@@ -53,10 +54,9 @@ const newProject = async (knex: Knex, projectId: string, projectType: ProjectTyp
await knex(TableName.GroupProjectMembershipRole).insert( await knex(TableName.GroupProjectMembershipRole).insert(
groupMembershipRoles.map((el) => { groupMembershipRoles.map((el) => {
const id = uuidV4(); const id = uuidV4();
el.id = id; const projectMembershipId = groupMembershipMapping[el.id];
el.projectMembershipId = groupMembershipMapping[el.id]; const customRoleId = el.customRoleId ? customRoleMapping[el.customRoleId] : el.customRoleId;
el.customRoleId = el.customRoleId ? customRoleMapping[el.customRoleId] : el.customRoleId; return { ...el, id, projectMembershipId, customRoleId };
return el;
}) })
); );
} }
@@ -68,9 +68,7 @@ const newProject = async (knex: Knex, projectId: string, projectType: ProjectTyp
identities.map((el) => { identities.map((el) => {
const id = uuidV4(); const id = uuidV4();
identityProjectMembershipMapping[el.id] = id; identityProjectMembershipMapping[el.id] = id;
el.id = id; return { ...el, id, projectId: newProjectId };
el.projectId = newProjectId;
return el;
}) })
); );
} }
@@ -83,10 +81,9 @@ const newProject = async (knex: Knex, projectId: string, projectType: ProjectTyp
await knex(TableName.IdentityProjectMembershipRole).insert( await knex(TableName.IdentityProjectMembershipRole).insert(
identitiesRoles.map((el) => { identitiesRoles.map((el) => {
const id = uuidV4(); const id = uuidV4();
el.id = id; const projectMembershipId = identityProjectMembershipMapping[el.projectMembershipId];
el.projectMembershipId = identityProjectMembershipMapping[el.projectMembershipId]; const customRoleId = el.customRoleId ? customRoleMapping[el.customRoleId] : el.customRoleId;
el.customRoleId = el.customRoleId ? customRoleMapping[el.customRoleId] : el.customRoleId; return { ...el, id, projectMembershipId, customRoleId };
return el;
}) })
); );
} }
@@ -98,9 +95,7 @@ const newProject = async (knex: Knex, projectId: string, projectType: ProjectTyp
projectUserMembers.map((el) => { projectUserMembers.map((el) => {
const id = uuidV4(); const id = uuidV4();
projectMembershipMapping[el.id] = id; projectMembershipMapping[el.id] = id;
el.id = id; return { ...el, id, projectId: newProjectId };
el.projectId = newProjectId;
return el;
}) })
); );
} }
@@ -112,10 +107,9 @@ const newProject = async (knex: Knex, projectId: string, projectType: ProjectTyp
await knex(TableName.ProjectUserMembershipRole).insert( await knex(TableName.ProjectUserMembershipRole).insert(
membershipRoles.map((el) => { membershipRoles.map((el) => {
const id = uuidV4(); const id = uuidV4();
el.id = id; const projectMembershipId = projectMembershipMapping[el.projectMembershipId];
el.projectMembershipId = projectMembershipMapping[el.projectMembershipId]; const customRoleId = el.customRoleId ? customRoleMapping[el.customRoleId] : el.customRoleId;
el.customRoleId = el.customRoleId ? customRoleMapping[el.customRoleId] : el.customRoleId; return { ...el, id, projectMembershipId, customRoleId };
return el;
}) })
); );
} }
@@ -125,10 +119,8 @@ const newProject = async (knex: Knex, projectId: string, projectType: ProjectTyp
await knex(TableName.KmsKey).insert( await knex(TableName.KmsKey).insert(
kmsKeys.map((el) => { kmsKeys.map((el) => {
const id = uuidV4(); const id = uuidV4();
el.id = id; const slug = slugify(alphaNumericNanoId(8).toLowerCase());
el.projectId = newProjectId; return { ...el, id, slug, projectId: newProjectId };
el.slug = slugify(alphaNumericNanoId(8).toLowerCase());
return el;
}) })
); );
} }
@@ -143,9 +135,7 @@ const newProject = async (knex: Knex, projectId: string, projectType: ProjectTyp
await knex(TableName.ProjectKeys).insert( await knex(TableName.ProjectKeys).insert(
projectKeys.map((el) => { projectKeys.map((el) => {
const id = uuidV4(); const id = uuidV4();
el.id = id; return { ...el, id, projectId: newProjectId };
el.projectId = newProjectId;
return el;
}) })
); );
} }
@@ -154,16 +144,14 @@ const newProject = async (knex: Knex, projectId: string, projectType: ProjectTyp
if (serviceTokens.length) { if (serviceTokens.length) {
await knex(TableName.ServiceToken).insert( await knex(TableName.ServiceToken).insert(
serviceTokens.map((el) => { serviceTokens.map((el) => {
el.id = uuidV4(); const id = uuidV4();
el.projectId = projectId; const scopes = el.scopes ? JSON.stringify(el.scopes) : el.scopes;
el.scopes = el.scopes ? JSON.stringify(el.scopes) : el.scopes; return { ...el, id, scopes, projectId: newProjectId };
return el;
}) })
); );
} }
return newProjectId; return newProjectId;
}; };
/* eslint-enable */
const BATCH_SIZE = 500; const BATCH_SIZE = 500;
export async function up(knex: Knex): Promise<void> { export async function up(knex: Knex): Promise<void> {
@@ -137,7 +137,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
.enum(["true", "false"]) .enum(["true", "false"])
.default("false") .default("false")
.transform((value) => value === "true"), .transform((value) => value === "true"),
type: z.nativeEnum(ProjectType).optional() type: z.enum([ProjectType.SecretManager, ProjectType.Cmek, ProjectType.CertificateManager, "all"]).optional()
}), }),
response: { response: {
200: z.object({ 200: z.object({
+1 -1
View File
@@ -197,7 +197,7 @@ export const orgServiceFactory = ({
const findAllWorkspaces = async ({ actor, actorId, orgId, type }: TFindAllWorkspacesDTO) => { const findAllWorkspaces = async ({ actor, actorId, orgId, type }: TFindAllWorkspacesDTO) => {
if (actor === ActorType.USER) { if (actor === ActorType.USER) {
const workspaces = await projectDAL.findAllProjects(actorId, orgId, type); const workspaces = await projectDAL.findAllProjects(actorId, orgId, type || "all");
return workspaces; return workspaces;
} }
+7 -3
View File
@@ -19,7 +19,7 @@ export type TProjectDALFactory = ReturnType<typeof projectDALFactory>;
export const projectDALFactory = (db: TDbClient) => { export const projectDALFactory = (db: TDbClient) => {
const projectOrm = ormify(db, TableName.Project); const projectOrm = ormify(db, TableName.Project);
const findAllProjects = async (userId: string, orgId: string, projectType?: ProjectType | null) => { const findAllProjects = async (userId: string, orgId: string, projectType: ProjectType | "all") => {
try { try {
const workspaces = await db const workspaces = await db
.replicaNode()(TableName.ProjectMembership) .replicaNode()(TableName.ProjectMembership)
@@ -27,7 +27,7 @@ export const projectDALFactory = (db: TDbClient) => {
.join(TableName.Project, `${TableName.ProjectMembership}.projectId`, `${TableName.Project}.id`) .join(TableName.Project, `${TableName.ProjectMembership}.projectId`, `${TableName.Project}.id`)
.where(`${TableName.Project}.orgId`, orgId) .where(`${TableName.Project}.orgId`, orgId)
.andWhere((qb) => { .andWhere((qb) => {
if (projectType) { if (projectType !== "all") {
void qb.where(`${TableName.Project}.type`, projectType); void qb.where(`${TableName.Project}.type`, projectType);
} }
}) })
@@ -130,7 +130,11 @@ export const projectDALFactory = (db: TDbClient) => {
.replicaNode()(TableName.IdentityProjectMembership) .replicaNode()(TableName.IdentityProjectMembership)
.where({ identityId }) .where({ identityId })
.join(TableName.Project, `${TableName.IdentityProjectMembership}.projectId`, `${TableName.Project}.id`) .join(TableName.Project, `${TableName.IdentityProjectMembership}.projectId`, `${TableName.Project}.id`)
.where(`${TableName.Project}.type`, projectType) .andWhere((qb) => {
if (projectType) {
void qb.where(`${TableName.Project}.type`, projectType);
}
})
.leftJoin(TableName.Environment, `${TableName.Environment}.projectId`, `${TableName.Project}.id`) .leftJoin(TableName.Environment, `${TableName.Environment}.projectId`, `${TableName.Project}.id`)
.select( .select(
selectAllTableCols(TableName.Project), selectAllTableCols(TableName.Project),
@@ -431,7 +431,13 @@ export const projectServiceFactory = ({
return deletedProject; return deletedProject;
}; };
const getProjects = async ({ actorId, includeRoles, actorAuthMethod, actorOrgId, type }: TListProjectsDTO) => { const getProjects = async ({
actorId,
includeRoles,
actorAuthMethod,
actorOrgId,
type = ProjectType.SecretManager
}: TListProjectsDTO) => {
const workspaces = await projectDAL.findAllProjects(actorId, actorOrgId, type); const workspaces = await projectDAL.findAllProjects(actorId, actorOrgId, type);
if (includeRoles) { if (includeRoles) {
@@ -85,7 +85,7 @@ export type TDeleteProjectDTO = {
export type TListProjectsDTO = { export type TListProjectsDTO = {
includeRoles: boolean; includeRoles: boolean;
type?: ProjectType | null; type?: ProjectType | "all";
} & Omit<TProjectPermission, "projectId">; } & Omit<TProjectPermission, "projectId">;
export type TUpgradeProjectDTO = { export type TUpgradeProjectDTO = {
@@ -5,6 +5,8 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { Menu, Transition } from "@headlessui/react"; import { Menu, Transition } from "@headlessui/react";
import { Tag } from "public/data/frequentInterfaces"; import { Tag } from "public/data/frequentInterfaces";
import { ProjectType } from "@app/hooks/api/workspace/types";
/** /**
* This is the menu that is used to add more tags to a secret * This is the menu that is used to add more tags to a secret
* @param {object} obj * @param {object} obj
@@ -75,7 +77,7 @@ const AddTagsMenu = ({
<button <button
type="button" type="button"
className="w-full rounded-sm bg-mineshaft-800 px-2 py-0.5 text-left text-bunker-200 duration-200 hover:bg-primary hover:text-black" className="w-full rounded-sm bg-mineshaft-800 px-2 py-0.5 text-left text-bunker-200 duration-200 hover:bg-primary hover:text-black"
onClick={() => router.push(`/project/${String(router.query.id)}/settings`)} onClick={() => router.push(`/${ProjectType.SecretManager}/${String(router.query.id)}/settings`)}
> >
<FontAwesomeIcon icon={faPlus} className="mr-2 text-xs" /> <FontAwesomeIcon icon={faPlus} className="mr-2 text-xs" />
Add more tags Add more tags
@@ -1,5 +1,7 @@
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { ProjectType } from "@app/hooks/api/workspace/types";
import { Button } from "../v2"; import { Button } from "../v2";
interface IProps { interface IProps {
@@ -20,7 +22,7 @@ export const NoEnvironmentsBanner = ({ projectId }: IProps) => {
</p> </p>
</div> </div>
<div className="my-2"> <div className="my-2">
<Button onClick={() => router.push(`/project/${projectId}/settings#environments`)}> <Button onClick={() => router.push(`/${ProjectType.SecretManager}/${projectId}/settings#environments`)}>
Add environments Add environments
</Button> </Button>
</div> </div>
@@ -148,7 +148,7 @@ const NewProjectForm = ({ onOpenChange, projectType }: NewProjectFormProps) => {
createNotification({ text: "Project created", type: "success" }); createNotification({ text: "Project created", type: "success" });
reset(); reset();
onOpenChange(false); onOpenChange(false);
router.push(`/project/${newProjectId}/${projectType}/overview`); router.push(`/${projectType}/${newProjectId}/${projectType}/overview`);
} catch (err) { } catch (err) {
console.error(err); console.error(err);
createNotification({ text: "Failed to create project", type: "error" }); createNotification({ text: "Failed to create project", type: "error" });
@@ -3,7 +3,7 @@ import { useRouter } from "next/router";
import { createNotification } from "@app/components/notifications"; import { createNotification } from "@app/components/notifications";
import { useGetUserWorkspaces } from "@app/hooks/api"; import { useGetUserWorkspaces } from "@app/hooks/api";
import { Workspace } from "@app/hooks/api/workspace/types"; import { ProjectType, Workspace } from "@app/hooks/api/workspace/types";
type TWorkspaceContext = { type TWorkspaceContext = {
workspaces: Workspace[]; workspaces: Workspace[];
@@ -35,7 +35,7 @@ export const WorkspaceProvider = ({ children }: Props): JSX.Element => {
const shouldTriggerNoProjectAccess = const shouldTriggerNoProjectAccess =
!value.isLoading && !value.isLoading &&
!value.currentWorkspace && !value.currentWorkspace &&
router.pathname.startsWith("/project") && Object.values(ProjectType).some((el) => router.pathname.startsWith(`/${el}`)) &&
workspaceId; workspaceId;
// handle redirects for project-specific routes // handle redirects for project-specific routes
+12
View File
@@ -0,0 +1,12 @@
import { Workspace } from "@app/hooks/api/types";
import { ProjectType } from "@app/hooks/api/workspace/types";
export const getWorkspaceHomePage = (workspace: Workspace) => {
if (workspace.type === ProjectType.SecretManager) {
return `/${workspace.type}/${workspace.id}/secrets/overview`;
}
if (workspace.type === ProjectType.CertificateManager) {
return `/${workspace.type}/${workspace.id}/certificates`;
}
return `/${workspace.type}/${workspace.id}/kms`;
};
+3 -3
View File
@@ -103,7 +103,7 @@ export const useGetUpgradeProjectStatus = ({
}); });
}; };
const fetchUserWorkspaces = async (includeRoles?: boolean, type?: ProjectType) => { const fetchUserWorkspaces = async (includeRoles?: boolean, type?: ProjectType | "all") => {
const { data } = await apiRequest.get<{ workspaces: Workspace[] }>("/api/v1/workspace", { const { data } = await apiRequest.get<{ workspaces: Workspace[] }>("/api/v1/workspace", {
params: { params: {
includeRoles, includeRoles,
@@ -143,10 +143,10 @@ export const useGetWorkspaceById = (
export const useGetUserWorkspaces = ({ export const useGetUserWorkspaces = ({
includeRoles, includeRoles,
type type = "all"
}: { }: {
includeRoles?: boolean; includeRoles?: boolean;
type?: ProjectType; type?: ProjectType | "all";
} = {}) => } = {}) =>
useQuery(workspaceKeys.getAllUserWorkspace(type || ""), () => useQuery(workspaceKeys.getAllUserWorkspace(type || ""), () =>
fetchUserWorkspaces(includeRoles, type) fetchUserWorkspaces(includeRoles, type)
+7 -160
View File
@@ -5,7 +5,7 @@
/* eslint-disable no-var */ /* eslint-disable no-var */
/* eslint-disable func-names */ /* eslint-disable func-names */
import { useEffect, useMemo, useState } from "react"; import { useEffect, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import Link from "next/link"; import Link from "next/link";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
@@ -38,13 +38,7 @@ import {
} from "@app/components/v2"; } from "@app/components/v2";
import { useOrganization, useSubscription, useUser, useWorkspace } from "@app/context"; import { useOrganization, useSubscription, useUser, useWorkspace } from "@app/context";
import { usePopUp, useToggle } from "@app/hooks"; import { usePopUp, useToggle } from "@app/hooks";
import { import { useGetOrgTrialUrl, useLogoutUser, useSelectOrganization } from "@app/hooks/api";
useGetAccessRequestsCount,
useGetOrgTrialUrl,
useGetSecretApprovalRequestCount,
useLogoutUser,
useSelectOrganization
} from "@app/hooks/api";
import { MfaMethod } from "@app/hooks/api/auth/types"; import { MfaMethod } from "@app/hooks/api/auth/types";
import { AuthMethod } from "@app/hooks/api/users/types"; import { AuthMethod } from "@app/hooks/api/users/types";
import { InsecureConnectionBanner } from "@app/layouts/AppLayout/components/InsecureConnectionBanner"; import { InsecureConnectionBanner } from "@app/layouts/AppLayout/components/InsecureConnectionBanner";
@@ -53,6 +47,7 @@ import { navigateUserToOrg } from "@app/views/Login/Login.utils";
import { Mfa } from "@app/views/Login/Mfa"; import { Mfa } from "@app/views/Login/Mfa";
import { CreateOrgModal } from "@app/views/Org/components"; import { CreateOrgModal } from "@app/views/Org/components";
import { ProjectSidebarItem } from "./components/ProjectSidebarItems";
import { WishForm } from "./components/WishForm/WishForm"; import { WishForm } from "./components/WishForm/WishForm";
interface LayoutProps { interface LayoutProps {
@@ -87,7 +82,7 @@ export const AppLayout = ({ children }: LayoutProps) => {
const { mutateAsync } = useGetOrgTrialUrl(); const { mutateAsync } = useGetOrgTrialUrl();
const { workspaces, currentWorkspace } = useWorkspace(); const { currentWorkspace } = useWorkspace();
const { orgs, currentOrg } = useOrganization(); const { orgs, currentOrg } = useOrganization();
const [shouldShowMfa, toggleShowMfa] = useToggle(false); const [shouldShowMfa, toggleShowMfa] = useToggle(false);
@@ -96,15 +91,6 @@ export const AppLayout = ({ children }: LayoutProps) => {
const { user } = useUser(); const { user } = useUser();
const { subscription } = useSubscription(); const { subscription } = useSubscription();
const workspaceId = currentWorkspace?.id || "";
const projectSlug = currentWorkspace?.slug || "";
const { data: secretApprovalReqCount } = useGetSecretApprovalRequestCount({ workspaceId });
const { data: accessApprovalRequestCount } = useGetAccessRequestsCount({ projectSlug });
const pendingRequestsCount = useMemo(() => {
return (secretApprovalReqCount?.open || 0) + (accessApprovalRequestCount?.pendingCount || 0);
}, [secretApprovalReqCount, accessApprovalRequestCount]);
const infisicalPlatformVersion = process.env.NEXT_PUBLIC_INFISICAL_PLATFORM_VERSION; const infisicalPlatformVersion = process.env.NEXT_PUBLIC_INFISICAL_PLATFORM_VERSION;
@@ -152,41 +138,6 @@ export const AppLayout = ({ children }: LayoutProps) => {
if (tempLocalStorage("orgData.id") === "" && orgs?.[0]?.id) { if (tempLocalStorage("orgData.id") === "" && orgs?.[0]?.id) {
localStorage.setItem("orgData.id", orgs?.[0]?.id); localStorage.setItem("orgData.id", orgs?.[0]?.id);
} }
if (
currentOrg &&
((workspaces?.length === 0 && router.asPath.includes("project")) ||
router.asPath.includes("/project/undefined") ||
(!orgs?.map((org) => org.id)?.includes(router.query.id as string) &&
!router.asPath.includes("project") &&
!router.asPath.includes("personal") &&
!router.asPath.includes("secret-scanning") &&
!router.asPath.includes("integration")))
) {
router.push(`/org/${currentOrg?.id}/secret-manager/overview`);
}
// else if (!router.asPath.includes("org") && !router.asPath.includes("project") && !router.asPath.includes("integrations") && !router.asPath.includes("personal-settings")) {
// const pathSegments = router.asPath.split("/").filter((segment) => segment.length > 0);
// let intendedWorkspaceId;
// if (pathSegments.length >= 2 && pathSegments[0] === "dashboard") {
// [, intendedWorkspaceId] = pathSegments;
// } else if (pathSegments.length >= 3 && pathSegments[0] === "settings") {
// [, , intendedWorkspaceId] = pathSegments;
// } else {
// const lastPathSegments = router.asPath.split("/").pop();
// if (lastPathSegments !== undefined) {
// [intendedWorkspaceId] = lastPathSegments.split("?");
// }
// }
// if (!intendedWorkspaceId) return;
// if (!["callback", "create", "authorize"].includes(intendedWorkspaceId)) {
// localStorage.setItem("projectData.id", intendedWorkspaceId);
// }
// }
}; };
putUserInOrg(); putUserInOrg();
}, [router.query.id]); }, [router.query.id]);
@@ -214,8 +165,7 @@ export const AppLayout = ({ children }: LayoutProps) => {
<div> <div>
{!router.asPath.includes("personal") && ( {!router.asPath.includes("personal") && (
<div className="flex h-12 cursor-default items-center px-3 pt-6"> <div className="flex h-12 cursor-default items-center px-3 pt-6">
{(router.asPath.includes("project") || {(currentWorkspace || router.asPath.includes("integrations")) && (
router.asPath.includes("integrations")) && (
<Link href={`/org/${currentOrg?.id}/${currentWorkspace?.type}/overview`}> <Link href={`/org/${currentOrg?.id}/${currentWorkspace?.type}/overview`}>
<div className="pl-1 pr-2 text-mineshaft-400 duration-200 hover:text-mineshaft-100"> <div className="pl-1 pr-2 text-mineshaft-400 duration-200 hover:text-mineshaft-100">
<FontAwesomeIcon icon={faArrowLeft} /> <FontAwesomeIcon icon={faArrowLeft} />
@@ -387,111 +337,8 @@ export const AppLayout = ({ children }: LayoutProps) => {
</Link> </Link>
))} ))}
<div className={`px-1 ${!router.asPath.includes("personal") ? "block" : "hidden"}`}> <div className={`px-1 ${!router.asPath.includes("personal") ? "block" : "hidden"}`}>
{(router.asPath.includes("project") || router.asPath.includes("integrations")) && <ProjectSidebarItem />
currentWorkspace ? ( {router.pathname.startsWith("/org") && (
<Menu>
<Link href={`/project/${currentWorkspace?.id}/secrets/overview`} passHref>
<a>
<MenuItem
isSelected={router.asPath.includes(
`/project/${currentWorkspace?.id}/secrets`
)}
icon="system-outline-90-lock-closed"
>
{t("nav.menu.secrets")}
</MenuItem>
</a>
</Link>
<Link href={`/project/${currentWorkspace?.id}/certificates`} passHref>
<a>
<MenuItem
isSelected={
router.asPath === `/project/${currentWorkspace?.id}/certificates`
}
icon="system-outline-90-lock-closed"
>
Internal PKI
</MenuItem>
</a>
</Link>
<Link href={`/project/${currentWorkspace?.id}/kms`} passHref>
<a>
<MenuItem
isSelected={router.asPath === `/project/${currentWorkspace?.id}/kms`}
icon="system-outline-90-lock-closed"
>
Key Management
</MenuItem>
</a>
</Link>
<Link href={`/project/${currentWorkspace?.id}/members`} passHref>
<a>
<MenuItem
isSelected={
router.asPath === `/project/${currentWorkspace?.id}/members`
}
icon="system-outline-96-groups"
>
Access Control
</MenuItem>
</a>
</Link>
<Link href={`/integrations/${currentWorkspace?.id}`} passHref>
<a>
<MenuItem
isSelected={router.asPath.includes("/integrations")}
icon="system-outline-82-extension"
>
{t("nav.menu.integrations")}
</MenuItem>
</a>
</Link>
<Link href={`/project/${currentWorkspace?.id}/secret-rotation`} passHref>
<a className="relative">
<MenuItem
isSelected={
router.asPath === `/project/${currentWorkspace?.id}/secret-rotation`
}
icon="rotation"
>
Secret Rotation
</MenuItem>
</a>
</Link>
<Link href={`/project/${currentWorkspace?.id}/approval`} passHref>
<a className="relative">
<MenuItem
isSelected={
router.asPath === `/project/${currentWorkspace?.id}/approval`
}
icon="system-outline-189-domain-verification"
>
Approvals
{Boolean(
secretApprovalReqCount?.open ||
accessApprovalRequestCount?.pendingCount
) && (
<span className="ml-2 rounded border border-primary-400 bg-primary-600 py-0.5 px-1 text-xs font-semibold text-black">
{pendingRequestsCount}
</span>
)}
</MenuItem>
</a>
</Link>
<Link href={`/project/${currentWorkspace?.id}/settings`} passHref>
<a>
<MenuItem
isSelected={
router.asPath === `/project/${currentWorkspace?.id}/settings`
}
icon="system-outline-109-slider-toggle-settings"
>
{t("nav.menu.project-settings")}
</MenuItem>
</a>
</Link>
</Menu>
) : (
<Menu className="mt-4"> <Menu className="mt-4">
<Link href={`/org/${currentOrg?.id}/secret-manager/overview`} passHref> <Link href={`/org/${currentOrg?.id}/secret-manager/overview`} passHref>
<a> <a>
@@ -16,6 +16,7 @@ import {
useSubscription, useSubscription,
useWorkspace useWorkspace
} from "@app/context"; } from "@app/context";
import { getWorkspaceHomePage } from "@app/helpers/workspace";
import { usePopUp } from "@app/hooks"; import { usePopUp } from "@app/hooks";
import { useUpdateUserProjectFavorites } from "@app/hooks/api/users/mutation"; import { useUpdateUserProjectFavorites } from "@app/hooks/api/users/mutation";
import { useGetUserProjectFavorites } from "@app/hooks/api/users/queries"; import { useGetUserProjectFavorites } from "@app/hooks/api/users/queries";
@@ -190,7 +191,7 @@ export const ProjectSelect = () => {
// todo(akhi): this is not using react query because react query in overview is throwing error when envs are not exact same count // todo(akhi): this is not using react query because react query in overview is throwing error when envs are not exact same count
// to reproduce change this back to router.push and switch between two projects with different env count // to reproduce change this back to router.push and switch between two projects with different env count
// look into this on dashboard revamp // look into this on dashboard revamp
window.location.assign(`/project/${project.id}/secrets/overview`); window.location.assign(getWorkspaceHomePage(project));
}} }}
options={options} options={options}
components={{ components={{
@@ -0,0 +1,158 @@
import { useTranslation } from "react-i18next";
import Link from "next/link";
import { useRouter } from "next/router";
import { Menu, MenuItem } from "@app/components/v2";
import { useWorkspace } from "@app/context";
import { useGetAccessRequestsCount, useGetSecretApprovalRequestCount } from "@app/hooks/api";
import { ProjectType } from "@app/hooks/api/workspace/types";
export const ProjectSidebarItem = () => {
const { currentWorkspace } = useWorkspace();
const router = useRouter();
const { t } = useTranslation();
const workspaceId = currentWorkspace?.id || "";
const projectSlug = currentWorkspace?.slug || "";
const { data: secretApprovalReqCount } = useGetSecretApprovalRequestCount({ workspaceId });
const { data: accessApprovalRequestCount } = useGetAccessRequestsCount({ projectSlug });
const pendingRequestsCount =
(secretApprovalReqCount?.open || 0) + (accessApprovalRequestCount?.pendingCount || 0);
if (
!currentWorkspace ||
router.asPath.startsWith("personal") ||
router.asPath.startsWith("integrations")
) {
return <div />;
}
const isSecretManager = currentWorkspace?.type === ProjectType.SecretManager;
const isCertManager = currentWorkspace?.type === ProjectType.CertificateManager;
const isCmek = currentWorkspace?.type === ProjectType.Cmek;
return (
<Menu>
{isSecretManager && (
<Link
href={`/${ProjectType.SecretManager}/${currentWorkspace?.id}/secrets/overview`}
passHref
>
<a>
<MenuItem
isSelected={router.asPath.includes(
`/${ProjectType.SecretManager}/${currentWorkspace?.id}/secrets`
)}
icon="system-outline-90-lock-closed"
>
{t("nav.menu.secrets")}
</MenuItem>
</a>
</Link>
)}
{isCertManager && (
<Link
href={`/${ProjectType.CertificateManager}/${currentWorkspace?.id}/certificates`}
passHref
>
<a>
<MenuItem
isSelected={
router.asPath ===
`/${ProjectType.CertificateManager}/${currentWorkspace?.id}/certificates`
}
icon="system-outline-90-lock-closed"
>
Internal PKI
</MenuItem>
</a>
</Link>
)}
{isCmek && (
<Link href={`/${ProjectType.Cmek}/${currentWorkspace?.id}/kms`} passHref>
<a>
<MenuItem
isSelected={router.asPath === `/${ProjectType.Cmek}/${currentWorkspace?.id}/kms`}
icon="system-outline-90-lock-closed"
>
Key Management
</MenuItem>
</a>
</Link>
)}
<Link href={`/${currentWorkspace.type}/${currentWorkspace?.id}/members`} passHref>
<a>
<MenuItem
isSelected={router.asPath.endsWith(`/${currentWorkspace?.id}/members`)}
icon="system-outline-96-groups"
>
Access Control
</MenuItem>
</a>
</Link>
{isSecretManager && (
<Link href={`/integrations/${currentWorkspace?.id}`} passHref>
<a>
<MenuItem
isSelected={router.asPath.includes("/integrations")}
icon="system-outline-82-extension"
>
{t("nav.menu.integrations")}
</MenuItem>
</a>
</Link>
)}
{isSecretManager && (
<Link
href={`/${ProjectType.SecretManager}/${currentWorkspace?.id}/secret-rotation`}
passHref
>
<a className="relative">
<MenuItem
isSelected={
router.asPath ===
`/${ProjectType.SecretManager}/${currentWorkspace?.id}/secret-rotation`
}
icon="rotation"
>
Secret Rotation
</MenuItem>
</a>
</Link>
)}
{isSecretManager && (
<Link href={`/secret-manager/${currentWorkspace?.id}/approval`} passHref>
<a className="relative">
<MenuItem
isSelected={
router.asPath === `/${ProjectType.SecretManager}/${currentWorkspace?.id}/approval`
}
icon="system-outline-189-domain-verification"
>
Approvals
{Boolean(
secretApprovalReqCount?.open || accessApprovalRequestCount?.pendingCount
) && (
<span className="ml-2 rounded border border-primary-400 bg-primary-600 py-0.5 px-1 text-xs font-semibold text-black">
{pendingRequestsCount}
</span>
)}
</MenuItem>
</a>
</Link>
)}
<Link href={`/${currentWorkspace.type}/${currentWorkspace?.id}/settings`} passHref>
<a>
<MenuItem
isSelected={router.asPath.endsWith(`/${currentWorkspace?.id}/settings`)}
icon="system-outline-109-slider-toggle-settings"
>
{t("nav.menu.project-settings")}
</MenuItem>
</a>
</Link>
</Menu>
);
};
@@ -0,0 +1 @@
export { ProjectSidebarItem } from "./ProjectSidebarItems";
@@ -0,0 +1,21 @@
import { useTranslation } from "react-i18next";
import Head from "next/head";
import { IPAllowlistPage } from "@app/views/Project/IPAllowListPage";
const ProjectAllowlist = () => {
const { t } = useTranslation();
return (
<>
<Head>
<title>{t("common.head-title", { title: t("settings.project.title") })}</title>
<link rel="icon" href="/infisical.ico" />
</Head>
<IPAllowlistPage />
</>
);
};
export default ProjectAllowlist;
ProjectAllowlist.requireAuth = true;
@@ -0,0 +1,20 @@
import { useTranslation } from "react-i18next";
import Head from "next/head";
import { IdentityDetailsPage } from "@app/views/Project/IdentityDetailsPage";
export default function ProjectIdentityDetailsPage() {
const { t } = useTranslation();
return (
<>
<Head>
<title>{t("common.head-title", { title: t("settings.members.title") })}</title>
<link rel="icon" href="/infisical.ico" />
</Head>
<IdentityDetailsPage />
</>
);
}
ProjectIdentityDetailsPage.requireAuth = true;
@@ -0,0 +1,20 @@
import { useTranslation } from "react-i18next";
import Head from "next/head";
import { MemberDetailsPage } from "@app/views/Project/MemberDetailsPage";
export default function Page() {
const { t } = useTranslation();
return (
<>
<Head>
<title>{t("common.head-title", { title: t("settings.members.title") })}</title>
<link rel="icon" href="/infisical.ico" />
</Head>
<MemberDetailsPage />
</>
);
}
Page.requireAuth = true;
@@ -0,0 +1,21 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import { useTranslation } from "react-i18next";
import Head from "next/head";
import { MembersPage } from "@app/views/Project/MembersPage";
export default function WorkspaceMemberSettings() {
const { t } = useTranslation();
return (
<>
<Head>
<title>{t("common.head-title", { title: t("settings.members.title") })}</title>
<link rel="icon" href="/infisical.ico" />
</Head>
<MembersPage />
</>
);
}
WorkspaceMemberSettings.requireAuth = true;
@@ -0,0 +1,20 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import { useTranslation } from "react-i18next";
import Head from "next/head";
import { RolePage } from "@app/views/Project/RolePage";
export default function Role() {
const { t } = useTranslation();
return (
<>
<Head>
<title>{t("common.head-title", { title: "Project Settings" })}</title>
<link rel="icon" href="/infisical.ico" />
</Head>
<RolePage />
</>
);
}
Role.requireAuth = true;
@@ -0,0 +1,22 @@
import { useTranslation } from "react-i18next";
import Head from "next/head";
import { ProjectSettingsPage } from "@app/views/Settings/ProjectSettingsPage";
const ProjectSettings = () => {
const { t } = useTranslation();
return (
<>
<Head>
<title>{t("common.head-title", { title: t("settings.project.title") })}</title>
<link rel="icon" href="/infisical.ico" />
</Head>
<ProjectSettingsPage />
</>
);
};
export default ProjectSettings;
ProjectSettings.requireAuth = true;
@@ -1,4 +1,5 @@
import { ProjectType } from "@app/hooks/api/workspace/types"; import { ProjectType } from "@app/hooks/api/workspace/types";
import { ProductOverview } from "../secret-manager/overview"; import { ProductOverview } from "../secret-manager/overview";
const CertManagerOverviewPage = () => <ProductOverview type={ProjectType.CertificateManager} />; const CertManagerOverviewPage = () => <ProductOverview type={ProjectType.CertificateManager} />;
@@ -1,4 +1,5 @@
import { ProjectType } from "@app/hooks/api/workspace/types"; import { ProjectType } from "@app/hooks/api/workspace/types";
import { ProductOverview } from "../secret-manager/overview"; import { ProductOverview } from "../secret-manager/overview";
const CmekManagerOverviewPage = () => <ProductOverview type={ProjectType.Cmek} />; const CmekManagerOverviewPage = () => <ProductOverview type={ProjectType.Cmek} />;
@@ -1,6 +1,7 @@
import { useOrganization } from "@app/context";
import { useRouter } from "next/router";
import { useEffect } from "react"; import { useEffect } from "react";
import { useRouter } from "next/router";
import { useOrganization } from "@app/context";
// #TODO: Update all the workspaceIds // #TODO: Update all the workspaceIds
const OrganizationPage = () => { const OrganizationPage = () => {
@@ -51,6 +51,7 @@ import {
useSubscription, useSubscription,
useUser useUser
} from "@app/context"; } from "@app/context";
import { getWorkspaceHomePage } from "@app/helpers/workspace";
import { usePagination, useResetPageHelper } from "@app/hooks"; import { usePagination, useResetPageHelper } from "@app/hooks";
import { useGetUserWorkspaces, useRegisterUserAction } from "@app/hooks/api"; import { useGetUserWorkspaces, useRegisterUserAction } from "@app/hooks/api";
import { OrderByDirection } from "@app/hooks/api/generic/types"; import { OrderByDirection } from "@app/hooks/api/generic/types";
@@ -59,8 +60,8 @@ import { useFetchServerStatus } from "@app/hooks/api/serverDetails";
import { Workspace } from "@app/hooks/api/types"; import { Workspace } from "@app/hooks/api/types";
import { useUpdateUserProjectFavorites } from "@app/hooks/api/users/mutation"; import { useUpdateUserProjectFavorites } from "@app/hooks/api/users/mutation";
import { useGetUserProjectFavorites } from "@app/hooks/api/users/queries"; import { useGetUserProjectFavorites } from "@app/hooks/api/users/queries";
import { usePopUp } from "@app/hooks/usePopUp";
import { ProjectType } from "@app/hooks/api/workspace/types"; import { ProjectType } from "@app/hooks/api/workspace/types";
import { usePopUp } from "@app/hooks/usePopUp";
const features = [ const features = [
{ {
@@ -603,7 +604,7 @@ export const ProductOverview = ({ type }: Props) => {
// eslint-disable-next-line jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events // eslint-disable-next-line jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events
<div <div
onClick={() => { onClick={() => {
router.push(`/project/${workspace.id}/secrets/overview`); router.push(getWorkspaceHomePage(workspace));
localStorage.setItem("projectData.id", workspace.id); localStorage.setItem("projectData.id", workspace.id);
}} }}
key={workspace.id} key={workspace.id}
@@ -667,7 +668,7 @@ export const ProductOverview = ({ type }: Props) => {
// eslint-disable-next-line jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events // eslint-disable-next-line jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events
<div <div
onClick={() => { onClick={() => {
router.push(`/project/${workspace.id}/secrets/overview`); router.push(getWorkspaceHomePage(workspace));
localStorage.setItem("projectData.id", workspace.id); localStorage.setItem("projectData.id", workspace.id);
}} }}
key={workspace.id} key={workspace.id}
@@ -1047,7 +1048,6 @@ export const ProductOverview = ({ type }: Props) => {
onOpenChange={(isOpen) => handlePopUpToggle("upgradePlan", isOpen)} onOpenChange={(isOpen) => handlePopUpToggle("upgradePlan", isOpen)}
text="You have exceeded the number of projects allowed on the free plan." text="You have exceeded the number of projects allowed on the free plan."
/> />
{/* <DeleteUserDialog isOpen={isDeleteOpen} closeModal={closeDeleteModal} submitModal={deleteMembership} userIdToBeDeleted={userIdToBeDeleted}/> */}
</div> </div>
); );
}; };
@@ -0,0 +1,21 @@
import { useTranslation } from "react-i18next";
import Head from "next/head";
import { IPAllowlistPage } from "@app/views/Project/IPAllowListPage";
const ProjectAllowlist = () => {
const { t } = useTranslation();
return (
<>
<Head>
<title>{t("common.head-title", { title: t("settings.project.title") })}</title>
<link rel="icon" href="/infisical.ico" />
</Head>
<IPAllowlistPage />
</>
);
};
export default ProjectAllowlist;
ProjectAllowlist.requireAuth = true;
@@ -0,0 +1,20 @@
import { useTranslation } from "react-i18next";
import Head from "next/head";
import { IdentityDetailsPage } from "@app/views/Project/IdentityDetailsPage";
export default function ProjectIdentityDetailsPage() {
const { t } = useTranslation();
return (
<>
<Head>
<title>{t("common.head-title", { title: t("settings.members.title") })}</title>
<link rel="icon" href="/infisical.ico" />
</Head>
<IdentityDetailsPage />
</>
);
}
ProjectIdentityDetailsPage.requireAuth = true;
@@ -0,0 +1,20 @@
import { useTranslation } from "react-i18next";
import Head from "next/head";
import { MemberDetailsPage } from "@app/views/Project/MemberDetailsPage";
export default function Page() {
const { t } = useTranslation();
return (
<>
<Head>
<title>{t("common.head-title", { title: t("settings.members.title") })}</title>
<link rel="icon" href="/infisical.ico" />
</Head>
<MemberDetailsPage />
</>
);
}
Page.requireAuth = true;
@@ -0,0 +1,21 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import { useTranslation } from "react-i18next";
import Head from "next/head";
import { MembersPage } from "@app/views/Project/MembersPage";
export default function WorkspaceMemberSettings() {
const { t } = useTranslation();
return (
<>
<Head>
<title>{t("common.head-title", { title: t("settings.members.title") })}</title>
<link rel="icon" href="/infisical.ico" />
</Head>
<MembersPage />
</>
);
}
WorkspaceMemberSettings.requireAuth = true;
@@ -0,0 +1,20 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import { useTranslation } from "react-i18next";
import Head from "next/head";
import { RolePage } from "@app/views/Project/RolePage";
export default function Role() {
const { t } = useTranslation();
return (
<>
<Head>
<title>{t("common.head-title", { title: "Project Settings" })}</title>
<link rel="icon" href="/infisical.ico" />
</Head>
<RolePage />
</>
);
}
Role.requireAuth = true;
@@ -0,0 +1,22 @@
import { useTranslation } from "react-i18next";
import Head from "next/head";
import { ProjectSettingsPage } from "@app/views/Settings/ProjectSettingsPage";
const ProjectSettings = () => {
const { t } = useTranslation();
return (
<>
<Head>
<title>{t("common.head-title", { title: t("settings.project.title") })}</title>
<link rel="icon" href="/infisical.ico" />
</Head>
<ProjectSettingsPage />
</>
);
};
export default ProjectSettings;
ProjectSettings.requireAuth = true;
+3 -2
View File
@@ -16,6 +16,7 @@ import { useServerConfig } from "@app/context";
import { useVerifySignupEmailVerificationCode } from "@app/hooks/api"; import { useVerifySignupEmailVerificationCode } from "@app/hooks/api";
import { fetchOrganizations } from "@app/hooks/api/organization/queries"; import { fetchOrganizations } from "@app/hooks/api/organization/queries";
import { useFetchServerStatus } from "@app/hooks/api/serverDetails"; import { useFetchServerStatus } from "@app/hooks/api/serverDetails";
import { ProjectType } from "@app/hooks/api/workspace/types";
/** /**
* @returns the signup page * @returns the signup page
@@ -47,7 +48,7 @@ export default function SignUp() {
const tryAuth = async () => { const tryAuth = async () => {
try { try {
const userOrgs = await fetchOrganizations(); const userOrgs = await fetchOrganizations();
router.push(`/org/${userOrgs[0].id}/overview`); router.push(`/org/${userOrgs[0].id}/${ProjectType.SecretManager}/overview`);
} catch (error) { } catch (error) {
console.log("Error - Not logged in yet"); console.log("Error - Not logged in yet");
} }
@@ -90,7 +91,7 @@ export default function SignUp() {
if (!serverDetails?.emailConfigured && step === 5) { if (!serverDetails?.emailConfigured && step === 5) {
const userOrgs = await fetchOrganizations(); const userOrgs = await fetchOrganizations();
router.push(`/org/${userOrgs[0].id}/overview`); router.push(`/org/${userOrgs[0].id}/${ProjectType.SecretManager}/overview`);
} }
})(); })();
}, [step]); }, [step]);
+2 -1
View File
@@ -31,6 +31,7 @@ import {
} from "@app/hooks/api/auth/queries"; } from "@app/hooks/api/auth/queries";
import { MfaMethod } from "@app/hooks/api/auth/types"; import { MfaMethod } from "@app/hooks/api/auth/types";
import { fetchOrganizations } from "@app/hooks/api/organization/queries"; import { fetchOrganizations } from "@app/hooks/api/organization/queries";
import { ProjectType } from "@app/hooks/api/workspace/types";
import { navigateUserToOrg } from "@app/views/Login/Login.utils"; import { navigateUserToOrg } from "@app/views/Login/Login.utils";
import { Mfa } from "@app/views/Login/Mfa"; import { Mfa } from "@app/views/Login/Mfa";
@@ -386,7 +387,7 @@ export default function SignupInvite() {
setBackupKeyError, setBackupKeyError,
setBackupKeyIssued setBackupKeyIssued
}); });
router.push(`/org/${organizationId}/overview`); router.push(`/org/${organizationId}/${ProjectType.SecretManager}/overview`);
}} }}
size="lg" size="lg"
/> />
+2 -1
View File
@@ -3,6 +3,7 @@ import { NextRouter, useRouter } from "next/router";
import { useServerConfig } from "@app/context"; import { useServerConfig } from "@app/context";
import { fetchOrganizations } from "@app/hooks/api/organization/queries"; import { fetchOrganizations } from "@app/hooks/api/organization/queries";
import { userKeys } from "@app/hooks/api/users"; import { userKeys } from "@app/hooks/api/users";
import { ProjectType } from "@app/hooks/api/workspace/types";
import { queryClient } from "@app/reactQuery"; import { queryClient } from "@app/reactQuery";
export const navigateUserToOrg = async (router: NextRouter, organizationId?: string) => { export const navigateUserToOrg = async (router: NextRouter, organizationId?: string) => {
@@ -20,7 +21,7 @@ export const navigateUserToOrg = async (router: NextRouter, organizationId?: str
// user is part of at least 1 non-auth enforced org // user is part of at least 1 non-auth enforced org
const userOrg = nonAuthEnforcedOrgs[0] && nonAuthEnforcedOrgs[0].id; const userOrg = nonAuthEnforcedOrgs[0] && nonAuthEnforcedOrgs[0].id;
localStorage.setItem("orgData.id", userOrg); localStorage.setItem("orgData.id", userOrg);
router.push(`/org/${userOrg}/overview`); router.push(`/org/${userOrg}/${ProjectType.SecretManager}/overview`);
} else { } else {
// user is not part of any non-auth enforced orgs // user is not part of any non-auth enforced orgs
localStorage.removeItem("orgData.id"); localStorage.removeItem("orgData.id");
@@ -33,7 +33,7 @@ export const IdentityProjectRow = ({
membership: { id, createdAt, identity, project, roles }, membership: { id, createdAt, identity, project, roles },
handlePopUpOpen handlePopUpOpen
}: Props) => { }: Props) => {
const { workspaces } = useWorkspace(); const { workspaces,currentWorkspace } = useWorkspace();
const router = useRouter(); const router = useRouter();
const isAccessible = useMemo(() => { const isAccessible = useMemo(() => {
@@ -52,7 +52,7 @@ export const IdentityProjectRow = ({
key={`identity-project-membership-${id}`} key={`identity-project-membership-${id}`}
onClick={() => { onClick={() => {
if (isAccessible) { if (isAccessible) {
router.push(`/project/${project.id}/members?selectedTab=${TabSections.Identities}`); router.push(`/${currentWorkspace?.type}/${project.id}/members?selectedTab=${TabSections.Identities}`);
return; return;
} }
@@ -7,6 +7,7 @@ import z from "zod";
import { createNotification } from "@app/components/notifications"; import { createNotification } from "@app/components/notifications";
import { Button, FormControl, Input, Modal, ModalContent } from "@app/components/v2"; import { Button, FormControl, Input, Modal, ModalContent } from "@app/components/v2";
import { useCreateOrg, useSelectOrganization } from "@app/hooks/api"; import { useCreateOrg, useSelectOrganization } from "@app/hooks/api";
import { ProjectType } from "@app/hooks/api/workspace/types";
const schema = z const schema = z
.object({ .object({
@@ -57,8 +58,8 @@ export const CreateOrgModal: FC<CreateOrgModalProps> = ({ isOpen, onClose }) =>
type: "success" type: "success"
}); });
if (router.isReady) router.push(`/org/${organization.id}/overview`); if (router.isReady) router.push(`/org/${organization.id}/${ProjectType.SecretManager}/overview`);
else window.location.href = `/org/${organization.id}/overview`; else window.location.href = `/org/${organization.id}/${ProjectType.SecretManager}/overview`;
localStorage.setItem("orgData.id", organization.id); localStorage.setItem("orgData.id", organization.id);
@@ -52,16 +52,13 @@ export const OrgAdminProjects = withPermission(
const projectCount = data?.count || 0; const projectCount = data?.count || 0;
const isEmpty = !isProjectsLoading && projects.length === 0; const isEmpty = !isProjectsLoading && projects.length === 0;
const handleAccessProject = async (projectId: string) => { const handleAccessProject = async (type:string,projectId: string) => {
try { try {
await orgAdminAccessProject.mutateAsync({ await orgAdminAccessProject.mutateAsync({
projectId projectId
}); });
await router.push({ await router.push({
pathname: "/project/[projectId]/secrets/overview", pathname: `/${type}/${projectId}/secrets/overview`,
query: {
projectId
}
}); });
} catch { } catch {
createNotification({ createNotification({
@@ -103,7 +100,7 @@ export const OrgAdminProjects = withPermission(
<TBody> <TBody>
{isProjectsLoading && <TableSkeleton columns={4} innerKey="projects" />} {isProjectsLoading && <TableSkeleton columns={4} innerKey="projects" />}
{!isProjectsLoading && {!isProjectsLoading &&
projects?.map(({ name, slug, createdAt, id }) => ( projects?.map(({ name, slug, createdAt,type, id }) => (
<Tr key={`project-${id}`} className="group w-full"> <Tr key={`project-${id}`} className="group w-full">
<Td>{name}</Td> <Td>{name}</Td>
<Td>{slug}</Td> <Td>{slug}</Td>
@@ -124,7 +121,7 @@ export const OrgAdminProjects = withPermission(
onClick={(e) => { onClick={(e) => {
e.stopPropagation(); e.stopPropagation();
e.preventDefault(); e.preventDefault();
handleAccessProject(id); handleAccessProject(type,id);
}} }}
icon={<FontAwesomeIcon icon={faSignIn} />} icon={<FontAwesomeIcon icon={faSignIn} />}
disabled={ disabled={
+3 -2
View File
@@ -18,6 +18,7 @@ import {
import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context"; import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context";
import { withProjectPermission } from "@app/hoc"; import { withProjectPermission } from "@app/hoc";
import { useDeleteCa, useGetCaById } from "@app/hooks/api"; import { useDeleteCa, useGetCaById } from "@app/hooks/api";
import { ProjectType } from "@app/hooks/api/workspace/types";
import { usePopUp } from "@app/hooks/usePopUp"; import { usePopUp } from "@app/hooks/usePopUp";
import { CaModal } from "@app/views/Project/CertificatesPage/components/CaTab/components/CaModal"; import { CaModal } from "@app/views/Project/CertificatesPage/components/CaTab/components/CaModal";
@@ -60,7 +61,7 @@ export const CaPage = withProjectPermission(
}); });
handlePopUpClose("deleteCa"); handlePopUpClose("deleteCa");
router.push(`/project/${projectId}/certificates`); router.push(`/${ProjectType.CertificateManager}/${projectId}/certificates`);
} catch (err) { } catch (err) {
console.error(err); console.error(err);
createNotification({ createNotification({
@@ -78,7 +79,7 @@ export const CaPage = withProjectPermission(
variant="link" variant="link"
type="submit" type="submit"
leftIcon={<FontAwesomeIcon icon={faChevronLeft} />} leftIcon={<FontAwesomeIcon icon={faChevronLeft} />}
onClick={() => router.push(`/project/${projectId}/certificates`)} onClick={() => router.push(`/${ProjectType.CertificateManager}/${projectId}/certificates`)}
className="mb-4" className="mb-4"
> >
Certificate Authorities Certificate Authorities
@@ -34,6 +34,7 @@ import {
caTypeToNameMap, caTypeToNameMap,
getCaStatusBadgeVariant getCaStatusBadgeVariant
} from "@app/hooks/api/ca/constants"; } from "@app/hooks/api/ca/constants";
import { ProjectType } from "@app/hooks/api/workspace/types";
import { UsePopUpState } from "@app/hooks/usePopUp"; import { UsePopUpState } from "@app/hooks/usePopUp";
type Props = { type Props = {
@@ -80,7 +81,7 @@ export const CaTable = ({ handlePopUpOpen }: Props) => {
<Tr <Tr
className="h-10 cursor-pointer transition-colors duration-100 hover:bg-mineshaft-700" className="h-10 cursor-pointer transition-colors duration-100 hover:bg-mineshaft-700"
key={`ca-${ca.id}`} key={`ca-${ca.id}`}
onClick={() => router.push(`/project/${currentWorkspace?.id}/ca/${ca.id}`)} onClick={() => router.push(`/${ProjectType.CertificateManager}/${currentWorkspace?.id}/ca/${ca.id}`)}
> >
<Td>{ca.friendlyName}</Td> <Td>{ca.friendlyName}</Td>
<Td> <Td>
@@ -12,6 +12,7 @@ import {
useGetPkiCollectionById, useGetPkiCollectionById,
useUpdatePkiCollection useUpdatePkiCollection
} from "@app/hooks/api"; } from "@app/hooks/api";
import { ProjectType } from "@app/hooks/api/workspace/types";
import { UsePopUpState } from "@app/hooks/usePopUp"; import { UsePopUpState } from "@app/hooks/usePopUp";
const schema = z.object({ const schema = z.object({
@@ -81,7 +82,7 @@ export const PkiCollectionModal = ({ popUp, handlePopUpToggle }: Props) => {
projectId projectId
}); });
router.push(`/project/${projectId}/pki-collections/${createdId}`); router.push(`/${ProjectType.CertificateManager}/${projectId}/pki-collections/${createdId}`);
} }
handlePopUpToggle("pkiCollection", false); handlePopUpToggle("pkiCollection", false);
@@ -21,6 +21,7 @@ import {
} from "@app/components/v2"; } from "@app/components/v2";
import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context"; import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context";
import { useListWorkspacePkiCollections } from "@app/hooks/api"; import { useListWorkspacePkiCollections } from "@app/hooks/api";
import { ProjectType } from "@app/hooks/api/workspace/types";
import { UsePopUpState } from "@app/hooks/usePopUp"; import { UsePopUpState } from "@app/hooks/usePopUp";
type Props = { type Props = {
@@ -59,7 +60,7 @@ export const PkiCollectionTable = ({ handlePopUpOpen }: Props) => {
className="h-10 cursor-pointer transition-colors duration-100 hover:bg-mineshaft-700" className="h-10 cursor-pointer transition-colors duration-100 hover:bg-mineshaft-700"
key={`pki-collection-${pkiCollection.id}`} key={`pki-collection-${pkiCollection.id}`}
onClick={() => onClick={() =>
router.push(`/project/${projectId}/pki-collections/${pkiCollection.id}`) router.push(`/${ProjectType.CertificateManager}/${projectId}/pki-collections/${pkiCollection.id}`)
} }
> >
<Td>{pkiCollection.name}</Td> <Td>{pkiCollection.name}</Td>
@@ -48,7 +48,7 @@ export const IdentityDetailsPage = withProjectPermission(
type: "success" type: "success"
}); });
handlePopUpClose("deleteIdentity"); handlePopUpClose("deleteIdentity");
router.push(`/project/${workspaceId}/members?selectedTab=identities`); router.push(`/${currentWorkspace?.type}/${workspaceId}/members?selectedTab=identities`);
} catch (err) { } catch (err) {
console.error(err); console.error(err);
const error = err as any; const error = err as any;
@@ -77,7 +77,7 @@ export const IdentityDetailsPage = withProjectPermission(
type="submit" type="submit"
leftIcon={<FontAwesomeIcon icon={faChevronLeft} />} leftIcon={<FontAwesomeIcon icon={faChevronLeft} />}
onClick={() => { onClick={() => {
router.push(`/project/${workspaceId}/members?selectedTab=identities`); router.push(`/${currentWorkspace?.type}/${workspaceId}/members?selectedTab=identities`);
}} }}
className="mb-4" className="mb-4"
> >
@@ -58,7 +58,7 @@ export const MemberDetailsPage = withProjectPermission(
text: "Successfully removed user from project", text: "Successfully removed user from project",
type: "success" type: "success"
}); });
router.push(`/project/${currentWorkspace?.id}/members`); router.push(`/${currentWorkspace.type}/${currentWorkspace?.id}/members`);
} catch (error) { } catch (error) {
console.error(error); console.error(error);
createNotification({ createNotification({
@@ -85,7 +85,7 @@ export const MemberDetailsPage = withProjectPermission(
type="submit" type="submit"
leftIcon={<FontAwesomeIcon icon={faChevronLeft} />} leftIcon={<FontAwesomeIcon icon={faChevronLeft} />}
onClick={() => { onClick={() => {
router.push(`/project/${workspaceId}/members`); router.push(`/${currentWorkspace?.type}/${workspaceId}/members`);
}} }}
className="mb-4" className="mb-4"
> >
@@ -244,10 +244,10 @@ export const IdentityTab = withProjectPermission(
tabIndex={0} tabIndex={0}
onKeyDown={(evt) => { onKeyDown={(evt) => {
if (evt.key === "Enter") { if (evt.key === "Enter") {
router.push(`/project/${workspaceId}/identities/${id}`); router.push(`/${currentWorkspace?.type}/${workspaceId}/identities/${id}`);
} }
}} }}
onClick={() => router.push(`/project/${workspaceId}/identities/${id}`)} onClick={() => router.push(`/${currentWorkspace?.type}/${workspaceId}/identities/${id}`)}
> >
<Td>{name}</Td> <Td>{name}</Td>
@@ -212,10 +212,10 @@ export const MembersTable = ({ handlePopUpOpen }: Props) => {
tabIndex={0} tabIndex={0}
onKeyDown={(evt) => { onKeyDown={(evt) => {
if (evt.key === "Enter") { if (evt.key === "Enter") {
router.push(`/project/${workspaceId}/members/${membershipId}`); router.push(`/${currentWorkspace?.type}/${workspaceId}/members/${membershipId}`);
} }
}} }}
onClick={() => router.push(`/project/${workspaceId}/members/${membershipId}`)} onClick={() => router.push(`/${currentWorkspace?.type}/${workspaceId}/members/${membershipId}`)}
> >
<Td>{name}</Td> <Td>{name}</Td>
<Td>{email}</Td> <Td>{email}</Td>
@@ -92,7 +92,7 @@ export const ProjectRoleList = () => {
<Tr <Tr
key={`role-list-${id}`} key={`role-list-${id}`}
className="h-10 cursor-pointer transition-colors duration-100 hover:bg-mineshaft-700" className="h-10 cursor-pointer transition-colors duration-100 hover:bg-mineshaft-700"
onClick={() => router.push(`/project/${projectId}/roles/${slug}`)} onClick={() => router.push(`/${currentWorkspace?.type}/${projectId}/roles/${slug}`)}
> >
<Td>{name}</Td> <Td>{name}</Td>
<Td>{slug}</Td> <Td>{slug}</Td>
@@ -115,7 +115,7 @@ export const ProjectRoleList = () => {
)} )}
onClick={(e) => { onClick={(e) => {
e.stopPropagation(); e.stopPropagation();
router.push(`/project/${projectId}/roles/${slug}`); router.push(`/${currentWorkspace?.type}/${projectId}/roles/${slug}`);
}} }}
disabled={!isAllowed} disabled={!isAllowed}
> >
@@ -19,6 +19,7 @@ import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@a
import { withProjectPermission } from "@app/hoc"; import { withProjectPermission } from "@app/hoc";
import { useDeletePkiCollection, useGetPkiCollectionById } from "@app/hooks/api"; import { useDeletePkiCollection, useGetPkiCollectionById } from "@app/hooks/api";
import { PkiItemType } from "@app/hooks/api/pkiCollections/constants"; import { PkiItemType } from "@app/hooks/api/pkiCollections/constants";
import { ProjectType } from "@app/hooks/api/workspace/types";
import { usePopUp } from "@app/hooks/usePopUp"; import { usePopUp } from "@app/hooks/usePopUp";
import { PkiCollectionModal } from "../CertificatesPage/components/PkiAlertsTab/components/PkiCollectionModal"; import { PkiCollectionModal } from "../CertificatesPage/components/PkiAlertsTab/components/PkiCollectionModal";
@@ -53,7 +54,7 @@ export const PkiCollectionPage = withProjectPermission(
type: "success" type: "success"
}); });
handlePopUpClose("deletePkiCollection"); handlePopUpClose("deletePkiCollection");
router.push(`/project/${projectId}/certificates`); router.push(`/${ProjectType.CertificateManager}/${projectId}/certificates`);
} catch (err) { } catch (err) {
console.error(err); console.error(err);
} }
@@ -68,7 +69,7 @@ export const PkiCollectionPage = withProjectPermission(
type="submit" type="submit"
leftIcon={<FontAwesomeIcon icon={faChevronLeft} />} leftIcon={<FontAwesomeIcon icon={faChevronLeft} />}
onClick={() => { onClick={() => {
router.push(`/project/${projectId}/certificates`); router.push(`/${ProjectType.CertificateManager}/${projectId}/certificates`);
}} }}
className="mb-4" className="mb-4"
> >
@@ -53,7 +53,7 @@ export const RolePage = withProjectPermission(
type: "success" type: "success"
}); });
handlePopUpClose("deleteRole"); handlePopUpClose("deleteRole");
router.push(`/project/${projectId}/members?selectedTab=${TabSections.Roles}`); router.push(`/${currentWorkspace?.type}/${projectId}/members?selectedTab=${TabSections.Roles}`);
} catch (err) { } catch (err) {
console.error(err); console.error(err);
const error = err as any; const error = err as any;
@@ -77,7 +77,7 @@ export const RolePage = withProjectPermission(
type="submit" type="submit"
leftIcon={<FontAwesomeIcon icon={faChevronLeft} />} leftIcon={<FontAwesomeIcon icon={faChevronLeft} />}
onClick={() => onClick={() =>
router.push(`/project/${projectId}/members?selectedTab=${TabSections.Roles}`) router.push(`/${currentWorkspace?.type}/${projectId}/members?selectedTab=${TabSections.Roles}`)
} }
className="mb-4" className="mb-4"
> >
@@ -99,7 +99,7 @@ export const RoleModal = ({ popUp, handlePopUpToggle }: Props) => {
permissions: [] permissions: []
}); });
router.push(`/project/${currentWorkspace?.id}/roles/${newRole.slug}`); router.push(`/${currentWorkspace?.type}/${currentWorkspace?.id}/roles/${newRole.slug}`);
handlePopUpToggle("role", false); handlePopUpToggle("role", false);
} }
@@ -35,6 +35,7 @@ import {
import { useGetProjectSecretsDetails } from "@app/hooks/api/dashboard"; import { useGetProjectSecretsDetails } from "@app/hooks/api/dashboard";
import { DashboardSecretsOrderBy } from "@app/hooks/api/dashboard/types"; import { DashboardSecretsOrderBy } from "@app/hooks/api/dashboard/types";
import { OrderByDirection } from "@app/hooks/api/generic/types"; import { OrderByDirection } from "@app/hooks/api/generic/types";
import { ProjectType } from "@app/hooks/api/workspace/types";
import { DynamicSecretListView } from "@app/views/SecretMainPage/components/DynamicSecretListView"; import { DynamicSecretListView } from "@app/views/SecretMainPage/components/DynamicSecretListView";
import { FolderListView } from "@app/views/SecretMainPage/components/FolderListView"; import { FolderListView } from "@app/views/SecretMainPage/components/FolderListView";
import { SecretImportListView } from "@app/views/SecretMainPage/components/SecretImportListView"; import { SecretImportListView } from "@app/views/SecretMainPage/components/SecretImportListView";
@@ -142,7 +143,7 @@ const SecretMainPageContent = () => {
!currentWorkspace?.environments.find((env) => env.slug === environment) && !currentWorkspace?.environments.find((env) => env.slug === environment) &&
router.isReady router.isReady
) { ) {
router.push(`/project/${workspaceId}/secrets/overview`); router.push(`/${ProjectType.SecretManager}/${workspaceId}/secrets/overview`);
createNotification({ createNotification({
text: "No environment found with given slug", text: "No environment found with given slug",
type: "error" type: "error"
@@ -68,7 +68,7 @@ import { OrderByDirection } from "@app/hooks/api/generic/types";
import { useUpdateFolderBatch } from "@app/hooks/api/secretFolders/queries"; import { useUpdateFolderBatch } from "@app/hooks/api/secretFolders/queries";
import { TUpdateFolderBatchDTO } from "@app/hooks/api/secretFolders/types"; import { TUpdateFolderBatchDTO } from "@app/hooks/api/secretFolders/types";
import { SecretType, SecretV3RawSanitized, TSecretFolder } from "@app/hooks/api/types"; import { SecretType, SecretV3RawSanitized, TSecretFolder } from "@app/hooks/api/types";
import { ProjectVersion } from "@app/hooks/api/workspace/types"; import { ProjectType, ProjectVersion } from "@app/hooks/api/workspace/types";
import { useDynamicSecretOverview, useFolderOverview, useSecretOverview } from "@app/hooks/utils"; import { useDynamicSecretOverview, useFolderOverview, useSecretOverview } from "@app/hooks/utils";
import { SecretOverviewDynamicSecretRow } from "@app/views/SecretOverviewPage/components/SecretOverviewDynamicSecretRow"; import { SecretOverviewDynamicSecretRow } from "@app/views/SecretOverviewPage/components/SecretOverviewDynamicSecretRow";
import { import {
@@ -170,7 +170,7 @@ export const SecretOverviewPage = () => {
useEffect(() => { useEffect(() => {
if (!isWorkspaceLoading && !workspaceId && router.isReady) { if (!isWorkspaceLoading && !workspaceId && router.isReady) {
router.push(`/org/${currentOrg?.id}/overview`); router.push(`/org/${currentOrg?.id}/${ProjectType.SecretManager}/overview`);
} }
}, [isWorkspaceLoading, workspaceId, router.isReady]); }, [isWorkspaceLoading, workspaceId, router.isReady]);
@@ -508,7 +508,7 @@ export const SecretOverviewPage = () => {
const envIndex = visibleEnvs.findIndex((el) => slug === el.slug); const envIndex = visibleEnvs.findIndex((el) => slug === el.slug);
if (envIndex !== -1) { if (envIndex !== -1) {
router.push({ router.push({
pathname: "/project/[id]/secrets/[env]", pathname: `/${ProjectType.SecretManager}/[id]/secrets/[env]`,
query query
}); });
} }
@@ -14,6 +14,7 @@ import {
} from "@app/context"; } from "@app/context";
import { useToggle } from "@app/hooks"; import { useToggle } from "@app/hooks";
import { useDeleteWorkspace, useGetWorkspaceUsers, useLeaveProject } from "@app/hooks/api"; import { useDeleteWorkspace, useGetWorkspaceUsers, useLeaveProject } from "@app/hooks/api";
import { ProjectType } from "@app/hooks/api/workspace/types";
import { usePopUp } from "@app/hooks/usePopUp"; import { usePopUp } from "@app/hooks/usePopUp";
export const DeleteProjectSection = () => { export const DeleteProjectSection = () => {
@@ -63,7 +64,7 @@ export const DeleteProjectSection = () => {
type: "success" type: "success"
}); });
router.push(`/org/${orgId}/overview`); router.push(`/org/${orgId}/${ProjectType.SecretManager}/overview`);
handlePopUpClose("deleteWorkspace"); handlePopUpClose("deleteWorkspace");
} catch (err) { } catch (err) {
console.error(err); console.error(err);
@@ -120,7 +121,7 @@ export const DeleteProjectSection = () => {
workspaceId: currentWorkspace.id workspaceId: currentWorkspace.id
}); });
router.push(`/org/${currentOrg.id}/overview`); router.push(`/org/${currentOrg.id}/${ProjectType.SecretManager}/overview`);
} catch (err) { } catch (err) {
console.error(err); console.error(err);
createNotification({ createNotification({
@@ -5,6 +5,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import issueBackupKey from "@app/components/utilities/cryptography/issueBackupKey"; import issueBackupKey from "@app/components/utilities/cryptography/issueBackupKey";
import { Button } from "@app/components/v2"; import { Button } from "@app/components/v2";
import { ProjectType } from "@app/hooks/api/workspace/types";
interface DownloadBackupPDFStepProps { interface DownloadBackupPDFStepProps {
email: string; email: string;
@@ -49,7 +50,7 @@ export const BackupPDFStep = ({ email, password, name }: DownloadBackupPDFStepPr
setBackupKeyIssued: () => {} setBackupKeyIssued: () => {}
}); });
router.push(`/org/${localStorage.getItem("orgData.id")}/overview`); router.push(`/org/${localStorage.getItem("orgData.id")}/${ProjectType.SecretManager}/overview`);
}} }}
size="sm" size="sm"
isFullWidth isFullWidth
@@ -27,6 +27,7 @@ import {
useGetServerRootKmsEncryptionDetails, useGetServerRootKmsEncryptionDetails,
useUpdateServerConfig useUpdateServerConfig
} from "@app/hooks/api"; } from "@app/hooks/api";
import { ProjectType } from "@app/hooks/api/workspace/types";
import { AuthPanel } from "./AuthPanel"; import { AuthPanel } from "./AuthPanel";
import { EncryptionPanel } from "./EncryptionPanel"; import { EncryptionPanel } from "./EncryptionPanel";
@@ -98,7 +99,7 @@ export const AdminDashboardPage = () => {
if (isNotAllowed && !isUserLoading) { if (isNotAllowed && !isUserLoading) {
if (orgs?.length) { if (orgs?.length) {
localStorage.setItem("orgData.id", orgs?.[0]?.id); localStorage.setItem("orgData.id", orgs?.[0]?.id);
router.push(`/org/${orgs?.[0]?.id}/overview`); router.push(`/org/${orgs?.[0]?.id}/${ProjectType.SecretManager}/overview`);
} }
} }
}, [isNotAllowed, isUserLoading]); }, [isNotAllowed, isUserLoading]);