Final changes

This commit is contained in:
Daniel Hougaard
2024-02-22 05:00:40 +01:00
parent 816c793ae3
commit 7816d8593e
8 changed files with 83 additions and 12 deletions
+10
View File
@@ -230,6 +230,15 @@ export const orgDALFactory = (db: TDbClient) => {
} }
}; };
const deleteMembershipByUserId = async (userId: string, orgId: string, tx?: Knex) => {
try {
const [membership] = await (tx || db)(TableName.OrgMembership).where({ userId, orgId }).delete().returning("*");
return membership;
} catch (error) {
throw new DatabaseError({ error, name: "Delete org membership" });
}
};
const findMembership = async ( const findMembership = async (
filter: TFindFilter<TOrgMemberships>, filter: TFindFilter<TOrgMemberships>,
{ offset, limit, sort, tx }: TFindOpt<TOrgMemberships> = {} { offset, limit, sort, tx }: TFindOpt<TOrgMemberships> = {}
@@ -275,6 +284,7 @@ export const orgDALFactory = (db: TDbClient) => {
createMembership, createMembership,
updateMembershipById, updateMembershipById,
deleteMembershipById, deleteMembershipById,
deleteMembershipByUserId,
updateMembership updateMembership
}); });
}; };
@@ -112,6 +112,9 @@ export const projectQueueFactory = ({
await projectDAL.setProjectUpgradeStatus(data.projectId, ProjectUpgradeStatus.InProgress); // Set the status to in progress. This is important to prevent multiple upgrades at the same time. await projectDAL.setProjectUpgradeStatus(data.projectId, ProjectUpgradeStatus.InProgress); // Set the status to in progress. This is important to prevent multiple upgrades at the same time.
// eslint-disable-next-line no-promise-executor-return
// await new Promise((resolve) => setTimeout(resolve, 50_000));
const userPrivateKey = infisicalSymmetricDecrypt({ const userPrivateKey = infisicalSymmetricDecrypt({
keyEncoding: data.encryptedPrivateKey.keyEncoding, keyEncoding: data.encryptedPrivateKey.keyEncoding,
ciphertext: data.encryptedPrivateKey.encryptedKey, ciphertext: data.encryptedPrivateKey.encryptedKey,
@@ -17,6 +17,7 @@ import { TProjectPermission } from "@app/lib/types";
import { ActorType } from "../auth/auth-type"; import { ActorType } from "../auth/auth-type";
import { TIdentityOrgDALFactory } from "../identity/identity-org-dal"; import { TIdentityOrgDALFactory } from "../identity/identity-org-dal";
import { TIdentityProjectDALFactory } from "../identity-project/identity-project-dal"; import { TIdentityProjectDALFactory } from "../identity-project/identity-project-dal";
import { TOrgDALFactory } from "../org/org-dal";
import { TOrgServiceFactory } from "../org/org-service"; import { TOrgServiceFactory } from "../org/org-service";
import { TProjectBotDALFactory } from "../project-bot/project-bot-dal"; import { TProjectBotDALFactory } from "../project-bot/project-bot-dal";
import { TProjectEnvDALFactory } from "../project-env/project-env-dal"; import { TProjectEnvDALFactory } from "../project-env/project-env-dal";
@@ -53,6 +54,7 @@ type TProjectServiceFactoryDep = {
projectKeyDAL: Pick<TProjectKeyDALFactory, "create" | "findLatestProjectKey" | "delete" | "find" | "insertMany">; projectKeyDAL: Pick<TProjectKeyDALFactory, "create" | "findLatestProjectKey" | "delete" | "find" | "insertMany">;
projectBotDAL: Pick<TProjectBotDALFactory, "create" | "findById" | "delete" | "findOne">; projectBotDAL: Pick<TProjectBotDALFactory, "create" | "findById" | "delete" | "findOne">;
projectMembershipDAL: Pick<TProjectMembershipDALFactory, "create" | "findProjectGhostUser" | "findOne">; projectMembershipDAL: Pick<TProjectMembershipDALFactory, "create" | "findProjectGhostUser" | "findOne">;
orgDAL: Pick<TOrgDALFactory, "deleteMembershipByUserId">;
secretBlindIndexDAL: Pick<TSecretBlindIndexDALFactory, "create">; secretBlindIndexDAL: Pick<TSecretBlindIndexDALFactory, "create">;
permissionService: TPermissionServiceFactory; permissionService: TPermissionServiceFactory;
orgService: Pick<TOrgServiceFactory, "addGhostUser">; orgService: Pick<TOrgServiceFactory, "addGhostUser">;
@@ -68,6 +70,7 @@ export const projectServiceFactory = ({
permissionService, permissionService,
userDAL, userDAL,
folderDAL, folderDAL,
orgDAL,
orgService, orgService,
identityProjectDAL, identityProjectDAL,
projectBotDAL, projectBotDAL,
@@ -287,17 +290,22 @@ export const projectServiceFactory = ({
return results; return results;
}; };
const findProjectGhostUser = async (projectId: string) => {
const user = await projectMembershipDAL.findProjectGhostUser(projectId);
return user;
};
const deleteProject = async ({ actor, actorId, actorOrgId, projectId }: TDeleteProjectDTO) => { const deleteProject = async ({ actor, actorId, actorOrgId, projectId }: TDeleteProjectDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId); const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Project); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Project);
const deletedProject = await projectDAL.deleteById(projectId); const deletedProject = await projectDAL.transaction(async (tx) => {
const project = await projectDAL.deleteById(projectId, tx);
const projectGhostUser = await projectMembershipDAL.findProjectGhostUser(projectId).catch(() => null);
// Delete the org membership for the ghost user if it's found.
if (projectGhostUser) {
await orgDAL.deleteMembershipByUserId(projectGhostUser.id, deletedProject.orgId, tx);
}
return project;
});
return deletedProject; return deletedProject;
}; };
@@ -389,7 +397,6 @@ export const projectServiceFactory = ({
deleteProject, deleteProject,
getProjects, getProjects,
updateProject, updateProject,
findProjectGhostUser,
getProjectUpgradeStatus, getProjectUpgradeStatus,
getAProject, getAProject,
toggleAutoCapitalization, toggleAutoCapitalization,
@@ -0,0 +1,46 @@
import { useRouter } from "next/router";
import { Spinner } from "@app/components/v2";
import { useWorkspace } from "@app/context";
import { useToggle } from "@app/hooks";
import { useGetUpgradeProjectStatus } from "@app/hooks/api/workspace/queries";
import { ProjectVersion } from "@app/hooks/api/workspace/types";
export const UpgradeOverlay = () => {
const router = useRouter();
const { currentWorkspace } = useWorkspace();
const [isUpgrading, setIsUpgrading] = useToggle(false);
const { isLoading: isUpgradeStatusLoading } = useGetUpgradeProjectStatus({
projectId: currentWorkspace?.id ?? "",
enabled: currentWorkspace?.version === ProjectVersion.V1,
refetchInterval: 5_000,
onSuccess: (data) => {
if (!data) return;
if (data.status !== "IN_PROGRESS") {
setIsUpgrading.off();
} else if (data?.status === "IN_PROGRESS") {
setIsUpgrading.on();
}
}
});
// make sure only to display this on /project routes
if (!currentWorkspace || !router.pathname.includes("/project")) {
return null;
}
// for non admin this would throw an error
// so no need to render
return !isUpgradeStatusLoading && isUpgrading ? ( // isUpgrading
<div className="absolute top-0 left-0 z-50 flex h-screen w-screen items-center justify-center bg-bunker-500 bg-opacity-80">
<Spinner size="lg" className="text-primary" />
<div className="ml-4 flex flex-col space-y-1">
<div className="text-3xl font-medium text-white">Please wait</div>
<span className="inline-block text-white">Upgrading your project...</span>
</div>
</div>
) : (
<div />
);
};
@@ -0,0 +1 @@
export { UpgradeOverlay } from "./UpgradeOverlay";
@@ -29,7 +29,7 @@ export const UpgradeProjectAlert = ({ project }: UpgradeProjectAlertProps): JSX.
refetch: manualProjectStatusRefetch refetch: manualProjectStatusRefetch
} = useGetUpgradeProjectStatus({ } = useGetUpgradeProjectStatus({
projectId: project.id, projectId: project.id,
enabled: membership.role === "admin", enabled: membership.role === "admin" && project.version === ProjectVersion.V1,
refetchInterval: 5_000, refetchInterval: 5_000,
onSuccess: (data) => { onSuccess: (data) => {
if (membership.role !== "admin") { if (membership.role !== "admin") {
@@ -49,6 +49,7 @@ import {
SelectItem, SelectItem,
UpgradePlanModal UpgradePlanModal
} from "@app/components/v2"; } from "@app/components/v2";
import { UpgradeOverlay } from "@app/components/v2/UpgradeOverlay";
import { import {
OrgPermissionActions, OrgPermissionActions,
OrgPermissionSubjects, OrgPermissionSubjects,
@@ -261,6 +262,7 @@ export const AppLayout = ({ children }: LayoutProps) => {
<aside className="dark w-full border-r border-mineshaft-600 bg-gradient-to-tr from-mineshaft-700 via-mineshaft-800 to-mineshaft-900 md:w-60"> <aside className="dark w-full border-r border-mineshaft-600 bg-gradient-to-tr from-mineshaft-700 via-mineshaft-800 to-mineshaft-900 md:w-60">
<nav className="items-between flex h-full flex-col justify-between overflow-y-auto dark:[color-scheme:dark]"> <nav className="items-between flex h-full flex-col justify-between overflow-y-auto dark:[color-scheme:dark]">
<div> <div>
<UpgradeOverlay />
{!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") || {(router.asPath.includes("project") ||
@@ -44,7 +44,6 @@ import { ProjectVersion } from "@app/hooks/api/workspace/types";
import { FolderBreadCrumbs } from "./components/FolderBreadCrumbs"; import { FolderBreadCrumbs } from "./components/FolderBreadCrumbs";
import { ProjectIndexSecretsSection } from "./components/ProjectIndexSecretsSection"; import { ProjectIndexSecretsSection } from "./components/ProjectIndexSecretsSection";
// import { ProjectIndexSecretsSection } from "./components/ProjectIndexSecretsSection";
import { SecretOverviewFolderRow } from "./components/SecretOverviewFolderRow"; import { SecretOverviewFolderRow } from "./components/SecretOverviewFolderRow";
import { SecretOverviewTableRow } from "./components/SecretOverviewTableRow"; import { SecretOverviewTableRow } from "./components/SecretOverviewTableRow";
@@ -319,7 +318,10 @@ export const SecretOverviewPage = () => {
</div> </div>
{currentWorkspace?.version === ProjectVersion.V1 && ( {currentWorkspace?.version === ProjectVersion.V1 && (
<UpgradeProjectAlert project={currentWorkspace} /> <>
<UpgradeProjectAlert project={currentWorkspace} />
{/* <UpgradeOverlay /> */}
</>
)} )}
<div className="mt-8 flex items-center justify-between"> <div className="mt-8 flex items-center justify-between">
<FolderBreadCrumbs secretPath={secretPath} onResetSearch={handleResetSearch} /> <FolderBreadCrumbs secretPath={secretPath} onResetSearch={handleResetSearch} />