mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-07 17:27:40 +00:00
feat: fixed review comments
This commit is contained in:
@@ -202,7 +202,7 @@ export async function up(knex: Knex): Promise<void> {
|
|||||||
.select("projectId");
|
.select("projectId");
|
||||||
for (const { projectId } of projectsWithCmek) {
|
for (const { projectId } of projectsWithCmek) {
|
||||||
if (projectId) {
|
if (projectId) {
|
||||||
const newProjectId = await newProject(knex, projectId, ProjectType.Cmek);
|
const newProjectId = await newProject(knex, projectId, ProjectType.KMS);
|
||||||
await knex(TableName.KmsKey)
|
await knex(TableName.KmsKey)
|
||||||
.where({
|
.where({
|
||||||
isReserved: false,
|
isReserved: false,
|
||||||
@@ -211,14 +211,13 @@ export async function up(knex: Knex): Promise<void> {
|
|||||||
.update({ projectId: newProjectId });
|
.update({ projectId: newProjectId });
|
||||||
await knex(TableName.ProjectSplitBackfillIds).insert({
|
await knex(TableName.ProjectSplitBackfillIds).insert({
|
||||||
sourceProjectId: projectId,
|
sourceProjectId: projectId,
|
||||||
destinationProjectType: ProjectType.Cmek,
|
destinationProjectType: ProjectType.KMS,
|
||||||
destinationProjectId: newProjectId
|
destinationProjectId: newProjectId
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* eslint-enable */
|
/* eslint-enable */
|
||||||
|
|
||||||
await knex.schema.alterTable(TableName.Project, (t) => {
|
await knex.schema.alterTable(TableName.Project, (t) => {
|
||||||
t.string("type").notNullable().alter();
|
t.string("type").notNullable().alter();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -205,5 +205,5 @@ export enum IdentityAuthMethod {
|
|||||||
export enum ProjectType {
|
export enum ProjectType {
|
||||||
SecretManager = "secret-manager",
|
SecretManager = "secret-manager",
|
||||||
CertificateManager = "cert-manager",
|
CertificateManager = "cert-manager",
|
||||||
Cmek = "cmek"
|
KMS = "kms"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export const ProjectsSchema = z.object({
|
|||||||
kmsSecretManagerKeyId: z.string().uuid().nullable().optional(),
|
kmsSecretManagerKeyId: z.string().uuid().nullable().optional(),
|
||||||
kmsSecretManagerEncryptedDataKey: zodBuffer.nullable().optional(),
|
kmsSecretManagerEncryptedDataKey: zodBuffer.nullable().optional(),
|
||||||
description: z.string().nullable().optional(),
|
description: z.string().nullable().optional(),
|
||||||
type: z.string().nullable().optional()
|
type: z.string()
|
||||||
});
|
});
|
||||||
|
|
||||||
export type TProjects = z.infer<typeof ProjectsSchema>;
|
export type TProjects = z.infer<typeof ProjectsSchema>;
|
||||||
|
|||||||
@@ -328,7 +328,7 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
|
|||||||
identity: IdentitiesSchema.pick({ name: true, id: true }).extend({
|
identity: IdentitiesSchema.pick({ name: true, id: true }).extend({
|
||||||
authMethods: z.array(z.string())
|
authMethods: z.array(z.string())
|
||||||
}),
|
}),
|
||||||
project: SanitizedProjectSchema.pick({ name: true, id: true })
|
project: SanitizedProjectSchema.pick({ name: true, id: true, type: true })
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -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.enum([ProjectType.SecretManager, ProjectType.Cmek, ProjectType.CertificateManager, "all"]).optional()
|
type: z.enum([ProjectType.SecretManager, ProjectType.KMS, ProjectType.CertificateManager, "all"]).optional()
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
|
|||||||
@@ -77,7 +77,9 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
params: z.object({
|
params: z.object({
|
||||||
organizationId: z.string().trim().describe(ORGANIZATIONS.GET_PROJECTS.organizationId),
|
organizationId: z.string().trim().describe(ORGANIZATIONS.GET_PROJECTS.organizationId)
|
||||||
|
}),
|
||||||
|
querystring: z.object({
|
||||||
type: z.nativeEnum(ProjectType).optional().describe(ORGANIZATIONS.GET_PROJECTS.type)
|
type: z.nativeEnum(ProjectType).optional().describe(ORGANIZATIONS.GET_PROJECTS.type)
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
@@ -106,7 +108,8 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
|
|||||||
actorId: req.permission.id,
|
actorId: req.permission.id,
|
||||||
actorOrgId: req.permission.orgId,
|
actorOrgId: req.permission.orgId,
|
||||||
actorAuthMethod: req.permission.authMethod,
|
actorAuthMethod: req.permission.authMethod,
|
||||||
orgId: req.params.organizationId
|
orgId: req.params.organizationId,
|
||||||
|
type: req.query.type
|
||||||
});
|
});
|
||||||
|
|
||||||
return { workspaces };
|
return { workspaces };
|
||||||
@@ -283,7 +286,7 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
|
|||||||
lastName: true,
|
lastName: true,
|
||||||
id: true
|
id: true
|
||||||
}).merge(UserEncryptionKeysSchema.pick({ publicKey: true })),
|
}).merge(UserEncryptionKeysSchema.pick({ publicKey: true })),
|
||||||
project: ProjectsSchema.pick({ name: true, id: true }),
|
project: ProjectsSchema.pick({ name: true, id: true, type: true }),
|
||||||
roles: z.array(
|
roles: z.array(
|
||||||
z.object({
|
z.object({
|
||||||
id: z.string(),
|
id: z.string(),
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export type TCmekServiceFactory = ReturnType<typeof cmekServiceFactory>;
|
|||||||
export const cmekServiceFactory = ({ kmsService, kmsDAL, permissionService, projectDAL }: TCmekServiceFactoryDep) => {
|
export const cmekServiceFactory = ({ kmsService, kmsDAL, permissionService, projectDAL }: TCmekServiceFactoryDep) => {
|
||||||
const createCmek = async ({ projectId: preSplitProjectId, ...dto }: TCreateCmekDTO, actor: OrgServiceActor) => {
|
const createCmek = async ({ projectId: preSplitProjectId, ...dto }: TCreateCmekDTO, actor: OrgServiceActor) => {
|
||||||
let projectId = preSplitProjectId;
|
let projectId = preSplitProjectId;
|
||||||
const cmekProjectFromSplit = await projectDAL.getProjectFromSplitId(projectId, ProjectType.Cmek);
|
const cmekProjectFromSplit = await projectDAL.getProjectFromSplitId(projectId, ProjectType.KMS);
|
||||||
if (cmekProjectFromSplit) {
|
if (cmekProjectFromSplit) {
|
||||||
projectId = cmekProjectFromSplit.id;
|
projectId = cmekProjectFromSplit.id;
|
||||||
}
|
}
|
||||||
@@ -41,7 +41,7 @@ export const cmekServiceFactory = ({ kmsService, kmsDAL, permissionService, proj
|
|||||||
actor.authMethod,
|
actor.authMethod,
|
||||||
actor.orgId
|
actor.orgId
|
||||||
);
|
);
|
||||||
ForbidOnInvalidProjectType(ProjectType.Cmek);
|
ForbidOnInvalidProjectType(ProjectType.KMS);
|
||||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionCmekActions.Create, ProjectPermissionSub.Cmek);
|
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionCmekActions.Create, ProjectPermissionSub.Cmek);
|
||||||
|
|
||||||
const cmek = await kmsService.generateKmsKey({
|
const cmek = await kmsService.generateKmsKey({
|
||||||
@@ -67,7 +67,7 @@ export const cmekServiceFactory = ({ kmsService, kmsDAL, permissionService, proj
|
|||||||
actor.authMethod,
|
actor.authMethod,
|
||||||
actor.orgId
|
actor.orgId
|
||||||
);
|
);
|
||||||
ForbidOnInvalidProjectType(ProjectType.Cmek);
|
ForbidOnInvalidProjectType(ProjectType.KMS);
|
||||||
|
|
||||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionCmekActions.Edit, ProjectPermissionSub.Cmek);
|
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionCmekActions.Edit, ProjectPermissionSub.Cmek);
|
||||||
|
|
||||||
@@ -90,7 +90,7 @@ export const cmekServiceFactory = ({ kmsService, kmsDAL, permissionService, proj
|
|||||||
actor.authMethod,
|
actor.authMethod,
|
||||||
actor.orgId
|
actor.orgId
|
||||||
);
|
);
|
||||||
ForbidOnInvalidProjectType(ProjectType.Cmek);
|
ForbidOnInvalidProjectType(ProjectType.KMS);
|
||||||
|
|
||||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionCmekActions.Delete, ProjectPermissionSub.Cmek);
|
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionCmekActions.Delete, ProjectPermissionSub.Cmek);
|
||||||
|
|
||||||
@@ -104,7 +104,7 @@ export const cmekServiceFactory = ({ kmsService, kmsDAL, permissionService, proj
|
|||||||
actor: OrgServiceActor
|
actor: OrgServiceActor
|
||||||
) => {
|
) => {
|
||||||
let projectId = preSplitProjectId;
|
let projectId = preSplitProjectId;
|
||||||
const cmekProjectFromSplit = await projectDAL.getProjectFromSplitId(preSplitProjectId, ProjectType.Cmek);
|
const cmekProjectFromSplit = await projectDAL.getProjectFromSplitId(preSplitProjectId, ProjectType.KMS);
|
||||||
if (cmekProjectFromSplit) {
|
if (cmekProjectFromSplit) {
|
||||||
projectId = cmekProjectFromSplit.id;
|
projectId = cmekProjectFromSplit.id;
|
||||||
}
|
}
|
||||||
@@ -141,7 +141,7 @@ export const cmekServiceFactory = ({ kmsService, kmsDAL, permissionService, proj
|
|||||||
actor.orgId
|
actor.orgId
|
||||||
);
|
);
|
||||||
|
|
||||||
ForbidOnInvalidProjectType(ProjectType.Cmek);
|
ForbidOnInvalidProjectType(ProjectType.KMS);
|
||||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionCmekActions.Encrypt, ProjectPermissionSub.Cmek);
|
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionCmekActions.Encrypt, ProjectPermissionSub.Cmek);
|
||||||
|
|
||||||
const encrypt = await kmsService.encryptWithKmsKey({ kmsId: keyId });
|
const encrypt = await kmsService.encryptWithKmsKey({ kmsId: keyId });
|
||||||
@@ -167,7 +167,7 @@ export const cmekServiceFactory = ({ kmsService, kmsDAL, permissionService, proj
|
|||||||
actor.authMethod,
|
actor.authMethod,
|
||||||
actor.orgId
|
actor.orgId
|
||||||
);
|
);
|
||||||
ForbidOnInvalidProjectType(ProjectType.Cmek);
|
ForbidOnInvalidProjectType(ProjectType.KMS);
|
||||||
|
|
||||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionCmekActions.Decrypt, ProjectPermissionSub.Cmek);
|
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionCmekActions.Decrypt, ProjectPermissionSub.Cmek);
|
||||||
|
|
||||||
|
|||||||
@@ -102,6 +102,7 @@ export const identityProjectDALFactory = (db: TDbClient) => {
|
|||||||
db.ref("temporaryAccessEndTime").withSchema(TableName.IdentityProjectMembershipRole),
|
db.ref("temporaryAccessEndTime").withSchema(TableName.IdentityProjectMembershipRole),
|
||||||
db.ref("projectId").withSchema(TableName.IdentityProjectMembership),
|
db.ref("projectId").withSchema(TableName.IdentityProjectMembership),
|
||||||
db.ref("name").as("projectName").withSchema(TableName.Project),
|
db.ref("name").as("projectName").withSchema(TableName.Project),
|
||||||
|
db.ref("type").as("projectType").withSchema(TableName.Project),
|
||||||
db.ref("id").as("uaId").withSchema(TableName.IdentityUniversalAuth),
|
db.ref("id").as("uaId").withSchema(TableName.IdentityUniversalAuth),
|
||||||
db.ref("id").as("gcpId").withSchema(TableName.IdentityGcpAuth),
|
db.ref("id").as("gcpId").withSchema(TableName.IdentityGcpAuth),
|
||||||
db.ref("id").as("awsId").withSchema(TableName.IdentityAwsAuth),
|
db.ref("id").as("awsId").withSchema(TableName.IdentityAwsAuth),
|
||||||
@@ -126,7 +127,8 @@ export const identityProjectDALFactory = (db: TDbClient) => {
|
|||||||
createdAt,
|
createdAt,
|
||||||
updatedAt,
|
updatedAt,
|
||||||
projectId,
|
projectId,
|
||||||
projectName
|
projectName,
|
||||||
|
projectType
|
||||||
}) => ({
|
}) => ({
|
||||||
id,
|
id,
|
||||||
identityId,
|
identityId,
|
||||||
@@ -147,7 +149,8 @@ export const identityProjectDALFactory = (db: TDbClient) => {
|
|||||||
},
|
},
|
||||||
project: {
|
project: {
|
||||||
id: projectId,
|
id: projectId,
|
||||||
name: projectName
|
name: projectName,
|
||||||
|
type: projectType
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
key: "id",
|
key: "id",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
|
import { ProjectType } from "@app/db/schemas";
|
||||||
import { TOrgPermission } from "@app/lib/types";
|
import { TOrgPermission } from "@app/lib/types";
|
||||||
|
|
||||||
import { ActorAuthMethod, ActorType, MfaMethod } from "../auth/auth-type";
|
import { ActorAuthMethod, ActorType, MfaMethod } from "../auth/auth-type";
|
||||||
import { ProjectType } from "@app/db/schemas";
|
|
||||||
|
|
||||||
export type TUpdateOrgMembershipDTO = {
|
export type TUpdateOrgMembershipDTO = {
|
||||||
userId: string;
|
userId: string;
|
||||||
|
|||||||
@@ -217,20 +217,33 @@ export const projectMembershipDALFactory = (db: TDbClient) => {
|
|||||||
db.ref("temporaryAccessStartTime").withSchema(TableName.ProjectUserMembershipRole),
|
db.ref("temporaryAccessStartTime").withSchema(TableName.ProjectUserMembershipRole),
|
||||||
db.ref("temporaryAccessEndTime").withSchema(TableName.ProjectUserMembershipRole),
|
db.ref("temporaryAccessEndTime").withSchema(TableName.ProjectUserMembershipRole),
|
||||||
db.ref("name").as("projectName").withSchema(TableName.Project),
|
db.ref("name").as("projectName").withSchema(TableName.Project),
|
||||||
db.ref("id").as("projectId").withSchema(TableName.Project)
|
db.ref("id").as("projectId").withSchema(TableName.Project),
|
||||||
|
db.ref("type").as("projectType").withSchema(TableName.Project)
|
||||||
)
|
)
|
||||||
.where({ isGhost: false });
|
.where({ isGhost: false });
|
||||||
|
|
||||||
const members = sqlNestRelationships({
|
const members = sqlNestRelationships({
|
||||||
data: docs,
|
data: docs,
|
||||||
parentMapper: ({ email, firstName, username, lastName, publicKey, isGhost, id, projectId, projectName }) => ({
|
parentMapper: ({
|
||||||
|
email,
|
||||||
|
firstName,
|
||||||
|
username,
|
||||||
|
lastName,
|
||||||
|
publicKey,
|
||||||
|
isGhost,
|
||||||
|
id,
|
||||||
|
projectId,
|
||||||
|
projectName,
|
||||||
|
projectType
|
||||||
|
}) => ({
|
||||||
id,
|
id,
|
||||||
userId,
|
userId,
|
||||||
projectId,
|
projectId,
|
||||||
user: { email, username, firstName, lastName, id: userId, publicKey, isGhost },
|
user: { email, username, firstName, lastName, id: userId, publicKey, isGhost },
|
||||||
project: {
|
project: {
|
||||||
id: projectId,
|
id: projectId,
|
||||||
name: projectName
|
name: projectName,
|
||||||
|
type: projectType
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
key: "id",
|
key: "id",
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ import {
|
|||||||
useSubscription,
|
useSubscription,
|
||||||
useUser
|
useUser
|
||||||
} from "@app/context";
|
} from "@app/context";
|
||||||
import { getWorkspaceHomePage } from "@app/helpers/workspace";
|
import { getProjectHomePage } from "@app/helpers/project";
|
||||||
import {
|
import {
|
||||||
fetchOrgUsers,
|
fetchOrgUsers,
|
||||||
useAddUserToWsNonE2EE,
|
useAddUserToWsNonE2EE,
|
||||||
@@ -120,9 +120,7 @@ const NewProjectForm = ({ onOpenChange, projectType }: NewProjectFormProps) => {
|
|||||||
if (!user) return;
|
if (!user) return;
|
||||||
try {
|
try {
|
||||||
const {
|
const {
|
||||||
data: {
|
data: { project }
|
||||||
project
|
|
||||||
}
|
|
||||||
} = await createWs.mutateAsync({
|
} = await createWs.mutateAsync({
|
||||||
projectName: name,
|
projectName: name,
|
||||||
projectDescription: description,
|
projectDescription: description,
|
||||||
@@ -130,7 +128,7 @@ const NewProjectForm = ({ onOpenChange, projectType }: NewProjectFormProps) => {
|
|||||||
template,
|
template,
|
||||||
type: projectType
|
type: projectType
|
||||||
});
|
});
|
||||||
const { id: newProjectId } = project
|
const { id: newProjectId } = project;
|
||||||
|
|
||||||
if (addMembers) {
|
if (addMembers) {
|
||||||
const orgUsers = await fetchOrgUsers(currentOrg.id);
|
const orgUsers = await fetchOrgUsers(currentOrg.id);
|
||||||
@@ -150,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(getWorkspaceHomePage(project));
|
router.push(getProjectHomePage(project));
|
||||||
} 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" });
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { apiRequest } from "@app/config/request";
|
import { apiRequest } from "@app/config/request";
|
||||||
import { createWorkspace } from "@app/hooks/api/workspace/queries";
|
import { createWorkspace } from "@app/hooks/api/workspace/queries";
|
||||||
import { ProjectType } from "@app/hooks/api/workspace/types";
|
import { ProjectType, Workspace } from "@app/hooks/api/workspace/types";
|
||||||
|
|
||||||
const secretsToBeAdded = [
|
const secretsToBeAdded = [
|
||||||
{
|
{
|
||||||
@@ -37,7 +37,7 @@ const secretsToBeAdded = [
|
|||||||
* Create and initialize a new project in organization with id [organizationId]
|
* Create and initialize a new project in organization with id [organizationId]
|
||||||
* Note: current user should be a member of the organization
|
* Note: current user should be a member of the organization
|
||||||
*/
|
*/
|
||||||
const initProjectHelper = async ({ projectName }: { projectName: string }) => {
|
export const initProjectHelper = async ({ projectName }: { projectName: string }) => {
|
||||||
// create new project
|
// create new project
|
||||||
const {
|
const {
|
||||||
data: { project }
|
data: { project }
|
||||||
@@ -61,4 +61,22 @@ const initProjectHelper = async ({ projectName }: { projectName: string }) => {
|
|||||||
return project;
|
return project;
|
||||||
};
|
};
|
||||||
|
|
||||||
export { initProjectHelper };
|
export const getProjectHomePage = (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`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getProjectTitle = (type: ProjectType) => {
|
||||||
|
const titleConvert = {
|
||||||
|
[ProjectType.SecretManager]: "Secret Management",
|
||||||
|
[ProjectType.KMS]: "Key Management",
|
||||||
|
[ProjectType.CertificateManager]: "Cert Management"
|
||||||
|
};
|
||||||
|
return titleConvert[type];
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
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`;
|
|
||||||
};
|
|
||||||
@@ -47,7 +47,7 @@ export type IdentityMembershipOrg = {
|
|||||||
export type IdentityMembership = {
|
export type IdentityMembership = {
|
||||||
id: string;
|
id: string;
|
||||||
identity: Identity;
|
identity: Identity;
|
||||||
project: Pick<Workspace, "id" | "name">;
|
project: Pick<Workspace, "id" | "name" | "type">;
|
||||||
roles: Array<
|
roles: Array<
|
||||||
{
|
{
|
||||||
id: string;
|
id: string;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { MfaMethod } from "../auth/types";
|
import { MfaMethod } from "../auth/types";
|
||||||
import { UserWsKeyPair } from "../keys/types";
|
import { UserWsKeyPair } from "../keys/types";
|
||||||
import { ProjectUserMembershipTemporaryMode } from "../workspace/types";
|
import { ProjectType, ProjectUserMembershipTemporaryMode } from "../workspace/types";
|
||||||
|
|
||||||
export enum AuthMethod {
|
export enum AuthMethod {
|
||||||
EMAIL = "email",
|
EMAIL = "email",
|
||||||
@@ -95,6 +95,7 @@ export type TWorkspaceUser = {
|
|||||||
project: {
|
project: {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
|
type: ProjectType;
|
||||||
};
|
};
|
||||||
inviteEmail: string;
|
inviteEmail: string;
|
||||||
organization: string;
|
organization: string;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export enum ProjectVersion {
|
|||||||
export enum ProjectType {
|
export enum ProjectType {
|
||||||
SecretManager = "secret-manager",
|
SecretManager = "secret-manager",
|
||||||
CertificateManager = "cert-manager",
|
CertificateManager = "cert-manager",
|
||||||
Cmek = "cmek"
|
KMS = "kms"
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum ProjectUserMembershipTemporaryMode {
|
export enum ProjectUserMembershipTemporaryMode {
|
||||||
|
|||||||
@@ -352,7 +352,7 @@ export const AppLayout = ({ children }: LayoutProps) => {
|
|||||||
)}
|
)}
|
||||||
icon="system-outline-165-view-carousel"
|
icon="system-outline-165-view-carousel"
|
||||||
>
|
>
|
||||||
Secret Manager
|
Secret Management
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
@@ -367,17 +367,17 @@ export const AppLayout = ({ children }: LayoutProps) => {
|
|||||||
)}
|
)}
|
||||||
icon="system-outline-165-view-carousel"
|
icon="system-outline-165-view-carousel"
|
||||||
>
|
>
|
||||||
Cert Manager
|
Cert Management
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
<Link href={`/org/${currentOrg?.id}/${ProjectType.Cmek}/overview`} passHref>
|
<Link href={`/org/${currentOrg?.id}/${ProjectType.KMS}/overview`} passHref>
|
||||||
<a>
|
<a>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
isSelected={router.asPath.includes(`/${ProjectType.Cmek}/overview`)}
|
isSelected={router.asPath.includes(`/${ProjectType.KMS}/overview`)}
|
||||||
icon="system-outline-165-view-carousel"
|
icon="system-outline-165-view-carousel"
|
||||||
>
|
>
|
||||||
Cmek
|
Key Management
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import {
|
|||||||
useSubscription,
|
useSubscription,
|
||||||
useWorkspace
|
useWorkspace
|
||||||
} from "@app/context";
|
} from "@app/context";
|
||||||
import { getWorkspaceHomePage } from "@app/helpers/workspace";
|
import { getProjectHomePage } from "@app/helpers/project";
|
||||||
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";
|
||||||
@@ -191,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(getWorkspaceHomePage(project));
|
window.location.assign(getProjectHomePage(project));
|
||||||
}}
|
}}
|
||||||
options={options}
|
options={options}
|
||||||
components={{
|
components={{
|
||||||
|
|||||||
+3
-3
@@ -31,7 +31,7 @@ export const ProjectSidebarItem = () => {
|
|||||||
|
|
||||||
const isSecretManager = currentWorkspace?.type === ProjectType.SecretManager;
|
const isSecretManager = currentWorkspace?.type === ProjectType.SecretManager;
|
||||||
const isCertManager = currentWorkspace?.type === ProjectType.CertificateManager;
|
const isCertManager = currentWorkspace?.type === ProjectType.CertificateManager;
|
||||||
const isCmek = currentWorkspace?.type === ProjectType.Cmek;
|
const isCmek = currentWorkspace?.type === ProjectType.KMS;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Menu>
|
<Menu>
|
||||||
@@ -71,10 +71,10 @@ export const ProjectSidebarItem = () => {
|
|||||||
</Link>
|
</Link>
|
||||||
)}
|
)}
|
||||||
{isCmek && (
|
{isCmek && (
|
||||||
<Link href={`/${ProjectType.Cmek}/${currentWorkspace?.id}/kms`} passHref>
|
<Link href={`/${ProjectType.KMS}/${currentWorkspace?.id}/kms`} passHref>
|
||||||
<a>
|
<a>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
isSelected={router.asPath === `/${ProjectType.Cmek}/${currentWorkspace?.id}/kms`}
|
isSelected={router.asPath === `/${ProjectType.KMS}/${currentWorkspace?.id}/kms`}
|
||||||
icon="system-outline-90-lock-closed"
|
icon="system-outline-90-lock-closed"
|
||||||
>
|
>
|
||||||
Key Management
|
Key Management
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@ 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.KMS} />;
|
||||||
|
|
||||||
Object.assign(CmekManagerOverviewPage, { requireAuth: true });
|
Object.assign(CmekManagerOverviewPage, { requireAuth: true });
|
||||||
|
|
||||||
@@ -2,6 +2,7 @@ import { useEffect } from "react";
|
|||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
import { useOrganization } from "@app/context";
|
import { useOrganization } from "@app/context";
|
||||||
|
import { ProjectType } from "@app/hooks/api/workspace/types";
|
||||||
|
|
||||||
// #TODO: Update all the workspaceIds
|
// #TODO: Update all the workspaceIds
|
||||||
const OrganizationPage = () => {
|
const OrganizationPage = () => {
|
||||||
@@ -9,7 +10,7 @@ const OrganizationPage = () => {
|
|||||||
const { currentOrg } = useOrganization();
|
const { currentOrg } = useOrganization();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (router.isReady && currentOrg?.id) {
|
if (router.isReady && currentOrg?.id) {
|
||||||
router.push(`/org/${currentOrg?.id}/secret-manager/overview`);
|
router.push(`/org/${currentOrg?.id}/${ProjectType.SecretManager}/overview`);
|
||||||
}
|
}
|
||||||
}, [router.isReady, currentOrg?.id]);
|
}, [router.isReady, currentOrg?.id]);
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ import {
|
|||||||
useOrganization,
|
useOrganization,
|
||||||
useSubscription
|
useSubscription
|
||||||
} from "@app/context";
|
} from "@app/context";
|
||||||
import { getWorkspaceHomePage } from "@app/helpers/workspace";
|
import { getProjectHomePage } from "@app/helpers/project";
|
||||||
import { usePagination, useResetPageHelper } from "@app/hooks";
|
import { usePagination, useResetPageHelper } from "@app/hooks";
|
||||||
import { useGetUserWorkspaces } from "@app/hooks/api";
|
import { useGetUserWorkspaces } from "@app/hooks/api";
|
||||||
import { OrderByDirection } from "@app/hooks/api/generic/types";
|
import { OrderByDirection } from "@app/hooks/api/generic/types";
|
||||||
@@ -60,9 +60,17 @@ enum ProjectOrderBy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const formatTitle = (type: ProjectType) => {
|
const formatTitle = (type: ProjectType) => {
|
||||||
if (type === ProjectType.SecretManager) return "Secret Managers";
|
if (type === ProjectType.SecretManager) return "Secret Management";
|
||||||
if (type === ProjectType.CertificateManager) return "Cert Managers";
|
if (type === ProjectType.CertificateManager) return "Cert Management";
|
||||||
return "Cmek";
|
return "Key Management";
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatDescription = (type: ProjectType) => {
|
||||||
|
if (type === ProjectType.SecretManager)
|
||||||
|
return "Securely store, manage, and rotate various application secrets, such as database credentials, API keys, etc.";
|
||||||
|
if (type === ProjectType.CertificateManager)
|
||||||
|
return "Manage your PKI infrastructure and issue digital certificates for services, applications, and devices.";
|
||||||
|
return "Centralize the management of keys for cryptographic operations, such as encryption and decryption.";
|
||||||
};
|
};
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -182,7 +190,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(getWorkspaceHomePage(workspace));
|
router.push(getProjectHomePage(workspace));
|
||||||
localStorage.setItem("projectData.id", workspace.id);
|
localStorage.setItem("projectData.id", workspace.id);
|
||||||
}}
|
}}
|
||||||
key={workspace.id}
|
key={workspace.id}
|
||||||
@@ -246,7 +254,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(getWorkspaceHomePage(workspace));
|
router.push(getProjectHomePage(workspace));
|
||||||
localStorage.setItem("projectData.id", workspace.id);
|
localStorage.setItem("projectData.id", workspace.id);
|
||||||
}}
|
}}
|
||||||
key={workspace.id}
|
key={workspace.id}
|
||||||
@@ -382,9 +390,12 @@ export const ProductOverview = ({ type }: Props) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="mb-4 flex flex-col items-start justify-start px-6 py-6 pb-0 text-3xl">
|
<div className="mb-4 flex flex-col items-start justify-start px-6 py-6 pb-0">
|
||||||
<div className="flex w-full justify-between">
|
<div className="flex w-full justify-between">
|
||||||
<p className="mr-4 font-semibold text-white">{formatTitle(type)}</p>
|
<p className="mr-4 text-3xl font-semibold text-white">{formatTitle(type)}</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="mr-4 mt-2 text-gray-400">{formatDescription(type)}</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-6 flex w-full flex-row">
|
<div className="mt-6 flex w-full flex-row">
|
||||||
<Input
|
<Input
|
||||||
|
|||||||
+8
-3
@@ -5,7 +5,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|||||||
import { format } from "date-fns";
|
import { format } from "date-fns";
|
||||||
|
|
||||||
import { createNotification } from "@app/components/notifications";
|
import { createNotification } from "@app/components/notifications";
|
||||||
import { IconButton, Td, Tooltip, Tr } from "@app/components/v2";
|
import { IconButton, Tag, Td, Tooltip, Tr } from "@app/components/v2";
|
||||||
import { useWorkspace } from "@app/context";
|
import { useWorkspace } from "@app/context";
|
||||||
import { IdentityMembership } from "@app/hooks/api/identities/types";
|
import { IdentityMembership } from "@app/hooks/api/identities/types";
|
||||||
import { ProjectMembershipRole } from "@app/hooks/api/roles/types";
|
import { ProjectMembershipRole } from "@app/hooks/api/roles/types";
|
||||||
@@ -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,currentWorkspace } = useWorkspace();
|
const { workspaces, currentWorkspace } = useWorkspace();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const isAccessible = useMemo(() => {
|
const isAccessible = useMemo(() => {
|
||||||
@@ -52,7 +52,9 @@ export const IdentityProjectRow = ({
|
|||||||
key={`identity-project-membership-${id}`}
|
key={`identity-project-membership-${id}`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (isAccessible) {
|
if (isAccessible) {
|
||||||
router.push(`/${currentWorkspace?.type}/${project.id}/members?selectedTab=${TabSections.Identities}`);
|
router.push(
|
||||||
|
`/${currentWorkspace?.type}/${project.id}/members?selectedTab=${TabSections.Identities}`
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,6 +65,9 @@ export const IdentityProjectRow = ({
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Td className="max-w-0 truncate">{project.name}</Td>
|
<Td className="max-w-0 truncate">{project.name}</Td>
|
||||||
|
<Td>
|
||||||
|
<Tag size="xs">{project.type}</Tag>
|
||||||
|
</Td>
|
||||||
<Td>{`${formatRoleName(roles[0].role, roles[0].customRoleName)}${
|
<Td>{`${formatRoleName(roles[0].role, roles[0].customRoleName)}${
|
||||||
roles.length > 1 ? ` (+${roles.length - 1})` : ""
|
roles.length > 1 ? ` (+${roles.length - 1})` : ""
|
||||||
}`}</Td>
|
}`}</Td>
|
||||||
|
|||||||
+1
@@ -106,6 +106,7 @@ export const IdentityProjectsTable = ({ identityId, handlePopUpOpen }: Props) =>
|
|||||||
</div>
|
</div>
|
||||||
</Th>
|
</Th>
|
||||||
|
|
||||||
|
<Th>Type</Th>
|
||||||
<Th>Role</Th>
|
<Th>Role</Th>
|
||||||
<Th>Added On</Th>
|
<Th>Added On</Th>
|
||||||
<Th className="w-5" />
|
<Th className="w-5" />
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { faTrash } from "@fortawesome/free-solid-svg-icons";
|
|||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
|
||||||
import { createNotification } from "@app/components/notifications";
|
import { createNotification } from "@app/components/notifications";
|
||||||
import { IconButton, Td, Tooltip, Tr } from "@app/components/v2";
|
import { IconButton, Tag, Td, Tooltip, Tr } from "@app/components/v2";
|
||||||
import { useWorkspace } from "@app/context";
|
import { useWorkspace } from "@app/context";
|
||||||
import { ProjectMembershipRole } from "@app/hooks/api/roles/types";
|
import { ProjectMembershipRole } from "@app/hooks/api/roles/types";
|
||||||
import { TWorkspaceUser } from "@app/hooks/api/types";
|
import { TWorkspaceUser } from "@app/hooks/api/types";
|
||||||
@@ -59,6 +59,9 @@ export const UserProjectRow = ({
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Td className="max-w-0 truncate">{project.name}</Td>
|
<Td className="max-w-0 truncate">{project.name}</Td>
|
||||||
|
<Td>
|
||||||
|
<Tag size="xs">{project.type}</Tag>
|
||||||
|
</Td>
|
||||||
<Td>{`${formatRoleName(roles[0].role, roles[0].customRoleName)}${
|
<Td>{`${formatRoleName(roles[0].role, roles[0].customRoleName)}${
|
||||||
roles.length > 1 ? ` (+${roles.length - 1})` : ""
|
roles.length > 1 ? ` (+${roles.length - 1})` : ""
|
||||||
}`}</Td>
|
}`}</Td>
|
||||||
|
|||||||
@@ -108,6 +108,7 @@ export const UserProjectsTable = ({ membershipId, handlePopUpOpen }: Props) => {
|
|||||||
</IconButton>
|
</IconButton>
|
||||||
</div>
|
</div>
|
||||||
</Th>
|
</Th>
|
||||||
|
<Th>Type</Th>
|
||||||
<Th>Role</Th>
|
<Th>Role</Th>
|
||||||
<Th className="w-5" />
|
<Th className="w-5" />
|
||||||
</Tr>
|
</Tr>
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { createNotification } from "@app/components/notifications";
|
|||||||
import { ProjectPermissionCan } from "@app/components/permissions";
|
import { ProjectPermissionCan } from "@app/components/permissions";
|
||||||
import { Button, DeleteActionModal, EmptyState, Spinner } from "@app/components/v2";
|
import { Button, DeleteActionModal, EmptyState, Spinner } from "@app/components/v2";
|
||||||
import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context";
|
import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context";
|
||||||
|
import { getProjectTitle } from "@app/helpers/project";
|
||||||
import { withProjectPermission } from "@app/hoc";
|
import { withProjectPermission } from "@app/hoc";
|
||||||
import { usePopUp } from "@app/hooks";
|
import { usePopUp } from "@app/hooks";
|
||||||
import {
|
import {
|
||||||
@@ -77,11 +78,14 @@ export const IdentityDetailsPage = withProjectPermission(
|
|||||||
type="submit"
|
type="submit"
|
||||||
leftIcon={<FontAwesomeIcon icon={faChevronLeft} />}
|
leftIcon={<FontAwesomeIcon icon={faChevronLeft} />}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
router.push(`/${currentWorkspace?.type}/${workspaceId}/members?selectedTab=identities`);
|
router.push(
|
||||||
|
`/${currentWorkspace?.type}/${workspaceId}/members?selectedTab=identities`
|
||||||
|
);
|
||||||
}}
|
}}
|
||||||
className="mb-4"
|
className="mb-4"
|
||||||
>
|
>
|
||||||
Project Access Control
|
{currentWorkspace?.type ? getProjectTitle(currentWorkspace?.type) : "Project"} Access
|
||||||
|
Access Control
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
{identityMembershipDetails ? (
|
{identityMembershipDetails ? (
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import {
|
|||||||
useOrganization,
|
useOrganization,
|
||||||
useWorkspace
|
useWorkspace
|
||||||
} from "@app/context";
|
} from "@app/context";
|
||||||
|
import { getProjectTitle } from "@app/helpers/project";
|
||||||
import { withProjectPermission } from "@app/hoc";
|
import { withProjectPermission } from "@app/hoc";
|
||||||
import { usePopUp } from "@app/hooks";
|
import { usePopUp } from "@app/hooks";
|
||||||
import { useDeleteUserFromWorkspace, useGetWorkspaceUserDetails } from "@app/hooks/api";
|
import { useDeleteUserFromWorkspace, useGetWorkspaceUserDetails } from "@app/hooks/api";
|
||||||
@@ -89,7 +90,8 @@ export const MemberDetailsPage = withProjectPermission(
|
|||||||
}}
|
}}
|
||||||
className="mb-4"
|
className="mb-4"
|
||||||
>
|
>
|
||||||
Project Access Control
|
{currentWorkspace?.type ? getProjectTitle(currentWorkspace?.type) : "Project"} Access
|
||||||
|
Control
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
{membershipDetails ? (
|
{membershipDetails ? (
|
||||||
|
|||||||
@@ -3,8 +3,10 @@ import { useEffect, useState } from "react";
|
|||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
import { Tab, TabList, TabPanel, Tabs } from "@app/components/v2";
|
import { Tab, TabList, TabPanel, Tabs } from "@app/components/v2";
|
||||||
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/context";
|
import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context";
|
||||||
|
import { getProjectTitle } from "@app/helpers/project";
|
||||||
import { withProjectPermission } from "@app/hoc";
|
import { withProjectPermission } from "@app/hoc";
|
||||||
|
import { ProjectType } from "@app/hooks/api/workspace/types";
|
||||||
|
|
||||||
import { isTabSection, TabSections } from "../Types";
|
import { isTabSection, TabSections } from "../Types";
|
||||||
import {
|
import {
|
||||||
@@ -18,6 +20,7 @@ import {
|
|||||||
export const MembersPage = withProjectPermission(
|
export const MembersPage = withProjectPermission(
|
||||||
() => {
|
() => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
const { currentWorkspace } = useWorkspace();
|
||||||
const { query } = router;
|
const { query } = router;
|
||||||
const selectedTab = query.selectedTab as string;
|
const selectedTab = query.selectedTab as string;
|
||||||
const [activeTab, setActiveTab] = useState<TabSections>(TabSections.Member);
|
const [activeTab, setActiveTab] = useState<TabSections>(TabSections.Member);
|
||||||
@@ -38,7 +41,10 @@ export const MembersPage = withProjectPermission(
|
|||||||
return (
|
return (
|
||||||
<div className="container mx-auto flex flex-col justify-between bg-bunker-800 text-white">
|
<div className="container mx-auto flex flex-col justify-between bg-bunker-800 text-white">
|
||||||
<div className="mx-auto mb-6 w-full max-w-7xl py-6 px-6">
|
<div className="mx-auto mb-6 w-full max-w-7xl py-6 px-6">
|
||||||
<p className="mr-4 mb-4 text-3xl font-semibold text-white">Project Access Control</p>
|
<p className="mr-4 mb-4 text-3xl font-semibold text-white">
|
||||||
|
{currentWorkspace?.type ? getProjectTitle(currentWorkspace?.type) : "Project"} Access
|
||||||
|
Access Control
|
||||||
|
</p>
|
||||||
<Tabs value={activeTab} onValueChange={updateSelectedTab}>
|
<Tabs value={activeTab} onValueChange={updateSelectedTab}>
|
||||||
<TabList>
|
<TabList>
|
||||||
<Tab value={TabSections.Member}>Users</Tab>
|
<Tab value={TabSections.Member}>Users</Tab>
|
||||||
@@ -60,9 +66,11 @@ export const MembersPage = withProjectPermission(
|
|||||||
<TabPanel value={TabSections.Identities}>
|
<TabPanel value={TabSections.Identities}>
|
||||||
<IdentityTab />
|
<IdentityTab />
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
<TabPanel value={TabSections.ServiceTokens}>
|
{currentWorkspace?.type === ProjectType.SecretManager && (
|
||||||
<ServiceTokenTab />
|
<TabPanel value={TabSections.ServiceTokens}>
|
||||||
</TabPanel>
|
<ServiceTokenTab />
|
||||||
|
</TabPanel>
|
||||||
|
)}
|
||||||
<TabPanel value={TabSections.Roles}>
|
<TabPanel value={TabSections.Roles}>
|
||||||
<ProjectRoleListTab />
|
<ProjectRoleListTab />
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
|
|||||||
@@ -23,7 +23,11 @@ export const ProjectSettingsPage = () => {
|
|||||||
currentWorkspace?.type !== ProjectType.SecretManager
|
currentWorkspace?.type !== ProjectType.SecretManager
|
||||||
},
|
},
|
||||||
{ name: "Workflow Integrations", key: "tab-workflow-integrations" },
|
{ name: "Workflow Integrations", key: "tab-workflow-integrations" },
|
||||||
{ name: "Webhooks", key: "tab-project-webhooks" }
|
{
|
||||||
|
name: "Webhooks",
|
||||||
|
key: "tab-project-webhooks",
|
||||||
|
isHidden: currentWorkspace?.type !== ProjectType.SecretManager
|
||||||
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -64,9 +68,11 @@ export const ProjectSettingsPage = () => {
|
|||||||
<Tab.Panel>
|
<Tab.Panel>
|
||||||
<WorkflowIntegrationTab />
|
<WorkflowIntegrationTab />
|
||||||
</Tab.Panel>
|
</Tab.Panel>
|
||||||
<Tab.Panel>
|
{currentWorkspace?.type === ProjectType.SecretManager && (
|
||||||
<WebhooksTab />
|
<Tab.Panel>
|
||||||
</Tab.Panel>
|
<WebhooksTab />
|
||||||
|
</Tab.Panel>
|
||||||
|
)}
|
||||||
</Tab.Panels>
|
</Tab.Panels>
|
||||||
</Tab.Group>
|
</Tab.Group>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user