mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-08 03:27:38 +00:00
feat: backend setup
This commit is contained in:
@@ -22,6 +22,7 @@ import { registerSecretApprovalPolicyRouter } from "./secret-approval-policy-rou
|
|||||||
import { registerSecretApprovalRequestRouter } from "./secret-approval-request-router";
|
import { registerSecretApprovalRequestRouter } from "./secret-approval-request-router";
|
||||||
import { registerSecretRotationProviderRouter } from "./secret-rotation-provider-router";
|
import { registerSecretRotationProviderRouter } from "./secret-rotation-provider-router";
|
||||||
import { registerSecretRotationRouter } from "./secret-rotation-router";
|
import { registerSecretRotationRouter } from "./secret-rotation-router";
|
||||||
|
import { registerSecretRouter } from "./secret-router";
|
||||||
import { registerSecretScanningRouter } from "./secret-scanning-router";
|
import { registerSecretScanningRouter } from "./secret-scanning-router";
|
||||||
import { registerSecretVersionRouter } from "./secret-version-router";
|
import { registerSecretVersionRouter } from "./secret-version-router";
|
||||||
import { registerSnapshotRouter } from "./snapshot-router";
|
import { registerSnapshotRouter } from "./snapshot-router";
|
||||||
@@ -92,6 +93,7 @@ export const registerV1EERoutes = async (server: FastifyZodProvider) => {
|
|||||||
await server.register(registerLdapRouter, { prefix: "/ldap" });
|
await server.register(registerLdapRouter, { prefix: "/ldap" });
|
||||||
await server.register(registerSecretScanningRouter, { prefix: "/secret-scanning" });
|
await server.register(registerSecretScanningRouter, { prefix: "/secret-scanning" });
|
||||||
await server.register(registerSecretRotationRouter, { prefix: "/secret-rotations" });
|
await server.register(registerSecretRotationRouter, { prefix: "/secret-rotations" });
|
||||||
|
await server.register(registerSecretRouter, { prefix: "/secrets" });
|
||||||
await server.register(registerSecretVersionRouter, { prefix: "/secret" });
|
await server.register(registerSecretVersionRouter, { prefix: "/secret" });
|
||||||
await server.register(registerGroupRouter, { prefix: "/groups" });
|
await server.register(registerGroupRouter, { prefix: "/groups" });
|
||||||
await server.register(registerAuditLogStreamRouter, { prefix: "/audit-log-streams" });
|
await server.register(registerAuditLogStreamRouter, { prefix: "/audit-log-streams" });
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
import z from "zod";
|
||||||
|
|
||||||
|
import { ProjectPermissionActions } from "@app/ee/services/permission/project-permission";
|
||||||
|
import { RAW_SECRETS } from "@app/lib/api-docs";
|
||||||
|
import { removeTrailingSlash } from "@app/lib/fn";
|
||||||
|
import { readLimit } from "@app/server/config/rateLimiter";
|
||||||
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
|
import { AuthMode } from "@app/services/auth/auth-type";
|
||||||
|
|
||||||
|
const AccessListEntrySchema = z
|
||||||
|
.object({
|
||||||
|
allowedActions: z.nativeEnum(ProjectPermissionActions).array(),
|
||||||
|
id: z.string(),
|
||||||
|
membershipId: z.string(),
|
||||||
|
name: z.string()
|
||||||
|
})
|
||||||
|
.array();
|
||||||
|
|
||||||
|
export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||||
|
server.route({
|
||||||
|
method: "GET",
|
||||||
|
url: "/raw/:secretName/access-list",
|
||||||
|
config: {
|
||||||
|
rateLimit: readLimit
|
||||||
|
},
|
||||||
|
schema: {
|
||||||
|
description: "Get list of users, machine identities, and groups with access to a secret",
|
||||||
|
security: [
|
||||||
|
{
|
||||||
|
bearerAuth: []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
params: z.object({
|
||||||
|
secretName: z.string().trim().describe(RAW_SECRETS.GET_ACCESS_LIST.secretName)
|
||||||
|
}),
|
||||||
|
querystring: z.object({
|
||||||
|
workspaceId: z.string().trim().describe(RAW_SECRETS.GET_ACCESS_LIST.workspaceId),
|
||||||
|
environment: z.string().trim().describe(RAW_SECRETS.GET_ACCESS_LIST.environment),
|
||||||
|
secretPath: z
|
||||||
|
.string()
|
||||||
|
.trim()
|
||||||
|
.default("/")
|
||||||
|
.transform(removeTrailingSlash)
|
||||||
|
.describe(RAW_SECRETS.GET_ACCESS_LIST.secretPath)
|
||||||
|
}),
|
||||||
|
response: {
|
||||||
|
200: z.object({
|
||||||
|
groups: AccessListEntrySchema,
|
||||||
|
identities: AccessListEntrySchema,
|
||||||
|
users: AccessListEntrySchema
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onRequest: verifyAuth([AuthMode.JWT]),
|
||||||
|
handler: async (req) => {
|
||||||
|
const { secretName } = req.params;
|
||||||
|
const { secretPath, environment, workspaceId: projectId } = req.query;
|
||||||
|
|
||||||
|
return server.services.secret.getSecretAccessList({
|
||||||
|
actorId: req.permission.id,
|
||||||
|
actor: req.permission.type,
|
||||||
|
actorAuthMethod: req.permission.authMethod,
|
||||||
|
actorOrgId: req.permission.orgId,
|
||||||
|
secretPath,
|
||||||
|
environment,
|
||||||
|
projectId,
|
||||||
|
secretName
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -125,6 +125,404 @@ export const permissionDALFactory = (db: TDbClient) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getProjectGroupPermissions = async (projectId: string) => {
|
||||||
|
try {
|
||||||
|
const docs = await db
|
||||||
|
.replicaNode()(TableName.GroupProjectMembership)
|
||||||
|
.join(TableName.Groups, `${TableName.Groups}.id`, `${TableName.GroupProjectMembership}.groupId`)
|
||||||
|
.join(
|
||||||
|
TableName.GroupProjectMembershipRole,
|
||||||
|
`${TableName.GroupProjectMembershipRole}.projectMembershipId`,
|
||||||
|
`${TableName.GroupProjectMembership}.id`
|
||||||
|
)
|
||||||
|
.leftJoin<TProjectRoles>(
|
||||||
|
{ groupCustomRoles: TableName.ProjectRoles },
|
||||||
|
`${TableName.GroupProjectMembershipRole}.customRoleId`,
|
||||||
|
`groupCustomRoles.id`
|
||||||
|
)
|
||||||
|
.where(`${TableName.GroupProjectMembership}.projectId`, "=", projectId)
|
||||||
|
.select(
|
||||||
|
db.ref("id").withSchema(TableName.GroupProjectMembership).as("membershipId"),
|
||||||
|
db.ref("id").withSchema(TableName.Groups).as("groupId"),
|
||||||
|
db.ref("name").withSchema(TableName.Groups).as("groupName"),
|
||||||
|
db.ref("slug").withSchema("groupCustomRoles").as("groupProjectMembershipRoleCustomRoleSlug"),
|
||||||
|
db.ref("permissions").withSchema("groupCustomRoles").as("groupProjectMembershipRolePermission"),
|
||||||
|
db.ref("id").withSchema(TableName.GroupProjectMembershipRole).as("groupProjectMembershipRoleId"),
|
||||||
|
db.ref("role").withSchema(TableName.GroupProjectMembershipRole).as("groupProjectMembershipRole"),
|
||||||
|
db
|
||||||
|
.ref("customRoleId")
|
||||||
|
.withSchema(TableName.GroupProjectMembershipRole)
|
||||||
|
.as("groupProjectMembershipRoleCustomRoleId"),
|
||||||
|
db
|
||||||
|
.ref("isTemporary")
|
||||||
|
.withSchema(TableName.GroupProjectMembershipRole)
|
||||||
|
.as("groupProjectMembershipRoleIsTemporary"),
|
||||||
|
db
|
||||||
|
.ref("temporaryMode")
|
||||||
|
.withSchema(TableName.GroupProjectMembershipRole)
|
||||||
|
.as("groupProjectMembershipRoleTemporaryMode"),
|
||||||
|
db
|
||||||
|
.ref("temporaryRange")
|
||||||
|
.withSchema(TableName.GroupProjectMembershipRole)
|
||||||
|
.as("groupProjectMembershipRoleTemporaryRange"),
|
||||||
|
db
|
||||||
|
.ref("temporaryAccessStartTime")
|
||||||
|
.withSchema(TableName.GroupProjectMembershipRole)
|
||||||
|
.as("groupProjectMembershipRoleTemporaryAccessStartTime"),
|
||||||
|
db
|
||||||
|
.ref("temporaryAccessEndTime")
|
||||||
|
.withSchema(TableName.GroupProjectMembershipRole)
|
||||||
|
.as("groupProjectMembershipRoleTemporaryAccessEndTime")
|
||||||
|
);
|
||||||
|
|
||||||
|
const groupPermissions = sqlNestRelationships({
|
||||||
|
data: docs,
|
||||||
|
key: "groupId",
|
||||||
|
parentMapper: ({ groupId, groupName, membershipId }) => ({
|
||||||
|
groupId,
|
||||||
|
username: groupName,
|
||||||
|
id: membershipId
|
||||||
|
}),
|
||||||
|
childrenMapper: [
|
||||||
|
{
|
||||||
|
key: "groupProjectMembershipRoleId",
|
||||||
|
label: "groupRoles" as const,
|
||||||
|
mapper: ({
|
||||||
|
groupProjectMembershipRoleId,
|
||||||
|
groupProjectMembershipRole,
|
||||||
|
groupProjectMembershipRolePermission,
|
||||||
|
groupProjectMembershipRoleCustomRoleSlug,
|
||||||
|
groupProjectMembershipRoleIsTemporary,
|
||||||
|
groupProjectMembershipRoleTemporaryMode,
|
||||||
|
groupProjectMembershipRoleTemporaryAccessEndTime,
|
||||||
|
groupProjectMembershipRoleTemporaryAccessStartTime,
|
||||||
|
groupProjectMembershipRoleTemporaryRange
|
||||||
|
}) => ({
|
||||||
|
id: groupProjectMembershipRoleId,
|
||||||
|
role: groupProjectMembershipRole,
|
||||||
|
customRoleSlug: groupProjectMembershipRoleCustomRoleSlug,
|
||||||
|
permissions: groupProjectMembershipRolePermission,
|
||||||
|
temporaryRange: groupProjectMembershipRoleTemporaryRange,
|
||||||
|
temporaryMode: groupProjectMembershipRoleTemporaryMode,
|
||||||
|
temporaryAccessStartTime: groupProjectMembershipRoleTemporaryAccessStartTime,
|
||||||
|
temporaryAccessEndTime: groupProjectMembershipRoleTemporaryAccessEndTime,
|
||||||
|
isTemporary: groupProjectMembershipRoleIsTemporary
|
||||||
|
})
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
return groupPermissions
|
||||||
|
.map((groupPermission) => {
|
||||||
|
if (!groupPermission) return undefined;
|
||||||
|
|
||||||
|
const activeGroupRoles =
|
||||||
|
groupPermission?.groupRoles?.filter(
|
||||||
|
({ isTemporary, temporaryAccessEndTime }) =>
|
||||||
|
!isTemporary || (isTemporary && temporaryAccessEndTime && new Date() < temporaryAccessEndTime)
|
||||||
|
) ?? [];
|
||||||
|
|
||||||
|
return {
|
||||||
|
...groupPermission,
|
||||||
|
roles: activeGroupRoles
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.filter((item): item is NonNullable<typeof item> => Boolean(item));
|
||||||
|
} catch (error) {
|
||||||
|
throw new DatabaseError({ error, name: "GetProjectGroupPermissions" });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getProjectUserPermissions = async (projectId: string) => {
|
||||||
|
try {
|
||||||
|
const docs = await db
|
||||||
|
.replicaNode()(TableName.Users)
|
||||||
|
.where("isGhost", "=", false)
|
||||||
|
.leftJoin(TableName.GroupProjectMembership, (queryBuilder) => {
|
||||||
|
void queryBuilder.on(`${TableName.GroupProjectMembership}.projectId`, db.raw("?", [projectId]));
|
||||||
|
})
|
||||||
|
.leftJoin(
|
||||||
|
TableName.GroupProjectMembershipRole,
|
||||||
|
`${TableName.GroupProjectMembershipRole}.projectMembershipId`,
|
||||||
|
`${TableName.GroupProjectMembership}.id`
|
||||||
|
)
|
||||||
|
.leftJoin<TProjectRoles>(
|
||||||
|
{ groupCustomRoles: TableName.ProjectRoles },
|
||||||
|
`${TableName.GroupProjectMembershipRole}.customRoleId`,
|
||||||
|
`groupCustomRoles.id`
|
||||||
|
)
|
||||||
|
.join(TableName.ProjectMembership, (queryBuilder) => {
|
||||||
|
void queryBuilder
|
||||||
|
.on(`${TableName.ProjectMembership}.projectId`, db.raw("?", [projectId]))
|
||||||
|
.andOn(`${TableName.ProjectMembership}.userId`, `${TableName.Users}.id`);
|
||||||
|
})
|
||||||
|
.leftJoin(
|
||||||
|
TableName.ProjectUserMembershipRole,
|
||||||
|
`${TableName.ProjectUserMembershipRole}.projectMembershipId`,
|
||||||
|
`${TableName.ProjectMembership}.id`
|
||||||
|
)
|
||||||
|
.leftJoin(
|
||||||
|
TableName.ProjectRoles,
|
||||||
|
`${TableName.ProjectUserMembershipRole}.customRoleId`,
|
||||||
|
`${TableName.ProjectRoles}.id`
|
||||||
|
)
|
||||||
|
.leftJoin(TableName.ProjectUserAdditionalPrivilege, (queryBuilder) => {
|
||||||
|
void queryBuilder
|
||||||
|
.on(`${TableName.ProjectUserAdditionalPrivilege}.projectId`, db.raw("?", [projectId]))
|
||||||
|
.andOn(`${TableName.ProjectUserAdditionalPrivilege}.userId`, `${TableName.Users}.id`);
|
||||||
|
})
|
||||||
|
.join<TProjects>(TableName.Project, `${TableName.Project}.id`, db.raw("?", [projectId]))
|
||||||
|
.join(TableName.Organization, `${TableName.Project}.orgId`, `${TableName.Organization}.id`)
|
||||||
|
.leftJoin(TableName.IdentityMetadata, (queryBuilder) => {
|
||||||
|
void queryBuilder
|
||||||
|
.on(`${TableName.Users}.id`, `${TableName.IdentityMetadata}.userId`)
|
||||||
|
.andOn(`${TableName.Organization}.id`, `${TableName.IdentityMetadata}.orgId`);
|
||||||
|
})
|
||||||
|
.select(
|
||||||
|
db.ref("id").withSchema(TableName.Users).as("userId"),
|
||||||
|
db.ref("username").withSchema(TableName.Users).as("username"),
|
||||||
|
// groups specific
|
||||||
|
db.ref("id").withSchema(TableName.GroupProjectMembership).as("groupMembershipId"),
|
||||||
|
db.ref("createdAt").withSchema(TableName.GroupProjectMembership).as("groupMembershipCreatedAt"),
|
||||||
|
db.ref("updatedAt").withSchema(TableName.GroupProjectMembership).as("groupMembershipUpdatedAt"),
|
||||||
|
db.ref("slug").withSchema("groupCustomRoles").as("userGroupProjectMembershipRoleCustomRoleSlug"),
|
||||||
|
db.ref("permissions").withSchema("groupCustomRoles").as("userGroupProjectMembershipRolePermission"),
|
||||||
|
db.ref("id").withSchema(TableName.GroupProjectMembershipRole).as("userGroupProjectMembershipRoleId"),
|
||||||
|
db.ref("role").withSchema(TableName.GroupProjectMembershipRole).as("userGroupProjectMembershipRole"),
|
||||||
|
db
|
||||||
|
.ref("customRoleId")
|
||||||
|
.withSchema(TableName.GroupProjectMembershipRole)
|
||||||
|
.as("userGroupProjectMembershipRoleCustomRoleId"),
|
||||||
|
db
|
||||||
|
.ref("isTemporary")
|
||||||
|
.withSchema(TableName.GroupProjectMembershipRole)
|
||||||
|
.as("userGroupProjectMembershipRoleIsTemporary"),
|
||||||
|
db
|
||||||
|
.ref("temporaryMode")
|
||||||
|
.withSchema(TableName.GroupProjectMembershipRole)
|
||||||
|
.as("userGroupProjectMembershipRoleTemporaryMode"),
|
||||||
|
db
|
||||||
|
.ref("temporaryRange")
|
||||||
|
.withSchema(TableName.GroupProjectMembershipRole)
|
||||||
|
.as("userGroupProjectMembershipRoleTemporaryRange"),
|
||||||
|
db
|
||||||
|
.ref("temporaryAccessStartTime")
|
||||||
|
.withSchema(TableName.GroupProjectMembershipRole)
|
||||||
|
.as("userGroupProjectMembershipRoleTemporaryAccessStartTime"),
|
||||||
|
db
|
||||||
|
.ref("temporaryAccessEndTime")
|
||||||
|
.withSchema(TableName.GroupProjectMembershipRole)
|
||||||
|
.as("userGroupProjectMembershipRoleTemporaryAccessEndTime"),
|
||||||
|
// user specific
|
||||||
|
db.ref("id").withSchema(TableName.ProjectMembership).as("membershipId"),
|
||||||
|
db.ref("createdAt").withSchema(TableName.ProjectMembership).as("membershipCreatedAt"),
|
||||||
|
db.ref("updatedAt").withSchema(TableName.ProjectMembership).as("membershipUpdatedAt"),
|
||||||
|
db.ref("slug").withSchema(TableName.ProjectRoles).as("userProjectMembershipRoleCustomRoleSlug"),
|
||||||
|
db.ref("permissions").withSchema(TableName.ProjectRoles).as("userProjectCustomRolePermission"),
|
||||||
|
db.ref("id").withSchema(TableName.ProjectUserMembershipRole).as("userProjectMembershipRoleId"),
|
||||||
|
db.ref("role").withSchema(TableName.ProjectUserMembershipRole).as("userProjectMembershipRole"),
|
||||||
|
db
|
||||||
|
.ref("temporaryMode")
|
||||||
|
.withSchema(TableName.ProjectUserMembershipRole)
|
||||||
|
.as("userProjectMembershipRoleTemporaryMode"),
|
||||||
|
db
|
||||||
|
.ref("isTemporary")
|
||||||
|
.withSchema(TableName.ProjectUserMembershipRole)
|
||||||
|
.as("userProjectMembershipRoleIsTemporary"),
|
||||||
|
db
|
||||||
|
.ref("temporaryRange")
|
||||||
|
.withSchema(TableName.ProjectUserMembershipRole)
|
||||||
|
.as("userProjectMembershipRoleTemporaryRange"),
|
||||||
|
db
|
||||||
|
.ref("temporaryAccessStartTime")
|
||||||
|
.withSchema(TableName.ProjectUserMembershipRole)
|
||||||
|
.as("userProjectMembershipRoleTemporaryAccessStartTime"),
|
||||||
|
db
|
||||||
|
.ref("temporaryAccessEndTime")
|
||||||
|
.withSchema(TableName.ProjectUserMembershipRole)
|
||||||
|
.as("userProjectMembershipRoleTemporaryAccessEndTime"),
|
||||||
|
db.ref("id").withSchema(TableName.ProjectUserAdditionalPrivilege).as("userAdditionalPrivilegesId"),
|
||||||
|
db
|
||||||
|
.ref("permissions")
|
||||||
|
.withSchema(TableName.ProjectUserAdditionalPrivilege)
|
||||||
|
.as("userAdditionalPrivilegesPermissions"),
|
||||||
|
db
|
||||||
|
.ref("temporaryMode")
|
||||||
|
.withSchema(TableName.ProjectUserAdditionalPrivilege)
|
||||||
|
.as("userAdditionalPrivilegesTemporaryMode"),
|
||||||
|
db
|
||||||
|
.ref("isTemporary")
|
||||||
|
.withSchema(TableName.ProjectUserAdditionalPrivilege)
|
||||||
|
.as("userAdditionalPrivilegesIsTemporary"),
|
||||||
|
db
|
||||||
|
.ref("temporaryRange")
|
||||||
|
.withSchema(TableName.ProjectUserAdditionalPrivilege)
|
||||||
|
.as("userAdditionalPrivilegesTemporaryRange"),
|
||||||
|
db.ref("userId").withSchema(TableName.ProjectUserAdditionalPrivilege).as("userAdditionalPrivilegesUserId"),
|
||||||
|
db
|
||||||
|
.ref("temporaryAccessStartTime")
|
||||||
|
.withSchema(TableName.ProjectUserAdditionalPrivilege)
|
||||||
|
.as("userAdditionalPrivilegesTemporaryAccessStartTime"),
|
||||||
|
db
|
||||||
|
.ref("temporaryAccessEndTime")
|
||||||
|
.withSchema(TableName.ProjectUserAdditionalPrivilege)
|
||||||
|
.as("userAdditionalPrivilegesTemporaryAccessEndTime"),
|
||||||
|
// general
|
||||||
|
db.ref("id").withSchema(TableName.IdentityMetadata).as("metadataId"),
|
||||||
|
db.ref("key").withSchema(TableName.IdentityMetadata).as("metadataKey"),
|
||||||
|
db.ref("value").withSchema(TableName.IdentityMetadata).as("metadataValue"),
|
||||||
|
db.ref("authEnforced").withSchema(TableName.Organization).as("orgAuthEnforced"),
|
||||||
|
db.ref("orgId").withSchema(TableName.Project),
|
||||||
|
db.ref("type").withSchema(TableName.Project).as("projectType"),
|
||||||
|
db.ref("id").withSchema(TableName.Project).as("projectId")
|
||||||
|
);
|
||||||
|
|
||||||
|
const userPermissions = sqlNestRelationships({
|
||||||
|
data: docs,
|
||||||
|
key: "userId",
|
||||||
|
parentMapper: ({
|
||||||
|
orgId,
|
||||||
|
username,
|
||||||
|
orgAuthEnforced,
|
||||||
|
membershipId,
|
||||||
|
groupMembershipId,
|
||||||
|
membershipCreatedAt,
|
||||||
|
groupMembershipCreatedAt,
|
||||||
|
groupMembershipUpdatedAt,
|
||||||
|
membershipUpdatedAt,
|
||||||
|
projectType,
|
||||||
|
userId
|
||||||
|
}) => ({
|
||||||
|
orgId,
|
||||||
|
orgAuthEnforced,
|
||||||
|
userId,
|
||||||
|
projectId,
|
||||||
|
username,
|
||||||
|
projectType,
|
||||||
|
id: membershipId || groupMembershipId,
|
||||||
|
createdAt: membershipCreatedAt || groupMembershipCreatedAt,
|
||||||
|
updatedAt: membershipUpdatedAt || groupMembershipUpdatedAt
|
||||||
|
}),
|
||||||
|
childrenMapper: [
|
||||||
|
{
|
||||||
|
key: "userGroupProjectMembershipRoleId",
|
||||||
|
label: "userGroupRoles" as const,
|
||||||
|
mapper: ({
|
||||||
|
userGroupProjectMembershipRoleId,
|
||||||
|
userGroupProjectMembershipRole,
|
||||||
|
userGroupProjectMembershipRolePermission,
|
||||||
|
userGroupProjectMembershipRoleCustomRoleSlug,
|
||||||
|
userGroupProjectMembershipRoleIsTemporary,
|
||||||
|
userGroupProjectMembershipRoleTemporaryMode,
|
||||||
|
userGroupProjectMembershipRoleTemporaryAccessEndTime,
|
||||||
|
userGroupProjectMembershipRoleTemporaryAccessStartTime,
|
||||||
|
userGroupProjectMembershipRoleTemporaryRange
|
||||||
|
}) => ({
|
||||||
|
id: userGroupProjectMembershipRoleId,
|
||||||
|
role: userGroupProjectMembershipRole,
|
||||||
|
customRoleSlug: userGroupProjectMembershipRoleCustomRoleSlug,
|
||||||
|
permissions: userGroupProjectMembershipRolePermission,
|
||||||
|
temporaryRange: userGroupProjectMembershipRoleTemporaryRange,
|
||||||
|
temporaryMode: userGroupProjectMembershipRoleTemporaryMode,
|
||||||
|
temporaryAccessStartTime: userGroupProjectMembershipRoleTemporaryAccessStartTime,
|
||||||
|
temporaryAccessEndTime: userGroupProjectMembershipRoleTemporaryAccessEndTime,
|
||||||
|
isTemporary: userGroupProjectMembershipRoleIsTemporary
|
||||||
|
})
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "userProjectMembershipRoleId",
|
||||||
|
label: "projectMembershipRoles" as const,
|
||||||
|
mapper: ({
|
||||||
|
userProjectMembershipRoleId,
|
||||||
|
userProjectMembershipRole,
|
||||||
|
userProjectCustomRolePermission,
|
||||||
|
userProjectMembershipRoleIsTemporary,
|
||||||
|
userProjectMembershipRoleTemporaryMode,
|
||||||
|
userProjectMembershipRoleTemporaryRange,
|
||||||
|
userProjectMembershipRoleTemporaryAccessEndTime,
|
||||||
|
userProjectMembershipRoleTemporaryAccessStartTime,
|
||||||
|
userProjectMembershipRoleCustomRoleSlug
|
||||||
|
}) => ({
|
||||||
|
id: userProjectMembershipRoleId,
|
||||||
|
role: userProjectMembershipRole,
|
||||||
|
customRoleSlug: userProjectMembershipRoleCustomRoleSlug,
|
||||||
|
permissions: userProjectCustomRolePermission,
|
||||||
|
temporaryRange: userProjectMembershipRoleTemporaryRange,
|
||||||
|
temporaryMode: userProjectMembershipRoleTemporaryMode,
|
||||||
|
temporaryAccessStartTime: userProjectMembershipRoleTemporaryAccessStartTime,
|
||||||
|
temporaryAccessEndTime: userProjectMembershipRoleTemporaryAccessEndTime,
|
||||||
|
isTemporary: userProjectMembershipRoleIsTemporary
|
||||||
|
})
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "userAdditionalPrivilegesId",
|
||||||
|
label: "additionalPrivileges" as const,
|
||||||
|
mapper: ({
|
||||||
|
userAdditionalPrivilegesId,
|
||||||
|
userAdditionalPrivilegesPermissions,
|
||||||
|
userAdditionalPrivilegesIsTemporary,
|
||||||
|
userAdditionalPrivilegesTemporaryMode,
|
||||||
|
userAdditionalPrivilegesTemporaryRange,
|
||||||
|
userAdditionalPrivilegesTemporaryAccessEndTime,
|
||||||
|
userAdditionalPrivilegesTemporaryAccessStartTime
|
||||||
|
}) => ({
|
||||||
|
id: userAdditionalPrivilegesId,
|
||||||
|
permissions: userAdditionalPrivilegesPermissions,
|
||||||
|
temporaryRange: userAdditionalPrivilegesTemporaryRange,
|
||||||
|
temporaryMode: userAdditionalPrivilegesTemporaryMode,
|
||||||
|
temporaryAccessStartTime: userAdditionalPrivilegesTemporaryAccessStartTime,
|
||||||
|
temporaryAccessEndTime: userAdditionalPrivilegesTemporaryAccessEndTime,
|
||||||
|
isTemporary: userAdditionalPrivilegesIsTemporary
|
||||||
|
})
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "metadataId",
|
||||||
|
label: "metadata" as const,
|
||||||
|
mapper: ({ metadataKey, metadataValue, metadataId }) => ({
|
||||||
|
id: metadataId,
|
||||||
|
key: metadataKey,
|
||||||
|
value: metadataValue
|
||||||
|
})
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
return userPermissions
|
||||||
|
.map((userPermission) => {
|
||||||
|
if (!userPermission) return undefined;
|
||||||
|
if (!userPermission?.userGroupRoles?.[0] && !userPermission?.projectMembershipRoles?.[0]) return undefined;
|
||||||
|
|
||||||
|
// when introducting cron mode change it here
|
||||||
|
const activeRoles =
|
||||||
|
userPermission?.projectMembershipRoles?.filter(
|
||||||
|
({ isTemporary, temporaryAccessEndTime }) =>
|
||||||
|
!isTemporary || (isTemporary && temporaryAccessEndTime && new Date() < temporaryAccessEndTime)
|
||||||
|
) ?? [];
|
||||||
|
|
||||||
|
const activeGroupRoles =
|
||||||
|
userPermission?.userGroupRoles?.filter(
|
||||||
|
({ isTemporary, temporaryAccessEndTime }) =>
|
||||||
|
!isTemporary || (isTemporary && temporaryAccessEndTime && new Date() < temporaryAccessEndTime)
|
||||||
|
) ?? [];
|
||||||
|
|
||||||
|
const activeAdditionalPrivileges =
|
||||||
|
userPermission?.additionalPrivileges?.filter(
|
||||||
|
({ isTemporary, temporaryAccessEndTime }) =>
|
||||||
|
!isTemporary || (isTemporary && temporaryAccessEndTime && new Date() < temporaryAccessEndTime)
|
||||||
|
) ?? [];
|
||||||
|
|
||||||
|
return {
|
||||||
|
...userPermission,
|
||||||
|
roles: [...activeRoles, ...activeGroupRoles],
|
||||||
|
additionalPrivileges: activeAdditionalPrivileges
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.filter((item): item is NonNullable<typeof item> => Boolean(item));
|
||||||
|
} catch (error) {
|
||||||
|
throw new DatabaseError({ error, name: "GetProjectUserPermissions" });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const getProjectPermission = async (userId: string, projectId: string) => {
|
const getProjectPermission = async (userId: string, projectId: string) => {
|
||||||
try {
|
try {
|
||||||
const subQueryUserGroups = db(TableName.UserGroupMembership).where("userId", userId).select("groupId");
|
const subQueryUserGroups = db(TableName.UserGroupMembership).where("userId", userId).select("groupId");
|
||||||
@@ -414,6 +812,163 @@ export const permissionDALFactory = (db: TDbClient) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getProjectIdentityPermissions = async (projectId: string) => {
|
||||||
|
try {
|
||||||
|
const docs = await db
|
||||||
|
.replicaNode()(TableName.IdentityProjectMembership)
|
||||||
|
.join(
|
||||||
|
TableName.IdentityProjectMembershipRole,
|
||||||
|
`${TableName.IdentityProjectMembershipRole}.projectMembershipId`,
|
||||||
|
`${TableName.IdentityProjectMembership}.id`
|
||||||
|
)
|
||||||
|
.join(TableName.Identity, `${TableName.Identity}.id`, `${TableName.IdentityProjectMembership}.identityId`)
|
||||||
|
.leftJoin(
|
||||||
|
TableName.ProjectRoles,
|
||||||
|
`${TableName.IdentityProjectMembershipRole}.customRoleId`,
|
||||||
|
`${TableName.ProjectRoles}.id`
|
||||||
|
)
|
||||||
|
.leftJoin(
|
||||||
|
TableName.IdentityProjectAdditionalPrivilege,
|
||||||
|
`${TableName.IdentityProjectAdditionalPrivilege}.projectMembershipId`,
|
||||||
|
`${TableName.IdentityProjectMembership}.id`
|
||||||
|
)
|
||||||
|
.join(
|
||||||
|
// Join the Project table to later select orgId
|
||||||
|
TableName.Project,
|
||||||
|
`${TableName.IdentityProjectMembership}.projectId`,
|
||||||
|
`${TableName.Project}.id`
|
||||||
|
)
|
||||||
|
.leftJoin(TableName.IdentityMetadata, (queryBuilder) => {
|
||||||
|
void queryBuilder
|
||||||
|
.on(`${TableName.Identity}.id`, `${TableName.IdentityMetadata}.identityId`)
|
||||||
|
.andOn(`${TableName.Project}.orgId`, `${TableName.IdentityMetadata}.orgId`);
|
||||||
|
})
|
||||||
|
.where(`${TableName.IdentityProjectMembership}.projectId`, projectId)
|
||||||
|
.select(selectAllTableCols(TableName.IdentityProjectMembershipRole))
|
||||||
|
.select(
|
||||||
|
db.ref("id").withSchema(TableName.IdentityProjectMembership).as("membershipId"),
|
||||||
|
db.ref("id").withSchema(TableName.Identity).as("identityId"),
|
||||||
|
db.ref("name").withSchema(TableName.Identity).as("identityName"),
|
||||||
|
db.ref("orgId").withSchema(TableName.Project).as("orgId"), // Now you can select orgId from Project
|
||||||
|
db.ref("type").withSchema(TableName.Project).as("projectType"),
|
||||||
|
db.ref("createdAt").withSchema(TableName.IdentityProjectMembership).as("membershipCreatedAt"),
|
||||||
|
db.ref("updatedAt").withSchema(TableName.IdentityProjectMembership).as("membershipUpdatedAt"),
|
||||||
|
db.ref("slug").withSchema(TableName.ProjectRoles).as("customRoleSlug"),
|
||||||
|
db.ref("permissions").withSchema(TableName.ProjectRoles),
|
||||||
|
db.ref("id").withSchema(TableName.IdentityProjectAdditionalPrivilege).as("identityApId"),
|
||||||
|
db.ref("permissions").withSchema(TableName.IdentityProjectAdditionalPrivilege).as("identityApPermissions"),
|
||||||
|
db
|
||||||
|
.ref("temporaryMode")
|
||||||
|
.withSchema(TableName.IdentityProjectAdditionalPrivilege)
|
||||||
|
.as("identityApTemporaryMode"),
|
||||||
|
db.ref("isTemporary").withSchema(TableName.IdentityProjectAdditionalPrivilege).as("identityApIsTemporary"),
|
||||||
|
db
|
||||||
|
.ref("temporaryRange")
|
||||||
|
.withSchema(TableName.IdentityProjectAdditionalPrivilege)
|
||||||
|
.as("identityApTemporaryRange"),
|
||||||
|
db
|
||||||
|
.ref("temporaryAccessStartTime")
|
||||||
|
.withSchema(TableName.IdentityProjectAdditionalPrivilege)
|
||||||
|
.as("identityApTemporaryAccessStartTime"),
|
||||||
|
db
|
||||||
|
.ref("temporaryAccessEndTime")
|
||||||
|
.withSchema(TableName.IdentityProjectAdditionalPrivilege)
|
||||||
|
.as("identityApTemporaryAccessEndTime"),
|
||||||
|
db.ref("id").withSchema(TableName.IdentityMetadata).as("metadataId"),
|
||||||
|
db.ref("key").withSchema(TableName.IdentityMetadata).as("metadataKey"),
|
||||||
|
db.ref("value").withSchema(TableName.IdentityMetadata).as("metadataValue")
|
||||||
|
);
|
||||||
|
|
||||||
|
const permissions = sqlNestRelationships({
|
||||||
|
data: docs,
|
||||||
|
key: "identityId",
|
||||||
|
parentMapper: ({
|
||||||
|
membershipId,
|
||||||
|
membershipCreatedAt,
|
||||||
|
membershipUpdatedAt,
|
||||||
|
orgId,
|
||||||
|
identityName,
|
||||||
|
projectType,
|
||||||
|
identityId
|
||||||
|
}) => ({
|
||||||
|
id: membershipId,
|
||||||
|
identityId,
|
||||||
|
username: identityName,
|
||||||
|
projectId,
|
||||||
|
createdAt: membershipCreatedAt,
|
||||||
|
updatedAt: membershipUpdatedAt,
|
||||||
|
orgId,
|
||||||
|
projectType,
|
||||||
|
// just a prefilled value
|
||||||
|
orgAuthEnforced: false
|
||||||
|
}),
|
||||||
|
childrenMapper: [
|
||||||
|
{
|
||||||
|
key: "id",
|
||||||
|
label: "roles" as const,
|
||||||
|
mapper: (data) =>
|
||||||
|
IdentityProjectMembershipRoleSchema.extend({
|
||||||
|
permissions: z.unknown(),
|
||||||
|
customRoleSlug: z.string().optional().nullable()
|
||||||
|
}).parse(data)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "identityApId",
|
||||||
|
label: "additionalPrivileges" as const,
|
||||||
|
mapper: ({
|
||||||
|
identityApId,
|
||||||
|
identityApPermissions,
|
||||||
|
identityApIsTemporary,
|
||||||
|
identityApTemporaryMode,
|
||||||
|
identityApTemporaryRange,
|
||||||
|
identityApTemporaryAccessEndTime,
|
||||||
|
identityApTemporaryAccessStartTime
|
||||||
|
}) => ({
|
||||||
|
id: identityApId,
|
||||||
|
permissions: identityApPermissions,
|
||||||
|
temporaryRange: identityApTemporaryRange,
|
||||||
|
temporaryMode: identityApTemporaryMode,
|
||||||
|
temporaryAccessEndTime: identityApTemporaryAccessEndTime,
|
||||||
|
temporaryAccessStartTime: identityApTemporaryAccessStartTime,
|
||||||
|
isTemporary: identityApIsTemporary
|
||||||
|
})
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "metadataId",
|
||||||
|
label: "metadata" as const,
|
||||||
|
mapper: ({ metadataKey, metadataValue, metadataId }) => ({
|
||||||
|
id: metadataId,
|
||||||
|
key: metadataKey,
|
||||||
|
value: metadataValue
|
||||||
|
})
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
return permissions
|
||||||
|
.map((permission) => {
|
||||||
|
if (!permission) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
// when introducting cron mode change it here
|
||||||
|
const activeRoles = permission?.roles.filter(
|
||||||
|
({ isTemporary, temporaryAccessEndTime }) =>
|
||||||
|
!isTemporary || (isTemporary && temporaryAccessEndTime && new Date() < temporaryAccessEndTime)
|
||||||
|
);
|
||||||
|
const activeAdditionalPrivileges = permission?.additionalPrivileges?.filter(
|
||||||
|
({ isTemporary, temporaryAccessEndTime }) =>
|
||||||
|
!isTemporary || (isTemporary && temporaryAccessEndTime && new Date() < temporaryAccessEndTime)
|
||||||
|
);
|
||||||
|
|
||||||
|
return { ...permission, roles: activeRoles, additionalPrivileges: activeAdditionalPrivileges };
|
||||||
|
})
|
||||||
|
.filter((item): item is NonNullable<typeof item> => Boolean(item));
|
||||||
|
} catch (error) {
|
||||||
|
throw new DatabaseError({ error, name: "GetProjectIdentityPermissions" });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const getProjectIdentityPermission = async (identityId: string, projectId: string) => {
|
const getProjectIdentityPermission = async (identityId: string, projectId: string) => {
|
||||||
try {
|
try {
|
||||||
const docs = await db
|
const docs = await db
|
||||||
@@ -568,6 +1123,9 @@ export const permissionDALFactory = (db: TDbClient) => {
|
|||||||
getOrgPermission,
|
getOrgPermission,
|
||||||
getOrgIdentityPermission,
|
getOrgIdentityPermission,
|
||||||
getProjectPermission,
|
getProjectPermission,
|
||||||
getProjectIdentityPermission
|
getProjectIdentityPermission,
|
||||||
|
getProjectUserPermissions,
|
||||||
|
getProjectIdentityPermissions,
|
||||||
|
getProjectGroupPermissions
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -405,6 +405,126 @@ export const permissionServiceFactory = ({
|
|||||||
ForbidOnInvalidProjectType: (type: ProjectType) => void;
|
ForbidOnInvalidProjectType: (type: ProjectType) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getProjectPermissions = async (projectId: string) => {
|
||||||
|
// fetch user permissions
|
||||||
|
const rawUserProjectPermissions = await permissionDAL.getProjectUserPermissions(projectId);
|
||||||
|
const userPermissions = rawUserProjectPermissions.map((userProjectPermission) => {
|
||||||
|
const rolePermissions =
|
||||||
|
userProjectPermission.roles?.map(({ role, permissions }) => ({ role, permissions })) || [];
|
||||||
|
const additionalPrivileges =
|
||||||
|
userProjectPermission.additionalPrivileges?.map(({ permissions }) => ({
|
||||||
|
role: ProjectMembershipRole.Custom,
|
||||||
|
permissions
|
||||||
|
})) || [];
|
||||||
|
|
||||||
|
const rules = buildProjectPermissionRules(rolePermissions.concat(additionalPrivileges));
|
||||||
|
const templatedRules = handlebars.compile(JSON.stringify(rules), { data: false });
|
||||||
|
const metadataKeyValuePair = escapeHandlebarsMissingMetadata(
|
||||||
|
objectify(
|
||||||
|
userProjectPermission.metadata,
|
||||||
|
(i) => i.key,
|
||||||
|
(i) => i.value
|
||||||
|
)
|
||||||
|
);
|
||||||
|
const interpolateRules = templatedRules(
|
||||||
|
{
|
||||||
|
identity: {
|
||||||
|
id: userProjectPermission.userId,
|
||||||
|
username: userProjectPermission.username,
|
||||||
|
metadata: metadataKeyValuePair
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ data: false }
|
||||||
|
);
|
||||||
|
const permission = createMongoAbility<ProjectPermissionSet>(
|
||||||
|
JSON.parse(interpolateRules) as RawRuleOf<MongoAbility<ProjectPermissionSet>>[],
|
||||||
|
{
|
||||||
|
conditionsMatcher
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
permission,
|
||||||
|
id: userProjectPermission.userId,
|
||||||
|
name: userProjectPermission.username,
|
||||||
|
membershipId: userProjectPermission.id
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// fetch identity permissions
|
||||||
|
const rawIdentityProjectPermissions = await permissionDAL.getProjectIdentityPermissions(projectId);
|
||||||
|
const identityPermissions = rawIdentityProjectPermissions.map((identityProjectPermission) => {
|
||||||
|
const rolePermissions =
|
||||||
|
identityProjectPermission.roles?.map(({ role, permissions }) => ({ role, permissions })) || [];
|
||||||
|
const additionalPrivileges =
|
||||||
|
identityProjectPermission.additionalPrivileges?.map(({ permissions }) => ({
|
||||||
|
role: ProjectMembershipRole.Custom,
|
||||||
|
permissions
|
||||||
|
})) || [];
|
||||||
|
|
||||||
|
const rules = buildProjectPermissionRules(rolePermissions.concat(additionalPrivileges));
|
||||||
|
const templatedRules = handlebars.compile(JSON.stringify(rules), { data: false });
|
||||||
|
const metadataKeyValuePair = escapeHandlebarsMissingMetadata(
|
||||||
|
objectify(
|
||||||
|
identityProjectPermission.metadata,
|
||||||
|
(i) => i.key,
|
||||||
|
(i) => i.value
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
const interpolateRules = templatedRules(
|
||||||
|
{
|
||||||
|
identity: {
|
||||||
|
id: identityProjectPermission.identityId,
|
||||||
|
username: identityProjectPermission.username,
|
||||||
|
metadata: metadataKeyValuePair
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ data: false }
|
||||||
|
);
|
||||||
|
const permission = createMongoAbility<ProjectPermissionSet>(
|
||||||
|
JSON.parse(interpolateRules) as RawRuleOf<MongoAbility<ProjectPermissionSet>>[],
|
||||||
|
{
|
||||||
|
conditionsMatcher
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
permission,
|
||||||
|
id: identityProjectPermission.identityId,
|
||||||
|
name: identityProjectPermission.username,
|
||||||
|
membershipId: identityProjectPermission.id
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// fetch group permissions
|
||||||
|
const rawGroupProjectPermissions = await permissionDAL.getProjectGroupPermissions(projectId);
|
||||||
|
const groupPermissions = rawGroupProjectPermissions.map((groupProjectPermission) => {
|
||||||
|
const rolePermissions =
|
||||||
|
groupProjectPermission.roles?.map(({ role, permissions }) => ({ role, permissions })) || [];
|
||||||
|
const rules = buildProjectPermissionRules(rolePermissions);
|
||||||
|
const permission = createMongoAbility<ProjectPermissionSet>(
|
||||||
|
rules as RawRuleOf<MongoAbility<ProjectPermissionSet>>[],
|
||||||
|
{
|
||||||
|
conditionsMatcher
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
permission,
|
||||||
|
id: groupProjectPermission.groupId,
|
||||||
|
name: groupProjectPermission.username,
|
||||||
|
membershipId: groupProjectPermission.id
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
userPermissions,
|
||||||
|
identityPermissions,
|
||||||
|
groupPermissions
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
const getProjectPermission = async <T extends ActorType>(
|
const getProjectPermission = async <T extends ActorType>(
|
||||||
type: T,
|
type: T,
|
||||||
id: string,
|
id: string,
|
||||||
@@ -455,6 +575,7 @@ export const permissionServiceFactory = ({
|
|||||||
getOrgPermission,
|
getOrgPermission,
|
||||||
getUserProjectPermission,
|
getUserProjectPermission,
|
||||||
getProjectPermission,
|
getProjectPermission,
|
||||||
|
getProjectPermissions,
|
||||||
getOrgPermissionByRole,
|
getOrgPermissionByRole,
|
||||||
getProjectPermissionByRole,
|
getProjectPermissionByRole,
|
||||||
buildOrgPermission,
|
buildOrgPermission,
|
||||||
|
|||||||
@@ -741,6 +741,12 @@ export const RAW_SECRETS = {
|
|||||||
workspaceId: "The ID of the project where the secret is located.",
|
workspaceId: "The ID of the project where the secret is located.",
|
||||||
environment: "The slug of the environment where the the secret is located.",
|
environment: "The slug of the environment where the the secret is located.",
|
||||||
secretPath: "The folder path where the secret is located."
|
secretPath: "The folder path where the secret is located."
|
||||||
|
},
|
||||||
|
GET_ACCESS_LIST: {
|
||||||
|
secretName: "The name of the secret to get the access list for.",
|
||||||
|
workspaceId: "The ID of the project where the secret is located.",
|
||||||
|
environment: "The slug of the environment where the the secret is located.",
|
||||||
|
secretPath: "The folder path where the secret is located."
|
||||||
}
|
}
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ import {
|
|||||||
TDeleteSecretRawDTO,
|
TDeleteSecretRawDTO,
|
||||||
TGetASecretDTO,
|
TGetASecretDTO,
|
||||||
TGetASecretRawDTO,
|
TGetASecretRawDTO,
|
||||||
|
TGetSecretAccessListDTO,
|
||||||
TGetSecretsDTO,
|
TGetSecretsDTO,
|
||||||
TGetSecretsRawDTO,
|
TGetSecretsRawDTO,
|
||||||
TGetSecretVersionsDTO,
|
TGetSecretVersionsDTO,
|
||||||
@@ -94,7 +95,7 @@ type TSecretServiceFactoryDep = {
|
|||||||
>;
|
>;
|
||||||
secretV2BridgeService: TSecretV2BridgeServiceFactory;
|
secretV2BridgeService: TSecretV2BridgeServiceFactory;
|
||||||
secretBlindIndexDAL: TSecretBlindIndexDALFactory;
|
secretBlindIndexDAL: TSecretBlindIndexDALFactory;
|
||||||
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">;
|
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission" | "getProjectPermissions">;
|
||||||
snapshotService: Pick<TSecretSnapshotServiceFactory, "performSnapshot">;
|
snapshotService: Pick<TSecretSnapshotServiceFactory, "performSnapshot">;
|
||||||
secretQueueService: Pick<
|
secretQueueService: Pick<
|
||||||
TSecretQueueFactory,
|
TSecretQueueFactory,
|
||||||
@@ -1147,6 +1148,64 @@ export const secretServiceFactory = ({
|
|||||||
return secretV2BridgeService.getSecretReferenceTree(dto);
|
return secretV2BridgeService.getSecretReferenceTree(dto);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getSecretAccessList = async (dto: TGetSecretAccessListDTO) => {
|
||||||
|
const { environment, secretPath, secretName, projectId } = dto;
|
||||||
|
const secret = await secretV2BridgeService.getSecretByName({
|
||||||
|
actor: dto.actor,
|
||||||
|
actorId: dto.actorId,
|
||||||
|
actorOrgId: dto.actorOrgId,
|
||||||
|
actorAuthMethod: dto.actorAuthMethod,
|
||||||
|
projectId,
|
||||||
|
secretName,
|
||||||
|
path: secretPath,
|
||||||
|
environment,
|
||||||
|
type: "shared"
|
||||||
|
});
|
||||||
|
|
||||||
|
const { userPermissions, identityPermissions, groupPermissions } = await permissionService.getProjectPermissions(
|
||||||
|
dto.projectId
|
||||||
|
);
|
||||||
|
|
||||||
|
const attachAllowedActions = (
|
||||||
|
entityPermission:
|
||||||
|
| (typeof userPermissions)[number]
|
||||||
|
| (typeof identityPermissions)[number]
|
||||||
|
| (typeof groupPermissions)[number]
|
||||||
|
) => {
|
||||||
|
const allowedActions = [
|
||||||
|
ProjectPermissionActions.Read,
|
||||||
|
ProjectPermissionActions.Delete,
|
||||||
|
ProjectPermissionActions.Create,
|
||||||
|
ProjectPermissionActions.Edit
|
||||||
|
].filter((action) =>
|
||||||
|
entityPermission.permission.can(
|
||||||
|
action,
|
||||||
|
subject(ProjectPermissionSub.Secrets, {
|
||||||
|
environment,
|
||||||
|
secretPath,
|
||||||
|
secretName,
|
||||||
|
secretTags: secret?.tags?.map((el) => el.slug)
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
...entityPermission,
|
||||||
|
allowedActions
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const usersWithAccess = userPermissions.map(attachAllowedActions).filter((user) => user.allowedActions.length > 0);
|
||||||
|
const identitiesWithAccess = identityPermissions
|
||||||
|
.map(attachAllowedActions)
|
||||||
|
.filter((identity) => identity.allowedActions.length > 0);
|
||||||
|
const groupsWithAccess = groupPermissions
|
||||||
|
.map(attachAllowedActions)
|
||||||
|
.filter((group) => group.allowedActions.length > 0);
|
||||||
|
|
||||||
|
return { users: usersWithAccess, identities: identitiesWithAccess, groups: groupsWithAccess };
|
||||||
|
};
|
||||||
|
|
||||||
const getSecretsRaw = async ({
|
const getSecretsRaw = async ({
|
||||||
projectId,
|
projectId,
|
||||||
path,
|
path,
|
||||||
@@ -2928,6 +2987,7 @@ export const secretServiceFactory = ({
|
|||||||
getSecretsCountMultiEnv,
|
getSecretsCountMultiEnv,
|
||||||
getSecretsRawMultiEnv,
|
getSecretsRawMultiEnv,
|
||||||
getSecretReferenceTree,
|
getSecretReferenceTree,
|
||||||
getSecretsRawByFolderMappings
|
getSecretsRawByFolderMappings,
|
||||||
|
getSecretAccessList
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -188,6 +188,12 @@ export type TGetSecretsRawDTO = {
|
|||||||
keys?: string[];
|
keys?: string[];
|
||||||
} & TProjectPermission;
|
} & TProjectPermission;
|
||||||
|
|
||||||
|
export type TGetSecretAccessListDTO = {
|
||||||
|
environment: string;
|
||||||
|
secretPath: string;
|
||||||
|
secretName: string;
|
||||||
|
} & TProjectPermission;
|
||||||
|
|
||||||
export type TGetASecretRawDTO = {
|
export type TGetASecretRawDTO = {
|
||||||
secretName: string;
|
secretName: string;
|
||||||
path: string;
|
path: string;
|
||||||
|
|||||||
Reference in New Issue
Block a user