diff --git a/backend/src/db/migrations/20240216154123_ghost_users.ts b/backend/src/db/migrations/20240216154123_ghost_users.ts index ddfdbe812..d0a840ee2 100644 --- a/backend/src/db/migrations/20240216154123_ghost_users.ts +++ b/backend/src/db/migrations/20240216154123_ghost_users.ts @@ -3,30 +3,30 @@ import { Knex } from "knex"; import { ProjectVersion, TableName } from "../schemas"; export async function up(knex: Knex): Promise { - const hasGhostUserColumn = await knex.schema.hasColumn(TableName.Users, "ghost"); + const hasGhostUserColumn = await knex.schema.hasColumn(TableName.Users, "isGhost"); const hasProjectVersionColumn = await knex.schema.hasColumn(TableName.Project, "version"); if (!hasGhostUserColumn) { await knex.schema.alterTable(TableName.Users, (t) => { - t.boolean("ghost").defaultTo(false).notNullable(); + t.boolean("isGhost").defaultTo(false).notNullable(); }); } if (!hasProjectVersionColumn) { await knex.schema.alterTable(TableName.Project, (t) => { - t.string("version").defaultTo(ProjectVersion.V1).notNullable(); - t.text("upgradeStatus").nullable(); + t.integer("version").defaultTo(ProjectVersion.V1).notNullable(); + t.string("upgradeStatus").nullable(); }); } } export async function down(knex: Knex): Promise { - const hasGhostUserColumn = await knex.schema.hasColumn(TableName.Users, "ghost"); + const hasGhostUserColumn = await knex.schema.hasColumn(TableName.Users, "isGhost"); const hasProjectVersionColumn = await knex.schema.hasColumn(TableName.Project, "version"); if (hasGhostUserColumn) { await knex.schema.alterTable(TableName.Users, (t) => { - t.dropColumn("ghost"); + t.dropColumn("isGhost"); }); } diff --git a/backend/src/db/schemas/models.ts b/backend/src/db/schemas/models.ts index b15912a57..abfb67949 100644 --- a/backend/src/db/schemas/models.ts +++ b/backend/src/db/schemas/models.ts @@ -113,8 +113,8 @@ export enum SecretType { } export enum ProjectVersion { - V1 = "v1", - V2 = "v2" + V1 = 1, + V2 = 2 } export enum ProjectUpgradeStatus { diff --git a/backend/src/db/schemas/projects.ts b/backend/src/db/schemas/projects.ts index 92be7a651..3834d6d58 100644 --- a/backend/src/db/schemas/projects.ts +++ b/backend/src/db/schemas/projects.ts @@ -15,7 +15,7 @@ export const ProjectsSchema = z.object({ orgId: z.string().uuid(), createdAt: z.date(), updatedAt: z.date(), - version: z.string().default("v1"), + version: z.number().default(1), upgradeStatus: z.string().nullable().optional() }); diff --git a/backend/src/db/schemas/users.ts b/backend/src/db/schemas/users.ts index e90b06187..cdbb5607a 100644 --- a/backend/src/db/schemas/users.ts +++ b/backend/src/db/schemas/users.ts @@ -20,7 +20,7 @@ export const UsersSchema = z.object({ devices: z.unknown().nullable().optional(), createdAt: z.date(), updatedAt: z.date(), - ghost: z.boolean().default(false) + isGhost: z.boolean().default(false) }); export type TUsers = z.infer; diff --git a/backend/src/ee/services/saml-config/saml-config-service.ts b/backend/src/ee/services/saml-config/saml-config-service.ts index 824db8251..b541e16be 100644 --- a/backend/src/ee/services/saml-config/saml-config-service.ts +++ b/backend/src/ee/services/saml-config/saml-config-service.ts @@ -339,7 +339,7 @@ export const samlConfigServiceFactory = ({ firstName, lastName, authMethods: [AuthMethod.EMAIL], - ghost: false + isGhost: false }, tx ); diff --git a/backend/src/services/auth/auth-login-service.ts b/backend/src/services/auth/auth-login-service.ts index 231a99e19..dcc9381b7 100644 --- a/backend/src/services/auth/auth-login-service.ts +++ b/backend/src/services/auth/auth-login-service.ts @@ -275,7 +275,7 @@ export const authLoginServiceFactory = ({ userDAL, tokenService, smtpService }: if (isOauthSignUpDisabled) throw new BadRequestError({ message: "User signup disabled", name: "Oauth 2 login" }); if (!user) { - user = await userDAL.create({ email, firstName, lastName, authMethods: [authMethod], ghost: false }); + user = await userDAL.create({ email, firstName, lastName, authMethods: [authMethod], isGhost: false }); } const isLinkingRequired = !user?.authMethods?.includes(authMethod); const isUserCompleted = user.isAccepted; diff --git a/backend/src/services/auth/auth-signup-service.ts b/backend/src/services/auth/auth-signup-service.ts index 0c2f53e5f..61fcfe3ce 100644 --- a/backend/src/services/auth/auth-signup-service.ts +++ b/backend/src/services/auth/auth-signup-service.ts @@ -50,7 +50,7 @@ export const authSignupServiceFactory = ({ throw new Error("Failed to send verification code for complete account"); } if (!user) { - user = await userDAL.create({ authMethods: [AuthMethod.EMAIL], email, ghost: false }); + user = await userDAL.create({ authMethods: [AuthMethod.EMAIL], email, isGhost: false }); } if (!user) throw new Error("Failed to create user"); diff --git a/backend/src/services/org/org-dal.ts b/backend/src/services/org/org-dal.ts index 20678b680..e4f81769f 100644 --- a/backend/src/services/org/org-dal.ts +++ b/backend/src/services/org/org-dal.ts @@ -77,7 +77,7 @@ export const orgDALFactory = (db: TDbClient) => { db.ref("id").withSchema(TableName.Users).as("userId"), db.ref("publicKey").withSchema(TableName.UserEncryptionKey) ) - .where({ ghost: false }); // MAKE SURE USER IS NOT A GHOST USER + .where({ isGhost: false }); // MAKE SURE USER IS NOT A GHOST USER return members.map(({ email, firstName, lastName, userId, publicKey, ...data }) => ({ ...data, user: { email, firstName, lastName, id: userId, publicKey } @@ -136,7 +136,7 @@ export const orgDALFactory = (db: TDbClient) => { db.ref("id").withSchema(TableName.Users).as("userId"), db.ref("publicKey").withSchema(TableName.UserEncryptionKey) ) - .where({ ghost: true }); + .where({ isGhost: true }); return member; } catch (error) { return null; @@ -150,7 +150,7 @@ export const orgDALFactory = (db: TDbClient) => { .join(TableName.Users, `${TableName.OrgMembership}.userId`, `${TableName.Users}.id`) .leftJoin(TableName.UserEncryptionKey, `${TableName.UserEncryptionKey}.userId`, `${TableName.Users}.id`) .select(db.ref("id").withSchema(TableName.Users).as("userId")) - .where({ ghost: true }); + .where({ isGhost: true }); return !!member; } catch (error) { return false; diff --git a/backend/src/services/org/org-service.ts b/backend/src/services/org/org-service.ts index 0f96b66ba..fac65dc1f 100644 --- a/backend/src/services/org/org-service.ts +++ b/backend/src/services/org/org-service.ts @@ -138,7 +138,7 @@ export const orgServiceFactory = ({ const user = await userDAL.create( { - ghost: true, + isGhost: true, authMethods: [AuthMethod.EMAIL], email, isAccepted: true @@ -401,7 +401,7 @@ export const orgServiceFactory = ({ email: inviteeEmail, isAccepted: false, authMethods: [AuthMethod.EMAIL], - ghost: false + isGhost: false }, tx ); diff --git a/backend/src/services/project-bot/project-bot-service.ts b/backend/src/services/project-bot/project-bot-service.ts index f5298fdc2..57170ad81 100644 --- a/backend/src/services/project-bot/project-bot-service.ts +++ b/backend/src/services/project-bot/project-bot-service.ts @@ -119,7 +119,7 @@ export const projectBotServiceFactory = ({ throw new BadRequestError({ message: "Failed to find project by bot ID" }); } - if (project.version === "v2") { + if (project.version === ProjectVersion.V2) { throw new BadRequestError({ message: "Failed to set bot active, project has a default bot enabled" }); } diff --git a/backend/src/services/project-membership/project-membership-dal.ts b/backend/src/services/project-membership/project-membership-dal.ts index 7bf5ff498..e0002f911 100644 --- a/backend/src/services/project-membership/project-membership-dal.ts +++ b/backend/src/services/project-membership/project-membership-dal.ts @@ -24,17 +24,17 @@ export const projectMembershipDALFactory = (db: TDbClient) => { db.ref("projectId").withSchema(TableName.ProjectMembership), db.ref("role").withSchema(TableName.ProjectMembership), db.ref("roleId").withSchema(TableName.ProjectMembership), - db.ref("ghost").withSchema(TableName.Users), + db.ref("isGhost").withSchema(TableName.Users), db.ref("email").withSchema(TableName.Users), db.ref("publicKey").withSchema(TableName.UserEncryptionKey), db.ref("firstName").withSchema(TableName.Users), db.ref("lastName").withSchema(TableName.Users), db.ref("id").withSchema(TableName.Users).as("userId") ) - .where({ ghost: false }); - return members.map(({ email, firstName, lastName, publicKey, ghost, ...data }) => ({ + .where({ isGhost: false }); + return members.map(({ email, firstName, lastName, publicKey, isGhost, ...data }) => ({ ...data, - user: { email, firstName, lastName, id: data.userId, publicKey, ghost } + user: { email, firstName, lastName, id: data.userId, publicKey, isGhost } })); } catch (error) { throw new DatabaseError({ error, name: "Find all project members" }); @@ -47,7 +47,7 @@ export const projectMembershipDALFactory = (db: TDbClient) => { .where({ projectId }) .join(TableName.Users, `${TableName.ProjectMembership}.userId`, `${TableName.Users}.id`) .select(selectAllTableCols(TableName.Users)) - .where({ ghost: true }) + .where({ isGhost: true }) .first(); return ghostUser; @@ -72,7 +72,7 @@ export const projectMembershipDALFactory = (db: TDbClient) => { db.ref("email").withSchema(TableName.Users) ) .whereIn("email", emails) - .where({ ghost: false }); + .where({ isGhost: false }); return members.map(({ userId, email, ...data }) => ({ ...data, user: { id: userId, email } diff --git a/backend/src/services/project-membership/project-membership-service.ts b/backend/src/services/project-membership/project-membership-service.ts index 7d5463819..9e2486966 100644 --- a/backend/src/services/project-membership/project-membership-service.ts +++ b/backend/src/services/project-membership/project-membership-service.ts @@ -16,11 +16,11 @@ import { getConfig } from "@app/lib/config/env"; import { infisicalSymmetricDecrypt } from "@app/lib/crypto/encryption"; import { BadRequestError } from "@app/lib/errors"; import { groupBy } from "@app/lib/fn"; -import { createWsMembers } from "@app/lib/project"; import { ActorType } from "../auth/auth-type"; import { TOrgDALFactory } from "../org/org-dal"; import { TProjectDALFactory } from "../project/project-dal"; +import { createWsMembers } from "../project/project-fns"; import { TProjectBotDALFactory } from "../project-bot/project-bot-dal"; import { TProjectKeyDALFactory } from "../project-key/project-key-dal"; import { TProjectRoleDALFactory } from "../project-role/project-role-dal"; @@ -320,7 +320,7 @@ export const projectMembershipServiceFactory = ({ const membershipUser = await userDAL.findUserByProjectMembershipId(membershipId); - if (membershipUser?.ghost) { + if (membershipUser?.isGhost) { throw new BadRequestError({ message: "Unauthorized member update", name: "Update project membership" @@ -365,7 +365,7 @@ export const projectMembershipServiceFactory = ({ const member = await userDAL.findUserByProjectMembershipId(membershipId); - if (member?.ghost) { + if (member?.isGhost) { throw new BadRequestError({ message: "Unauthorized member delete", name: "Delete project membership" diff --git a/backend/src/services/project/project-dal.ts b/backend/src/services/project/project-dal.ts index fafa02394..ecd60dc41 100644 --- a/backend/src/services/project/project-dal.ts +++ b/backend/src/services/project/project-dal.ts @@ -60,7 +60,7 @@ export const projectDALFactory = (db: TDbClient) => { .where({ projectId }) .join(TableName.Users, `${TableName.ProjectMembership}.userId`, `${TableName.Users}.id`) .select(selectAllTableCols(TableName.Users)) - .where({ ghost: true }) + .where({ isGhost: true }) .first(); return ghostUser; } catch (error) { diff --git a/backend/src/services/super-admin/super-admin-service.ts b/backend/src/services/super-admin/super-admin-service.ts index faaef42d4..64dac73f2 100644 --- a/backend/src/services/super-admin/super-admin-service.ts +++ b/backend/src/services/super-admin/super-admin-service.ts @@ -70,7 +70,7 @@ export const superAdminServiceFactory = ({ lastName, email, superAdmin: true, - ghost: false, + isGhost: false, isAccepted: true, authMethods: [AuthMethod.EMAIL] }, diff --git a/backend/src/services/user/user-dal.ts b/backend/src/services/user/user-dal.ts index 086ad5931..2c89b9c4d 100644 --- a/backend/src/services/user/user-dal.ts +++ b/backend/src/services/user/user-dal.ts @@ -23,7 +23,7 @@ export const userDALFactory = (db: TDbClient) => { const findUserEncKeyByEmail = async (email: string) => { try { return await db(TableName.Users) - .where({ email, ghost: false }) + .where({ email, isGhost: false }) .join(TableName.UserEncryptionKey, `${TableName.Users}.id`, `${TableName.UserEncryptionKey}.userId`) .first(); } catch (error) { diff --git a/frontend/src/components/v2/UpgradeProjectAlert/UpgradeProjectAlert.tsx b/frontend/src/components/v2/UpgradeProjectAlert/UpgradeProjectAlert.tsx index a9d8243e2..7fce14418 100644 --- a/frontend/src/components/v2/UpgradeProjectAlert/UpgradeProjectAlert.tsx +++ b/frontend/src/components/v2/UpgradeProjectAlert/UpgradeProjectAlert.tsx @@ -5,6 +5,7 @@ import { useNotificationContext } from "@app/components/context/Notifications/No import { useProjectPermission } from "@app/context"; import { useGetUpgradeProjectStatus, useUpgradeProject } from "@app/hooks/api"; import { Workspace } from "@app/hooks/api/types"; +import { ProjectVersion } from "@app/hooks/api/workspace/types"; import { Alert } from "../Alert"; import { Button } from "../Button"; @@ -55,7 +56,7 @@ export const UpgradeProjectAlert = ({ project }: UpgradeProjectAlertProps): JSX. let interval: NodeJS.Timeout | null = null; if (membership.role === "admin") { - if (project.version === "v1") { + if (project.version === ProjectVersion.V1) { getLatestProjectStatus(); } @@ -72,7 +73,7 @@ export const UpgradeProjectAlert = ({ project }: UpgradeProjectAlertProps): JSX. } interval = setInterval(() => { - if (project.version === "v1") { + if (project.version === ProjectVersion.V1) { getLatestProjectStatus(); } }, 5_000); @@ -92,7 +93,7 @@ export const UpgradeProjectAlert = ({ project }: UpgradeProjectAlertProps): JSX. (currentStatus === null && statusIsLoading)) && projectStatus?.status !== "FAILED"; - if (project.version !== "v1") return null; + if (project.version !== ProjectVersion.V1) return null; if (membership.role !== "admin") return null; return ( diff --git a/frontend/src/hooks/api/workspace/types.ts b/frontend/src/hooks/api/workspace/types.ts index a888b7c34..fc7c217dc 100644 --- a/frontend/src/hooks/api/workspace/types.ts +++ b/frontend/src/hooks/api/workspace/types.ts @@ -1,9 +1,14 @@ +export enum ProjectVersion { + V1 = 1, + V2 = 2 +} + export type Workspace = { __v: number; id: string; name: string; orgId: string; - version: "v1" | "v2"; + version: ProjectVersion; upgradeStatus: string | null; autoCapitalization: boolean; environments: WorkspaceEnv[]; diff --git a/frontend/src/views/IntegrationsPage/IntegrationsPage.tsx b/frontend/src/views/IntegrationsPage/IntegrationsPage.tsx index cd0fb08dd..be4bee7af 100644 --- a/frontend/src/views/IntegrationsPage/IntegrationsPage.tsx +++ b/frontend/src/views/IntegrationsPage/IntegrationsPage.tsx @@ -17,6 +17,7 @@ import { useUpdateBotActiveStatus } from "@app/hooks/api"; import { IntegrationAuth } from "@app/hooks/api/types"; +import { ProjectVersion } from "@app/hooks/api/workspace/types"; import { CloudIntegrationSection } from "./components/CloudIntegrationSection"; import { FrameworkIntegrationSection } from "./components/FrameworkIntegrationSection"; @@ -92,7 +93,7 @@ export const IntegrationsPage = withProjectPermission( isIntegrationsAuthorizedEmpty && isIntegrationsEmpty ) { - if (bot?.id && currentWorkspace?.version === "v1") + if (bot?.id && currentWorkspace?.version === ProjectVersion.V1) updateBotActiveStatusSync({ isActive: false, botId: bot.id, @@ -113,7 +114,7 @@ export const IntegrationsPage = withProjectPermission( if (!selectedCloudIntegration) return; try { - if (bot && !bot.isActive && currentWorkspace?.version === "v1") { + if (bot && !bot.isActive && currentWorkspace?.version === ProjectVersion.V1) { const botKey = generateBotKey(bot.publicKey, latestWsKey!); await updateBotActiveStatus({ workspaceId, diff --git a/frontend/src/views/Project/MembersPage/components/MemberListTab/MemberListTab.tsx b/frontend/src/views/Project/MembersPage/components/MemberListTab/MemberListTab.tsx index 9fb95e7d8..221cdb763 100644 --- a/frontend/src/views/Project/MembersPage/components/MemberListTab/MemberListTab.tsx +++ b/frontend/src/views/Project/MembersPage/components/MemberListTab/MemberListTab.tsx @@ -55,6 +55,7 @@ import { useUploadWsKey } from "@app/hooks/api"; import { ProjectMembershipRole } from "@app/hooks/api/roles/types"; +import { ProjectVersion } from "@app/hooks/api/workspace/types"; const addMemberFormSchema = z.object({ orgMembershipId: z.string().trim() @@ -117,14 +118,14 @@ export const MemberListTab = () => { if (!orgUser) return; try { - if (currentWorkspace.version === "v1") { + if (currentWorkspace.version === ProjectVersion.V1) { await addUserToWorkspace({ workspaceId, userPrivateKey, decryptKey: wsKey, members: [{ orgMembershipId, userPublicKey: orgUser.user.publicKey }] }); - } else if (currentWorkspace.version === "v2") { + } else if (currentWorkspace.version === ProjectVersion.V2) { await addUserToWorkspaceNonE2EE({ projectId: workspaceId, emails: [orgUser.user.email] diff --git a/frontend/src/views/SecretOverviewPage/SecretOverviewPage.tsx b/frontend/src/views/SecretOverviewPage/SecretOverviewPage.tsx index 7ea00831c..d31eb3b6e 100644 --- a/frontend/src/views/SecretOverviewPage/SecretOverviewPage.tsx +++ b/frontend/src/views/SecretOverviewPage/SecretOverviewPage.tsx @@ -40,6 +40,7 @@ import { useGetUserWsKey, useUpdateSecretV3 } from "@app/hooks/api"; +import { ProjectVersion } from "@app/hooks/api/workspace/types"; import { FolderBreadCrumbs } from "./components/FolderBreadCrumbs"; import { ProjectIndexSecretsSection } from "./components/ProjectIndexSecretsSection"; @@ -317,7 +318,9 @@ export const SecretOverviewPage = () => {

- {currentWorkspace?.version === "v1" && } + {currentWorkspace?.version === ProjectVersion.V1 && ( + + )}
diff --git a/frontend/src/views/Settings/ProjectSettingsPage/components/E2EESection/E2EESection.tsx b/frontend/src/views/Settings/ProjectSettingsPage/components/E2EESection/E2EESection.tsx index 586f98ac5..829397e0a 100644 --- a/frontend/src/views/Settings/ProjectSettingsPage/components/E2EESection/E2EESection.tsx +++ b/frontend/src/views/Settings/ProjectSettingsPage/components/E2EESection/E2EESection.tsx @@ -6,6 +6,7 @@ import { import { Alert, AlertDescription, Checkbox } from "@app/components/v2"; import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context"; import { useGetUserWsKey, useGetWorkspaceBot, useUpdateBotActiveStatus } from "@app/hooks/api"; +import { ProjectVersion } from "@app/hooks/api/workspace/types"; export const E2EESection = () => { const { currentWorkspace } = useWorkspace(); @@ -78,7 +79,7 @@ export const E2EESection = () => { if (!currentWorkspace) return null; - return bot && currentWorkspace.version === "v1" ? ( + return bot && currentWorkspace.version === ProjectVersion.V1 ? (

End-to-End Encryption