mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-06 09:26:47 +00:00
Final changes
This commit is contained in:
@@ -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,
|
||||||
@@ -238,7 +239,7 @@ export const AppLayout = ({ children }: LayoutProps) => {
|
|||||||
projectId: newProjectId
|
projectId: newProjectId
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line no-promise-executor-return -- We do this because the function returns too fast, which sometimes causes an error when the user is redirected.
|
// eslint-disable-next-line no-promise-executor-return -- We do this because the function returns too fast, which sometimes causes an error when the user is redirected.
|
||||||
await new Promise((resolve) => setTimeout(resolve, 2_000));
|
await new Promise((resolve) => setTimeout(resolve, 2_000));
|
||||||
|
|
||||||
@@ -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} />
|
||||||
|
|||||||
Reference in New Issue
Block a user