mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
feat: battle of ts - unlimited edition
This commit is contained in:
@@ -37,7 +37,7 @@ export async function up(knex: Knex): Promise<void> {
|
||||
t.foreign("scopeNamespaceId").references("id").inTable(TableName.Namespace).onDelete("CASCADE");
|
||||
|
||||
t.boolean("isActive").defaultTo(true).notNullable();
|
||||
t.string("status").defaultTo("invited");
|
||||
t.string("status").defaultTo("invited").notNullable();
|
||||
t.string("inviteEmail");
|
||||
t.datetime("lastInvitedAt");
|
||||
t.string("lastLoginAuthMethod");
|
||||
@@ -139,8 +139,40 @@ export async function up(knex: Knex): Promise<void> {
|
||||
t.datetime("temporaryAccessEndTime");
|
||||
t.jsonb("permissions").notNullable();
|
||||
|
||||
t.uuid("membershipId").notNullable();
|
||||
t.foreign("membershipId").references("id").inTable(TableName.Membership).onDelete("CASCADE");
|
||||
t.uuid("actorUserId");
|
||||
t.foreign("actorUserId").references("id").inTable(TableName.Users).onDelete("CASCADE");
|
||||
t.uuid("actorIdentityId");
|
||||
t.foreign("actorIdentityId").references("id").inTable(TableName.Identity).onDelete("CASCADE");
|
||||
|
||||
t.uuid("orgId");
|
||||
t.foreign("orgId").references("id").inTable(TableName.Organization).onDelete("CASCADE");
|
||||
t.string("projectId", 36);
|
||||
t.foreign("projectId").references("id").inTable(TableName.Project).onDelete("CASCADE");
|
||||
t.uuid("namespaceId");
|
||||
t.foreign("namespaceId").references("id").inTable(TableName.Namespace).onDelete("CASCADE");
|
||||
|
||||
t.check(
|
||||
`(:orgIdColumn: IS NOT NULL AND :namespaceIdColumn: IS NULL AND :projectIdColumn: IS NULL) OR
|
||||
(:namespaceIdColumn: IS NOT NULL AND :orgIdColumn: IS NULL AND :projectIdColumn: IS NULL) OR
|
||||
(:projectIdColumn: IS NOT NULL AND :orgIdColumn: IS NULL AND :namespaceIdColumn: IS NULL)`,
|
||||
{
|
||||
orgIdColumn: "orgId",
|
||||
namespaceIdColumn: "namespaceId",
|
||||
projectIdColumn: "projectId"
|
||||
},
|
||||
"only_one_scope_id"
|
||||
);
|
||||
|
||||
t.check(
|
||||
`(:actorUserIdColumn: IS NOT NULL AND :actorIdentityIdColumn: IS NULL) OR
|
||||
(:actorIdentityIdColumn: IS NOT NULL AND :actorUserIdColumn: IS NULL)
|
||||
`,
|
||||
{
|
||||
actorUserIdColumn: "actorUserId",
|
||||
actorIdentityIdColumn: "actorIdentityId"
|
||||
},
|
||||
"only_one_actor_type"
|
||||
);
|
||||
t.timestamps(true, true, true);
|
||||
});
|
||||
|
||||
|
||||
@@ -16,7 +16,11 @@ export const AdditionalPrivilegesSchema = z.object({
|
||||
temporaryAccessStartTime: z.date().nullable().optional(),
|
||||
temporaryAccessEndTime: z.date().nullable().optional(),
|
||||
permissions: z.unknown(),
|
||||
membershipId: z.string().uuid(),
|
||||
actorUserId: z.string().uuid().nullable().optional(),
|
||||
actorIdentityId: z.string().uuid().nullable().optional(),
|
||||
orgId: z.string().uuid().nullable().optional(),
|
||||
projectId: z.string().nullable().optional(),
|
||||
namespaceId: z.string().uuid().nullable().optional(),
|
||||
createdAt: z.date(),
|
||||
updatedAt: z.date()
|
||||
});
|
||||
|
||||
@@ -17,7 +17,7 @@ export const MembershipsSchema = z.object({
|
||||
scopeProjectId: z.string().nullable().optional(),
|
||||
scopeNamespaceId: z.string().uuid().nullable().optional(),
|
||||
isActive: z.boolean().default(true),
|
||||
status: z.string().default("invited").nullable().optional(),
|
||||
status: z.string().default("invited"),
|
||||
inviteEmail: z.string().nullable().optional(),
|
||||
lastInvitedAt: z.date().nullable().optional(),
|
||||
lastLoginAuthMethod: z.string().nullable().optional(),
|
||||
|
||||
27
backend/src/db/schemas/user-notifications-default.ts
Normal file
27
backend/src/db/schemas/user-notifications-default.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
// Code generated by automation script, DO NOT EDIT.
|
||||
// Automated by pulling database and generating zod schema
|
||||
// To update. Just run npm run generate:schema
|
||||
// Written by akhilmhdh.
|
||||
|
||||
import { z } from "zod";
|
||||
|
||||
import { TImmutableDBKeys } from "./models";
|
||||
|
||||
export const UserNotificationsDefaultSchema = z.object({
|
||||
id: z.string().uuid(),
|
||||
userId: z.string().uuid(),
|
||||
orgId: z.string().uuid().nullable().optional(),
|
||||
type: z.string(),
|
||||
title: z.string(),
|
||||
body: z.string().nullable().optional(),
|
||||
link: z.string().nullable().optional(),
|
||||
isRead: z.boolean().default(false),
|
||||
createdAt: z.date(),
|
||||
updatedAt: z.date()
|
||||
});
|
||||
|
||||
export type TUserNotificationsDefault = z.infer<typeof UserNotificationsDefaultSchema>;
|
||||
export type TUserNotificationsDefaultInsert = Omit<z.input<typeof UserNotificationsDefaultSchema>, TImmutableDBKeys>;
|
||||
export type TUserNotificationsDefaultUpdate = Partial<
|
||||
Omit<z.input<typeof UserNotificationsDefaultSchema>, TImmutableDBKeys>
|
||||
>;
|
||||
@@ -1,6 +1,7 @@
|
||||
import slugify from "@sindresorhus/slugify";
|
||||
import { z } from "zod";
|
||||
|
||||
import { AccessScope, TemporaryPermissionMode } from "@app/db/schemas";
|
||||
import { backfillPermissionV1SchemaToV2Schema } from "@app/ee/services/permission/project-permission";
|
||||
import { ApiDocsTags, IDENTITY_ADDITIONAL_PRIVILEGE } from "@app/lib/api-docs";
|
||||
import { UnauthorizedError } from "@app/lib/errors";
|
||||
@@ -14,8 +15,7 @@ import {
|
||||
ProjectSpecificPrivilegePermissionSchema,
|
||||
SanitizedIdentityPrivilegeSchema
|
||||
} from "@app/server/routes/sanitizedSchemas";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
import { AccessScope, MembershipActors, TemporaryPermissionMode } from "@app/db/schemas";
|
||||
import { ActorType, AuthMode } from "@app/services/auth/auth-type";
|
||||
|
||||
export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
@@ -78,7 +78,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
||||
},
|
||||
data: {
|
||||
actorId: req.body.identityId,
|
||||
actorType: MembershipActors.Identity,
|
||||
actorType: ActorType.IDENTITY,
|
||||
...req.body,
|
||||
isTemporary: false,
|
||||
name: req.body.slug || slugify(alphaNumericNanoId(8)),
|
||||
@@ -92,7 +92,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
||||
privilege: {
|
||||
...privilege,
|
||||
identityId: req.body.identityId,
|
||||
projectMembershipId: privilege.membershipId,
|
||||
projectMembershipId: "",
|
||||
projectId,
|
||||
slug: privilege.name
|
||||
}
|
||||
@@ -172,7 +172,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
||||
},
|
||||
data: {
|
||||
actorId: req.body.identityId,
|
||||
actorType: MembershipActors.Identity,
|
||||
actorType: ActorType.IDENTITY,
|
||||
...req.body,
|
||||
isTemporary: true,
|
||||
name: req.body.slug || slugify(alphaNumericNanoId(8)),
|
||||
@@ -186,7 +186,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
||||
privilege: {
|
||||
...privilege,
|
||||
identityId: req.body.identityId,
|
||||
projectMembershipId: privilege.membershipId,
|
||||
projectMembershipId: "",
|
||||
projectId,
|
||||
slug: privilege.name
|
||||
}
|
||||
@@ -262,15 +262,9 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
||||
slug: req.body.projectSlug
|
||||
});
|
||||
|
||||
const { membershipId } = await server.services.convertor.identityIdToMembershipId(
|
||||
req.body.identityId,
|
||||
AccessScope.Project,
|
||||
projectId
|
||||
);
|
||||
|
||||
const { privilegeId } = await server.services.convertor.additionalPrivilegeNameToId(
|
||||
const { privilege: privilegeDoc } = await server.services.convertor.additionalPrivilegeNameToDoc(
|
||||
req.body.privilegeSlug,
|
||||
membershipId
|
||||
projectId
|
||||
);
|
||||
|
||||
const { additionalPrivilege: privilege } = await server.services.additionalPrivilege.updateAdditionalPrivilege({
|
||||
@@ -282,8 +276,8 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
||||
},
|
||||
selector: {
|
||||
actorId: req.body.identityId,
|
||||
actorType: MembershipActors.Identity,
|
||||
id: privilegeId
|
||||
actorType: ActorType.IDENTITY,
|
||||
id: privilegeDoc.id
|
||||
},
|
||||
data: {
|
||||
...req.body,
|
||||
@@ -305,7 +299,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
||||
privilege: {
|
||||
...privilege,
|
||||
identityId: req.body.identityId,
|
||||
projectMembershipId: privilege.membershipId,
|
||||
projectMembershipId: "",
|
||||
projectId,
|
||||
slug: privilege.name
|
||||
}
|
||||
@@ -346,15 +340,9 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
||||
slug: req.body.projectSlug
|
||||
});
|
||||
|
||||
const { membershipId } = await server.services.convertor.identityIdToMembershipId(
|
||||
req.body.identityId,
|
||||
AccessScope.Project,
|
||||
projectId
|
||||
);
|
||||
|
||||
const { privilegeId } = await server.services.convertor.additionalPrivilegeNameToId(
|
||||
const { privilegeId } = await server.services.convertor.additionalPrivilegeNameToDoc(
|
||||
req.body.privilegeSlug,
|
||||
membershipId
|
||||
projectId
|
||||
);
|
||||
|
||||
const { additionalPrivilege: privilege } = await server.services.additionalPrivilege.deleteAdditionalPrivilege({
|
||||
@@ -366,7 +354,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
||||
},
|
||||
selector: {
|
||||
actorId: req.body.identityId,
|
||||
actorType: MembershipActors.Identity,
|
||||
actorType: ActorType.IDENTITY,
|
||||
id: privilegeId
|
||||
}
|
||||
});
|
||||
@@ -375,7 +363,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
||||
privilege: {
|
||||
...privilege,
|
||||
identityId: req.body.identityId,
|
||||
projectMembershipId: privilege.membershipId,
|
||||
projectMembershipId: "",
|
||||
projectId,
|
||||
slug: privilege.name
|
||||
}
|
||||
@@ -418,15 +406,9 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
||||
slug: req.query.projectSlug
|
||||
});
|
||||
|
||||
const { membershipId } = await server.services.convertor.identityIdToMembershipId(
|
||||
req.query.identityId,
|
||||
AccessScope.Project,
|
||||
projectId
|
||||
);
|
||||
|
||||
const { privilegeId } = await server.services.convertor.additionalPrivilegeNameToId(
|
||||
const { privilegeId } = await server.services.convertor.additionalPrivilegeNameToDoc(
|
||||
req.params.privilegeSlug,
|
||||
membershipId
|
||||
projectId
|
||||
);
|
||||
|
||||
const { additionalPrivilege: privilege } = await server.services.additionalPrivilege.getAdditionalPrivilegeById({
|
||||
@@ -438,7 +420,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
||||
},
|
||||
selector: {
|
||||
actorId: req.query.identityId,
|
||||
actorType: MembershipActors.Identity,
|
||||
actorType: ActorType.IDENTITY,
|
||||
id: privilegeId
|
||||
}
|
||||
});
|
||||
@@ -447,7 +429,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
||||
privilege: {
|
||||
...privilege,
|
||||
identityId: req.query.identityId,
|
||||
projectMembershipId: privilege.membershipId,
|
||||
projectMembershipId: "",
|
||||
projectId,
|
||||
slug: privilege.name
|
||||
}
|
||||
@@ -496,7 +478,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
||||
},
|
||||
selector: {
|
||||
actorId: req.query.identityId,
|
||||
actorType: MembershipActors.Identity
|
||||
actorType: ActorType.IDENTITY
|
||||
}
|
||||
});
|
||||
|
||||
@@ -504,7 +486,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
||||
privileges: privileges.map((privilege) => ({
|
||||
...privilege,
|
||||
identityId: req.query.identityId,
|
||||
projectMembershipId: privilege.membershipId,
|
||||
projectMembershipId: "",
|
||||
projectId,
|
||||
slug: privilege.name
|
||||
}))
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
import slugify from "@sindresorhus/slugify";
|
||||
import { z } from "zod";
|
||||
|
||||
import { AccessScope, MembershipActors, TemporaryPermissionMode } from "@app/db/schemas";
|
||||
import { AccessScope, TemporaryPermissionMode } from "@app/db/schemas";
|
||||
import { checkForInvalidPermissionCombination } from "@app/ee/services/permission/permission-fns";
|
||||
import { ProjectPermissionV2Schema } from "@app/ee/services/permission/project-permission";
|
||||
import { PROJECT_USER_ADDITIONAL_PRIVILEGE } from "@app/lib/api-docs";
|
||||
import { NotFoundError } from "@app/lib/errors";
|
||||
import { ms } from "@app/lib/ms";
|
||||
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { slugSchema } from "@app/server/lib/schemas";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { SanitizedUserProjectAdditionalPrivilegeSchema } from "@app/server/routes/sanitizedSchema/user-additional-privilege";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
import { ActorType, AuthMode } from "@app/services/auth/auth-type";
|
||||
|
||||
export const registerUserAdditionalPrivilegeRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
@@ -70,7 +71,7 @@ export const registerUserAdditionalPrivilegeRouter = async (server: FastifyZodPr
|
||||
},
|
||||
data: {
|
||||
actorId: userId,
|
||||
actorType: MembershipActors.User,
|
||||
actorType: ActorType.USER,
|
||||
...req.body.type,
|
||||
name: req.body.slug || slugify(alphaNumericNanoId(8)),
|
||||
permissions: req.body.permissions
|
||||
@@ -127,17 +128,15 @@ export const registerUserAdditionalPrivilegeRouter = async (server: FastifyZodPr
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
handler: async (req) => {
|
||||
const { membership } = await server.services.convertor.additionalPrivilegeIdToMembershipId(
|
||||
req.params.privilegeId,
|
||||
AccessScope.Project,
|
||||
req.permission.orgId
|
||||
);
|
||||
const data = await server.services.convertor.additionalPrivilegeIdToDoc(req.params.privilegeId);
|
||||
if (!data.privilege.actorUserId)
|
||||
throw new NotFoundError({ message: `Privilege with id ${req.params.privilegeId} not found` });
|
||||
|
||||
const { additionalPrivilege: privilege } = await server.services.additionalPrivilege.updateAdditionalPrivilege({
|
||||
permission: req.permission,
|
||||
scopeData: {
|
||||
scope: AccessScope.Project,
|
||||
projectId: membership.scopeProjectId as string,
|
||||
projectId: data.privilege.projectId as string,
|
||||
orgId: req.permission.orgId
|
||||
},
|
||||
data: {
|
||||
@@ -151,16 +150,16 @@ export const registerUserAdditionalPrivilegeRouter = async (server: FastifyZodPr
|
||||
},
|
||||
selector: {
|
||||
id: req.params.privilegeId,
|
||||
actorId: membership.actorUserId as string,
|
||||
actorType: MembershipActors.User
|
||||
actorId: data.privilege.actorUserId,
|
||||
actorType: ActorType.USER
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
privilege: {
|
||||
...privilege,
|
||||
userId: membership.actorUserId as string,
|
||||
projectId: membership.scopeProjectId as string,
|
||||
userId: data.privilege.actorUserId,
|
||||
projectId: data.privilege.projectId as string,
|
||||
slug: privilege.name
|
||||
}
|
||||
};
|
||||
@@ -185,31 +184,29 @@ export const registerUserAdditionalPrivilegeRouter = async (server: FastifyZodPr
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
handler: async (req) => {
|
||||
const { membership } = await server.services.convertor.additionalPrivilegeIdToMembershipId(
|
||||
req.params.privilegeId,
|
||||
AccessScope.Project,
|
||||
req.permission.orgId
|
||||
);
|
||||
const data = await server.services.convertor.additionalPrivilegeIdToDoc(req.params.privilegeId);
|
||||
if (!data.privilege.actorUserId)
|
||||
throw new NotFoundError({ message: `Privilege with id ${req.params.privilegeId} not found` });
|
||||
|
||||
const { additionalPrivilege: privilege } = await server.services.additionalPrivilege.deleteAdditionalPrivilege({
|
||||
permission: req.permission,
|
||||
scopeData: {
|
||||
scope: AccessScope.Project,
|
||||
projectId: membership.scopeProjectId as string,
|
||||
projectId: data.privilege.projectId as string,
|
||||
orgId: req.permission.orgId
|
||||
},
|
||||
selector: {
|
||||
id: req.params.privilegeId,
|
||||
actorId: membership.actorUserId as string,
|
||||
actorType: MembershipActors.User
|
||||
actorId: data.privilege.actorUserId,
|
||||
actorType: ActorType.USER
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
privilege: {
|
||||
...privilege,
|
||||
userId: membership.actorUserId as string,
|
||||
projectId: membership.scopeProjectId as string,
|
||||
userId: data.privilege.actorUserId,
|
||||
projectId: data.privilege.projectId as string,
|
||||
slug: privilege.name
|
||||
}
|
||||
};
|
||||
@@ -249,7 +246,7 @@ export const registerUserAdditionalPrivilegeRouter = async (server: FastifyZodPr
|
||||
},
|
||||
selector: {
|
||||
actorId: userId,
|
||||
actorType: MembershipActors.User
|
||||
actorType: ActorType.USER
|
||||
}
|
||||
});
|
||||
|
||||
@@ -282,31 +279,29 @@ export const registerUserAdditionalPrivilegeRouter = async (server: FastifyZodPr
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
handler: async (req) => {
|
||||
const { membership } = await server.services.convertor.additionalPrivilegeIdToMembershipId(
|
||||
req.params.privilegeId,
|
||||
AccessScope.Project,
|
||||
req.permission.orgId
|
||||
);
|
||||
const data = await server.services.convertor.additionalPrivilegeIdToDoc(req.params.privilegeId);
|
||||
if (!data.privilege.actorUserId)
|
||||
throw new NotFoundError({ message: `Privilege with id ${req.params.privilegeId} not found` });
|
||||
|
||||
const { additionalPrivilege: privilege } = await server.services.additionalPrivilege.getAdditionalPrivilegeById({
|
||||
permission: req.permission,
|
||||
scopeData: {
|
||||
scope: AccessScope.Project,
|
||||
projectId: membership.scopeProjectId as string,
|
||||
projectId: data.privilege.projectId as string,
|
||||
orgId: req.permission.orgId
|
||||
},
|
||||
selector: {
|
||||
id: req.params.privilegeId,
|
||||
actorId: membership.actorUserId as string,
|
||||
actorType: MembershipActors.User
|
||||
actorId: data.privilege.actorUserId,
|
||||
actorType: ActorType.USER
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
privilege: {
|
||||
...privilege,
|
||||
userId: membership.actorUserId as string,
|
||||
projectId: membership.scopeProjectId as string,
|
||||
userId: data.privilege.actorUserId,
|
||||
projectId: data.privilege.projectId as string,
|
||||
slug: privilege.name
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import slugify from "@sindresorhus/slugify";
|
||||
import { z } from "zod";
|
||||
|
||||
import { AccessScope, MembershipActors, TemporaryPermissionMode } from "@app/db/schemas";
|
||||
import { AccessScope, TemporaryPermissionMode } from "@app/db/schemas";
|
||||
import { checkForInvalidPermissionCombination } from "@app/ee/services/permission/permission-fns";
|
||||
import { ProjectPermissionV2Schema } from "@app/ee/services/permission/project-permission";
|
||||
import { ApiDocsTags, IDENTITY_ADDITIONAL_PRIVILEGE_V2 } from "@app/lib/api-docs";
|
||||
@@ -11,7 +11,7 @@ import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { slugSchema } from "@app/server/lib/schemas";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { SanitizedIdentityPrivilegeSchema } from "@app/server/routes/sanitizedSchema/identitiy-additional-privilege";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
import { ActorType, AuthMode } from "@app/services/auth/auth-type";
|
||||
|
||||
export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
@@ -73,7 +73,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
||||
},
|
||||
data: {
|
||||
actorId: req.body.identityId,
|
||||
actorType: MembershipActors.Identity,
|
||||
actorType: ActorType.IDENTITY,
|
||||
...req.body.type,
|
||||
name: req.body.slug || slugify(alphaNumericNanoId(8)),
|
||||
permissions: req.body.permissions
|
||||
@@ -84,7 +84,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
||||
privilege: {
|
||||
...privilege,
|
||||
identityId: req.body.identityId,
|
||||
projectMembershipId: privilege.membershipId,
|
||||
projectMembershipId: "",
|
||||
projectId: req.body.projectId,
|
||||
slug: privilege.name
|
||||
}
|
||||
@@ -142,23 +142,19 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const { membership } = await server.services.convertor.additionalPrivilegeIdToMembershipId(
|
||||
req.params.id,
|
||||
AccessScope.Project,
|
||||
req.permission.orgId
|
||||
);
|
||||
const { privilege: privilegeDoc } = await server.services.convertor.additionalPrivilegeIdToDoc(req.params.id);
|
||||
|
||||
const { additionalPrivilege: privilege } = await server.services.additionalPrivilege.updateAdditionalPrivilege({
|
||||
permission: req.permission,
|
||||
scopeData: {
|
||||
scope: AccessScope.Project,
|
||||
projectId: membership.scopeProjectId as string,
|
||||
projectId: privilegeDoc.projectId as string,
|
||||
orgId: req.permission.orgId
|
||||
},
|
||||
selector: {
|
||||
id: req.params.id,
|
||||
actorId: membership.actorIdentityId as string,
|
||||
actorType: MembershipActors.Identity
|
||||
actorId: privilegeDoc.actorIdentityId as string,
|
||||
actorType: ActorType.IDENTITY
|
||||
},
|
||||
data: {
|
||||
...req.body,
|
||||
@@ -170,9 +166,9 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
||||
return {
|
||||
privilege: {
|
||||
...privilege,
|
||||
identityId: membership.actorIdentityId as string,
|
||||
projectMembershipId: privilege.membershipId,
|
||||
projectId: membership.scopeProjectId as string,
|
||||
identityId: privilegeDoc.actorIdentityId as string,
|
||||
projectMembershipId: "",
|
||||
projectId: privilegeDoc.projectId as string,
|
||||
slug: privilege.name
|
||||
}
|
||||
};
|
||||
@@ -205,32 +201,28 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const { membership } = await server.services.convertor.additionalPrivilegeIdToMembershipId(
|
||||
req.params.id,
|
||||
AccessScope.Project,
|
||||
req.permission.orgId
|
||||
);
|
||||
const { privilege: privilegeDoc } = await server.services.convertor.additionalPrivilegeIdToDoc(req.params.id);
|
||||
|
||||
const { additionalPrivilege: privilege } = await server.services.additionalPrivilege.deleteAdditionalPrivilege({
|
||||
permission: req.permission,
|
||||
scopeData: {
|
||||
scope: AccessScope.Project,
|
||||
projectId: membership.scopeProjectId as string,
|
||||
projectId: privilegeDoc.projectId as string,
|
||||
orgId: req.permission.orgId
|
||||
},
|
||||
selector: {
|
||||
id: req.params.id,
|
||||
actorId: membership.actorIdentityId as string,
|
||||
actorType: MembershipActors.Identity
|
||||
actorId: privilegeDoc.actorIdentityId as string,
|
||||
actorType: ActorType.IDENTITY
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
privilege: {
|
||||
...privilege,
|
||||
identityId: membership.actorIdentityId as string,
|
||||
projectMembershipId: privilege.membershipId,
|
||||
projectId: membership.scopeProjectId as string,
|
||||
identityId: privilegeDoc.actorIdentityId as string,
|
||||
projectMembershipId: "",
|
||||
projectId: privilegeDoc.projectId as string,
|
||||
slug: privilege.name
|
||||
}
|
||||
};
|
||||
@@ -263,32 +255,28 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const { membership } = await server.services.convertor.additionalPrivilegeIdToMembershipId(
|
||||
req.params.id,
|
||||
AccessScope.Project,
|
||||
req.permission.orgId
|
||||
);
|
||||
const { privilege: privilegeDoc } = await server.services.convertor.additionalPrivilegeIdToDoc(req.params.id);
|
||||
|
||||
const { additionalPrivilege: privilege } = await server.services.additionalPrivilege.getAdditionalPrivilegeById({
|
||||
permission: req.permission,
|
||||
scopeData: {
|
||||
scope: AccessScope.Project,
|
||||
projectId: membership.scopeProjectId as string,
|
||||
projectId: privilegeDoc.projectId as string,
|
||||
orgId: req.permission.orgId
|
||||
},
|
||||
selector: {
|
||||
id: req.params.id,
|
||||
actorId: membership.actorIdentityId as string,
|
||||
actorType: MembershipActors.Identity
|
||||
actorId: privilegeDoc.actorIdentityId as string,
|
||||
actorType: ActorType.IDENTITY
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
privilege: {
|
||||
...privilege,
|
||||
identityId: membership.actorIdentityId as string,
|
||||
projectMembershipId: privilege.membershipId,
|
||||
projectId: membership.scopeProjectId as string,
|
||||
identityId: privilegeDoc.actorIdentityId as string,
|
||||
projectMembershipId: "",
|
||||
projectId: privilegeDoc.projectId as string,
|
||||
slug: privilege.name
|
||||
}
|
||||
};
|
||||
@@ -341,7 +329,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
||||
selector: {
|
||||
name: req.params.privilegeSlug,
|
||||
actorId: req.query.identityId,
|
||||
actorType: MembershipActors.Identity
|
||||
actorType: ActorType.IDENTITY
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -350,7 +338,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
||||
privilege: {
|
||||
...privilege,
|
||||
identityId: req.query.identityId,
|
||||
projectMembershipId: privilege.membershipId,
|
||||
projectMembershipId: "",
|
||||
projectId,
|
||||
slug: privilege.name
|
||||
}
|
||||
@@ -394,7 +382,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
||||
},
|
||||
selector: {
|
||||
actorId: req.query.identityId,
|
||||
actorType: MembershipActors.Identity
|
||||
actorType: ActorType.IDENTITY
|
||||
}
|
||||
});
|
||||
|
||||
@@ -402,7 +390,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
||||
privileges: privileges.map((privilege) => ({
|
||||
...privilege,
|
||||
identityId: req.query.identityId,
|
||||
projectMembershipId: privilege.membershipId,
|
||||
projectMembershipId: "",
|
||||
projectId: req.query.projectId,
|
||||
slug: privilege.name
|
||||
}))
|
||||
|
||||
@@ -1,21 +1,18 @@
|
||||
import { ForbiddenError } from "@casl/ability";
|
||||
|
||||
import { ActionProjectType } from "@app/db/schemas";
|
||||
import { AccessScope, ActionProjectType } from "@app/db/schemas";
|
||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
|
||||
import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { groupBy } from "@app/lib/fn";
|
||||
import { TOrgMembershipDALFactory } from "@app/services/org-membership/org-membership-dal";
|
||||
import { TProjectDALFactory } from "@app/services/project/project-dal";
|
||||
import { TProjectEnvDALFactory } from "@app/services/project-env/project-env-dal";
|
||||
import { TProjectMembershipDALFactory } from "@app/services/project-membership/project-membership-dal";
|
||||
import { TUserDALFactory } from "@app/services/user/user-dal";
|
||||
|
||||
import { TAccessApprovalRequestDALFactory } from "../access-approval-request/access-approval-request-dal";
|
||||
import { TAccessApprovalRequestReviewerDALFactory } from "../access-approval-request/access-approval-request-reviewer-dal";
|
||||
import { ApprovalStatus } from "../access-approval-request/access-approval-request-types";
|
||||
import { TGroupDALFactory } from "../group/group-dal";
|
||||
import { TProjectUserAdditionalPrivilegeDALFactory } from "../project-user-additional-privilege/project-user-additional-privilege-dal";
|
||||
import {
|
||||
TAccessApprovalPolicyApproverDALFactory,
|
||||
TAccessApprovalPolicyBypasserDALFactory
|
||||
@@ -31,6 +28,8 @@ import {
|
||||
TListAccessApprovalPoliciesDTO,
|
||||
TUpdateAccessApprovalPolicy
|
||||
} from "./access-approval-policy-types";
|
||||
import { TMembershipUserDALFactory } from "@app/services/membership-user/membership-user-dal";
|
||||
import { TAdditionalPrivilegeDALFactory } from "@app/services/additional-privilege/additional-privilege-dal";
|
||||
|
||||
type TAccessApprovalPolicyServiceFactoryDep = {
|
||||
projectDAL: TProjectDALFactory;
|
||||
@@ -39,14 +38,13 @@ type TAccessApprovalPolicyServiceFactoryDep = {
|
||||
projectEnvDAL: Pick<TProjectEnvDALFactory, "find" | "findOne">;
|
||||
accessApprovalPolicyApproverDAL: TAccessApprovalPolicyApproverDALFactory;
|
||||
accessApprovalPolicyBypasserDAL: TAccessApprovalPolicyBypasserDALFactory;
|
||||
projectMembershipDAL: Pick<TProjectMembershipDALFactory, "find">;
|
||||
groupDAL: TGroupDALFactory;
|
||||
userDAL: Pick<TUserDALFactory, "find">;
|
||||
accessApprovalRequestDAL: Pick<TAccessApprovalRequestDALFactory, "update" | "find" | "resetReviewByPolicyId">;
|
||||
additionalPrivilegeDAL: Pick<TProjectUserAdditionalPrivilegeDALFactory, "delete">;
|
||||
additionalPrivilegeDAL: Pick<TAdditionalPrivilegeDALFactory, "delete">;
|
||||
accessApprovalRequestReviewerDAL: Pick<TAccessApprovalRequestReviewerDALFactory, "update" | "delete">;
|
||||
orgMembershipDAL: Pick<TOrgMembershipDALFactory, "find">;
|
||||
accessApprovalPolicyEnvironmentDAL: TAccessApprovalPolicyEnvironmentDALFactory;
|
||||
membershipUserDAL: TMembershipUserDALFactory;
|
||||
};
|
||||
|
||||
export const accessApprovalPolicyServiceFactory = ({
|
||||
@@ -62,7 +60,7 @@ export const accessApprovalPolicyServiceFactory = ({
|
||||
accessApprovalRequestDAL,
|
||||
additionalPrivilegeDAL,
|
||||
accessApprovalRequestReviewerDAL,
|
||||
orgMembershipDAL
|
||||
membershipUserDAL
|
||||
}: TAccessApprovalPolicyServiceFactoryDep): TAccessApprovalPolicyServiceFactory => {
|
||||
const $policyExists = async ({
|
||||
envId,
|
||||
@@ -424,13 +422,14 @@ export const accessApprovalPolicyServiceFactory = ({
|
||||
|
||||
// Validate user bypassers
|
||||
if (bypasserUserIds.length > 0) {
|
||||
const orgMemberships = await orgMembershipDAL.find({
|
||||
$in: { userId: bypasserUserIds },
|
||||
orgId: actorOrgId
|
||||
const orgMemberships = await membershipUserDAL.find({
|
||||
$in: { actorUserId: bypasserUserIds },
|
||||
scopeOrgId: actorOrgId,
|
||||
scope: AccessScope.Organization
|
||||
});
|
||||
|
||||
if (orgMemberships.length !== bypasserUserIds.length) {
|
||||
const foundUserIdsInOrg = new Set(orgMemberships.map((mem) => mem.userId));
|
||||
const foundUserIdsInOrg = new Set(orgMemberships.map((mem) => mem.actorUserId as string));
|
||||
const missingUserIds = bypasserUserIds.filter((id) => !foundUserIdsInOrg.has(id));
|
||||
throw new BadRequestError({
|
||||
message: `One or more specified bypasser users are not part of the organization or do not exist. Invalid or non-member user IDs: ${missingUserIds.join(", ")}`
|
||||
|
||||
@@ -26,16 +26,15 @@ import { TAccessApprovalPolicyApproverDALFactory } from "../access-approval-poli
|
||||
import { TAccessApprovalPolicyDALFactory } from "../access-approval-policy/access-approval-policy-dal";
|
||||
import { TGroupDALFactory } from "../group/group-dal";
|
||||
import { TPermissionServiceFactory } from "../permission/permission-service-types";
|
||||
import { TProjectUserAdditionalPrivilegeDALFactory } from "../project-user-additional-privilege/project-user-additional-privilege-dal";
|
||||
import { ProjectUserAdditionalPrivilegeTemporaryMode } from "../project-user-additional-privilege/project-user-additional-privilege-types";
|
||||
import { TAccessApprovalRequestDALFactory } from "./access-approval-request-dal";
|
||||
import { verifyRequestedPermissions } from "./access-approval-request-fns";
|
||||
import { TAccessApprovalRequestReviewerDALFactory } from "./access-approval-request-reviewer-dal";
|
||||
import { ApprovalStatus, TAccessApprovalRequestServiceFactory } from "./access-approval-request-types";
|
||||
import { TAdditionalPrivilegeDALFactory } from "@app/services/additional-privilege/additional-privilege-dal";
|
||||
|
||||
type TSecretApprovalRequestServiceFactoryDep = {
|
||||
additionalPrivilegeDAL: Pick<TProjectUserAdditionalPrivilegeDALFactory, "create" | "findById">;
|
||||
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission" | "invalidateProjectPermissionCache">;
|
||||
additionalPrivilegeDAL: Pick<TAdditionalPrivilegeDALFactory, "create" | "findById">;
|
||||
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">;
|
||||
accessApprovalPolicyApproverDAL: Pick<TAccessApprovalPolicyApproverDALFactory, "find">;
|
||||
projectEnvDAL: Pick<TProjectEnvDALFactory, "findOne">;
|
||||
projectDAL: Pick<
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TDbClient } from "@app/db";
|
||||
import { GatewaysV2Schema, TableName, TGatewaysV2 } from "@app/db/schemas";
|
||||
import { AccessScope, GatewaysV2Schema, TableName, TGatewaysV2 } from "@app/db/schemas";
|
||||
import { DatabaseError } from "@app/lib/errors";
|
||||
import { buildFindFilter, ormify, selectAllTableCols, TFindFilter, TFindOpt } from "@app/lib/knex";
|
||||
|
||||
@@ -16,11 +16,6 @@ export const gatewayV2DalFactory = (db: TDbClient) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
.where(buildFindFilter(filter, TableName.GatewayV2))
|
||||
.join(TableName.Identity, `${TableName.Identity}.id`, `${TableName.GatewayV2}.identityId`)
|
||||
.join(
|
||||
TableName.IdentityOrgMembership,
|
||||
`${TableName.IdentityOrgMembership}.identityId`,
|
||||
`${TableName.GatewayV2}.identityId`
|
||||
)
|
||||
.select(selectAllTableCols(TableName.GatewayV2))
|
||||
.select(db.ref("name").withSchema(TableName.Identity).as("identityName"));
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { TDbClient } from "@app/db";
|
||||
import { GatewaysSchema, TableName, TGateways } from "@app/db/schemas";
|
||||
import { AccessScope, GatewaysSchema, TableName, TGateways } from "@app/db/schemas";
|
||||
import { DatabaseError } from "@app/lib/errors";
|
||||
import { buildFindFilter, ormify, selectAllTableCols, TFindFilter, TFindOpt } from "@app/lib/knex";
|
||||
|
||||
@@ -17,17 +17,14 @@ export const gatewayDALFactory = (db: TDbClient) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
.where(buildFindFilter(filter, TableName.Gateway, ["orgId"]))
|
||||
.join(TableName.Identity, `${TableName.Identity}.id`, `${TableName.Gateway}.identityId`)
|
||||
.join(
|
||||
TableName.IdentityOrgMembership,
|
||||
`${TableName.IdentityOrgMembership}.identityId`,
|
||||
`${TableName.Gateway}.identityId`
|
||||
)
|
||||
.join(TableName.Membership, `${TableName.Membership}.actorIdentityId`, `${TableName.Gateway}.identityId`)
|
||||
.select(selectAllTableCols(TableName.Gateway))
|
||||
.select(db.ref("orgId").withSchema(TableName.IdentityOrgMembership).as("identityOrgId"))
|
||||
.select(db.ref("name").withSchema(TableName.Identity).as("identityName"));
|
||||
.select(db.ref("scopeOrgId").withSchema(TableName.IdentityOrgMembership).as("identityOrgId"))
|
||||
.select(db.ref("name").withSchema(TableName.Identity).as("identityName"))
|
||||
.where(`${TableName.Membership}.scope`, AccessScope.Organization);
|
||||
|
||||
if (filter.orgId) {
|
||||
void query.where(`${TableName.IdentityOrgMembership}.orgId`, filter.orgId);
|
||||
void query.where(`${TableName.Membership}.scopeOrgId`, filter.orgId);
|
||||
}
|
||||
if (limit) void query.limit(limit);
|
||||
if (offset) void query.offset(offset);
|
||||
@@ -39,7 +36,7 @@ export const gatewayDALFactory = (db: TDbClient) => {
|
||||
|
||||
return docs.map((el) => ({
|
||||
...GatewaysSchema.parse(el),
|
||||
orgId: el.identityOrgId as string, // todo(daniel): figure out why typescript is not inferring this as a string
|
||||
orgId: el.identityOrgId,
|
||||
identity: { id: el.identityId, name: el.identityName }
|
||||
}));
|
||||
} catch (error) {
|
||||
|
||||
@@ -36,14 +36,21 @@ export const groupDALFactory = (db: TDbClient) => {
|
||||
try {
|
||||
const docs = await (tx || db.replicaNode())(TableName.Groups)
|
||||
.where(`${TableName.Groups}.orgId`, orgId)
|
||||
.leftJoin(TableName.OrgRoles, `${TableName.Groups}.roleId`, `${TableName.OrgRoles}.id`)
|
||||
.where(`${TableName.Membership}.scopeOrgId`, orgId)
|
||||
.where(`${TableName.Membership}.scope`, AccessScope.Organization)
|
||||
.join(TableName.Membership, `${TableName.Groups}.id`, `${TableName.Membership}.actorGroupId`)
|
||||
.join(TableName.MembershipRole, `${TableName.MembershipRole}.membershipId`, `${TableName.Membership}.id`)
|
||||
.join(TableName.Role, `${TableName.MembershipRole}.customRoleId`, `${TableName.Role}.id`)
|
||||
.select(selectAllTableCols(TableName.Groups))
|
||||
// cr stands for custom role
|
||||
.select(db.ref("id").as("crId").withSchema(TableName.OrgRoles))
|
||||
.select(db.ref("name").as("crName").withSchema(TableName.OrgRoles))
|
||||
.select(db.ref("slug").as("crSlug").withSchema(TableName.OrgRoles))
|
||||
.select(db.ref("description").as("crDescription").withSchema(TableName.OrgRoles))
|
||||
.select(db.ref("permissions").as("crPermission").withSchema(TableName.OrgRoles));
|
||||
.select(db.ref("id").as("crId").withSchema(TableName.Role))
|
||||
.select(db.ref("name").as("crName").withSchema(TableName.Role))
|
||||
.select(db.ref("role").withSchema(TableName.MembershipRole))
|
||||
.select(db.ref("customRoleId").as("roleId").withSchema(TableName.MembershipRole))
|
||||
.select(db.ref("slug").as("crSlug").withSchema(TableName.Role))
|
||||
.select(db.ref("description").as("crDescription").withSchema(TableName.Role))
|
||||
.select(db.ref("permissions").as("crPermission").withSchema(TableName.Role));
|
||||
|
||||
return docs.map(({ crId, crDescription, crSlug, crPermission, crName, ...el }) => ({
|
||||
...el,
|
||||
customRole: el.roleId
|
||||
|
||||
@@ -9,8 +9,7 @@ import {
|
||||
MembershipsSchema,
|
||||
TableName,
|
||||
TMemberships,
|
||||
TProjectRoles,
|
||||
TProjects
|
||||
TProjectRoles
|
||||
} from "@app/db/schemas";
|
||||
import { DatabaseError } from "@app/lib/errors";
|
||||
import { selectAllTableCols, sqlNestRelationships } from "@app/lib/knex";
|
||||
@@ -204,11 +203,19 @@ export const permissionDALFactory = (db: TDbClient): TPermissionDALFactory => {
|
||||
.replicaNode()(TableName.Membership)
|
||||
.join(TableName.MembershipRole, `${TableName.Membership}.id`, `${TableName.MembershipRole}.membershipId`)
|
||||
.leftJoin(TableName.Role, `${TableName.MembershipRole}.customRoleId`, `${TableName.Role}.id`)
|
||||
.leftJoin(
|
||||
TableName.AdditionalPrivilege,
|
||||
`${TableName.Membership}.id`,
|
||||
`${TableName.AdditionalPrivilege}.membershipId`
|
||||
)
|
||||
.leftJoin(TableName.AdditionalPrivilege, (qb) => {
|
||||
if (actorType === ActorType.IDENTITY) {
|
||||
qb.on(`${TableName.Membership}.actorIdentityId`, `${TableName.AdditionalPrivilege}.actorIdentityId`).andOn(
|
||||
`${TableName.Membership}.scopeOrgId`,
|
||||
`${TableName.AdditionalPrivilege}.orgId`
|
||||
);
|
||||
} else {
|
||||
qb.on(`${TableName.Membership}.actorUserId`, `${TableName.AdditionalPrivilege}.actorUserId`).andOn(
|
||||
`${TableName.Membership}.scopeOrgId`,
|
||||
`${TableName.AdditionalPrivilege}.orgId`
|
||||
);
|
||||
}
|
||||
})
|
||||
.leftJoin(TableName.IdentityMetadata, (queryBuilder) => {
|
||||
if (actorType === ActorType.USER) {
|
||||
void queryBuilder
|
||||
@@ -366,22 +373,20 @@ export const permissionDALFactory = (db: TDbClient): TPermissionDALFactory => {
|
||||
) => {
|
||||
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`
|
||||
)
|
||||
.replicaNode()(TableName.Membership)
|
||||
.whereNotNull(`${TableName.Membership}.actorGroupId`)
|
||||
.where(`${TableName.Membership}.scope`, AccessScope.Project)
|
||||
.join(TableName.Groups, `${TableName.Groups}.id`, `${TableName.Membership}.actorGroupId`)
|
||||
.join(TableName.MembershipRole, `${TableName.MembershipRole}.membershipId`, `${TableName.Membership}.id`)
|
||||
.leftJoin<TProjectRoles>(
|
||||
{ groupCustomRoles: TableName.ProjectRoles },
|
||||
`${TableName.GroupProjectMembershipRole}.customRoleId`,
|
||||
{ groupCustomRoles: TableName.Role },
|
||||
`${TableName.MembershipRole}.customRoleId`,
|
||||
`groupCustomRoles.id`
|
||||
)
|
||||
.where(`${TableName.GroupProjectMembership}.projectId`, "=", projectId)
|
||||
.where(`${TableName.Membership}.scopeProjectId`, "=", projectId)
|
||||
.where((bd) => {
|
||||
if (filterGroupId) {
|
||||
void bd.where(`${TableName.GroupProjectMembership}.groupId`, "=", filterGroupId);
|
||||
void bd.where(`${TableName.Membership}.actorGroupId`, "=", filterGroupId);
|
||||
}
|
||||
})
|
||||
.select(
|
||||
@@ -390,31 +395,19 @@ export const permissionDALFactory = (db: TDbClient): TPermissionDALFactory => {
|
||||
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("id").withSchema(TableName.MembershipRole).as("groupProjectMembershipRoleId"),
|
||||
db.ref("role").withSchema(TableName.MembershipRole).as("groupProjectMembershipRole"),
|
||||
db.ref("customRoleId").withSchema(TableName.MembershipRole).as("groupProjectMembershipRoleCustomRoleId"),
|
||||
db.ref("isTemporary").withSchema(TableName.MembershipRole).as("groupProjectMembershipRoleIsTemporary"),
|
||||
db.ref("temporaryMode").withSchema(TableName.MembershipRole).as("groupProjectMembershipRoleTemporaryMode"),
|
||||
db.ref("temporaryRange").withSchema(TableName.MembershipRole).as("groupProjectMembershipRoleTemporaryRange"),
|
||||
db
|
||||
.ref("temporaryAccessStartTime")
|
||||
.withSchema(TableName.GroupProjectMembershipRole)
|
||||
.withSchema(TableName.MembershipRole)
|
||||
.as("groupProjectMembershipRoleTemporaryAccessStartTime"),
|
||||
db
|
||||
.ref("temporaryAccessEndTime")
|
||||
.withSchema(TableName.GroupProjectMembershipRole)
|
||||
.withSchema(TableName.MembershipRole)
|
||||
.as("groupProjectMembershipRoleTemporaryAccessEndTime")
|
||||
);
|
||||
|
||||
@@ -476,175 +469,124 @@ export const permissionDALFactory = (db: TDbClient): TPermissionDALFactory => {
|
||||
}
|
||||
};
|
||||
|
||||
const getProjectUserPermissions: TPermissionDALFactory["getProjectUserPermissions"] = async (projectId: string) => {
|
||||
// TODO(simp): this query is wrong and fix it
|
||||
const getProjectUserPermissions: TPermissionDALFactory["getProjectUserPermissions"] = async (
|
||||
projectId: string,
|
||||
orgId: string
|
||||
) => {
|
||||
try {
|
||||
const userGroupSubquery = db(TableName.Groups)
|
||||
.leftJoin(TableName.UserGroupMembership, `${TableName.UserGroupMembership}.groupId`, `${TableName.Groups}.id`)
|
||||
.where(`${TableName.Groups}.orgId`, orgId)
|
||||
.select(db.ref("id").withSchema(TableName.Groups));
|
||||
|
||||
const docs = await db
|
||||
.replicaNode()(TableName.Users)
|
||||
.where("isGhost", "=", false)
|
||||
.leftJoin(TableName.GroupProjectMembership, (queryBuilder) => {
|
||||
void queryBuilder.on(`${TableName.GroupProjectMembership}.projectId`, db.raw("?", [projectId]));
|
||||
.replicaNode()(TableName.Membership)
|
||||
.join(TableName.MembershipRole, `${TableName.Membership}.id`, `${TableName.MembershipRole}.membershipId`)
|
||||
.leftJoin(TableName.Role, `${TableName.MembershipRole}.customRoleId`, `${TableName.Role}.id`)
|
||||
.leftJoin(TableName.AdditionalPrivilege, (qb) => {
|
||||
qb.on(`${TableName.Membership}.actorUserId`, `${TableName.AdditionalPrivilege}.actorUserId`).andOn(
|
||||
`${TableName.Membership}.scopeOrgId`,
|
||||
`${TableName.AdditionalPrivilege}.orgId`
|
||||
);
|
||||
})
|
||||
.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`);
|
||||
.on(`${TableName.Membership}.actorUserId`, `${TableName.IdentityMetadata}.userId`)
|
||||
.andOn(`${TableName.Membership}.scopeOrgId`, `${TableName.IdentityMetadata}.orgId`);
|
||||
})
|
||||
.leftJoin(
|
||||
TableName.UserGroupMembership,
|
||||
`${TableName.UserGroupMembership}.groupId`,
|
||||
`${TableName.Membership}.actorGroupId`
|
||||
)
|
||||
.leftJoin(TableName.Users, (qb) => {
|
||||
qb.on(`${TableName.Users}.id`, `${TableName.Membership}.actorUserId`).orOn(
|
||||
`${TableName.Users}.id`,
|
||||
`${TableName.UserGroupMembership}.groupId`
|
||||
);
|
||||
})
|
||||
.where(`${TableName.Membership}.scopeOrgId`, orgId)
|
||||
.where(`${TableName.Membership}.scope`, AccessScope.Project)
|
||||
.where(`${TableName.Membership}.scopeProjectId`, projectId)
|
||||
.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("id").withSchema(TableName.MembershipRole).as("userGroupProjectMembershipRoleId"),
|
||||
db.ref("role").withSchema(TableName.MembershipRole).as("userGroupProjectMembershipRole"),
|
||||
db.ref("customRoleId").withSchema(TableName.MembershipRole).as("userGroupProjectMembershipRoleCustomRoleId"),
|
||||
db.ref("isTemporary").withSchema(TableName.MembershipRole).as("userGroupProjectMembershipRoleIsTemporary"),
|
||||
db
|
||||
.ref("temporaryMode")
|
||||
.withSchema(TableName.GroupProjectMembershipRole)
|
||||
.withSchema(TableName.MembershipRole)
|
||||
.as("userGroupProjectMembershipRoleTemporaryMode"),
|
||||
db
|
||||
.ref("temporaryRange")
|
||||
.withSchema(TableName.GroupProjectMembershipRole)
|
||||
.withSchema(TableName.MembershipRole)
|
||||
.as("userGroupProjectMembershipRoleTemporaryRange"),
|
||||
db
|
||||
.ref("temporaryAccessStartTime")
|
||||
.withSchema(TableName.GroupProjectMembershipRole)
|
||||
.withSchema(TableName.MembershipRole)
|
||||
.as("userGroupProjectMembershipRoleTemporaryAccessStartTime"),
|
||||
db
|
||||
.ref("temporaryAccessEndTime")
|
||||
.withSchema(TableName.GroupProjectMembershipRole)
|
||||
.withSchema(TableName.MembershipRole)
|
||||
.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("id").withSchema(TableName.Membership).as("membershipId"),
|
||||
db.ref("createdAt").withSchema(TableName.Membership).as("membershipCreatedAt"),
|
||||
db.ref("updatedAt").withSchema(TableName.Membership).as("membershipUpdatedAt"),
|
||||
db.ref("slug").withSchema(TableName.Role).as("userProjectMembershipRoleCustomRoleSlug"),
|
||||
db.ref("permissions").withSchema(TableName.Role).as("userProjectCustomRolePermission"),
|
||||
db.ref("id").withSchema(TableName.Role).as("userProjectMembershipRoleId"),
|
||||
db.ref("role").withSchema(TableName.Role).as("userProjectMembershipRole"),
|
||||
db.ref("temporaryMode").withSchema(TableName.Role).as("userProjectMembershipRoleTemporaryMode"),
|
||||
db.ref("isTemporary").withSchema(TableName.Role).as("userProjectMembershipRoleIsTemporary"),
|
||||
db.ref("temporaryRange").withSchema(TableName.Role).as("userProjectMembershipRoleTemporaryRange"),
|
||||
db
|
||||
.ref("temporaryAccessStartTime")
|
||||
.withSchema(TableName.ProjectUserMembershipRole)
|
||||
.withSchema(TableName.Role)
|
||||
.as("userProjectMembershipRoleTemporaryAccessStartTime"),
|
||||
db
|
||||
.ref("temporaryAccessEndTime")
|
||||
.withSchema(TableName.ProjectUserMembershipRole)
|
||||
.withSchema(TableName.Role)
|
||||
.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("id").withSchema(TableName.AdditionalPrivilege).as("userAdditionalPrivilegesId"),
|
||||
db.ref("permissions").withSchema(TableName.AdditionalPrivilege).as("userAdditionalPrivilegesPermissions"),
|
||||
db.ref("temporaryMode").withSchema(TableName.AdditionalPrivilege).as("userAdditionalPrivilegesTemporaryMode"),
|
||||
db.ref("isTemporary").withSchema(TableName.AdditionalPrivilege).as("userAdditionalPrivilegesIsTemporary"),
|
||||
db
|
||||
.ref("temporaryRange")
|
||||
.withSchema(TableName.ProjectUserAdditionalPrivilege)
|
||||
.withSchema(TableName.AdditionalPrivilege)
|
||||
.as("userAdditionalPrivilegesTemporaryRange"),
|
||||
db.ref("userId").withSchema(TableName.ProjectUserAdditionalPrivilege).as("userAdditionalPrivilegesUserId"),
|
||||
db.ref("userId").withSchema(TableName.AdditionalPrivilege).as("userAdditionalPrivilegesUserId"),
|
||||
db
|
||||
.ref("temporaryAccessStartTime")
|
||||
.withSchema(TableName.ProjectUserAdditionalPrivilege)
|
||||
.withSchema(TableName.AdditionalPrivilege)
|
||||
.as("userAdditionalPrivilegesTemporaryAccessStartTime"),
|
||||
db
|
||||
.ref("temporaryAccessEndTime")
|
||||
.withSchema(TableName.ProjectUserAdditionalPrivilege)
|
||||
.withSchema(TableName.AdditionalPrivilege)
|
||||
.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")
|
||||
db.ref("value").withSchema(TableName.IdentityMetadata).as("metadataValue")
|
||||
);
|
||||
|
||||
const userPermissions = sqlNestRelationships({
|
||||
data: docs,
|
||||
key: "userId",
|
||||
parentMapper: ({
|
||||
orgId,
|
||||
username,
|
||||
orgAuthEnforced,
|
||||
membershipId,
|
||||
groupMembershipId,
|
||||
membershipCreatedAt,
|
||||
groupMembershipCreatedAt,
|
||||
groupMembershipUpdatedAt,
|
||||
membershipUpdatedAt,
|
||||
projectType,
|
||||
userId
|
||||
}) => ({
|
||||
orgId,
|
||||
orgAuthEnforced,
|
||||
parentMapper: ({ username, membershipId, membershipCreatedAt, membershipUpdatedAt, userId }) => ({
|
||||
userId,
|
||||
projectId,
|
||||
username,
|
||||
projectType,
|
||||
id: membershipId || groupMembershipId,
|
||||
createdAt: membershipCreatedAt || groupMembershipCreatedAt,
|
||||
updatedAt: membershipUpdatedAt || groupMembershipUpdatedAt
|
||||
id: membershipId,
|
||||
createdAt: membershipCreatedAt,
|
||||
updatedAt: membershipUpdatedAt
|
||||
}),
|
||||
childrenMapper: [
|
||||
{
|
||||
@@ -767,68 +709,49 @@ export const permissionDALFactory = (db: TDbClient): TPermissionDALFactory => {
|
||||
};
|
||||
|
||||
const getProjectIdentityPermissions: TPermissionDALFactory["getProjectIdentityPermissions"] = async (
|
||||
projectId: string
|
||||
projectId: string,
|
||||
orgId: 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`
|
||||
)
|
||||
.replicaNode()(TableName.Membership)
|
||||
.join(TableName.MembershipRole, `${TableName.Membership}.id`, `${TableName.MembershipRole}.membershipId`)
|
||||
.leftJoin(TableName.Role, `${TableName.MembershipRole}.customRoleId`, `${TableName.Role}.id`)
|
||||
.leftJoin(TableName.AdditionalPrivilege, (qb) => {
|
||||
qb.on(`${TableName.Membership}.actorIdentityId`, `${TableName.AdditionalPrivilege}.actorIdentityId`).andOn(
|
||||
`${TableName.Membership}.scopeOrgId`,
|
||||
`${TableName.AdditionalPrivilege}.orgId`
|
||||
);
|
||||
})
|
||||
.leftJoin(TableName.IdentityMetadata, (queryBuilder) => {
|
||||
void queryBuilder
|
||||
.on(`${TableName.Identity}.id`, `${TableName.IdentityMetadata}.identityId`)
|
||||
.andOn(`${TableName.Project}.orgId`, `${TableName.IdentityMetadata}.orgId`);
|
||||
.on(`${TableName.Membership}.actorIdentityId`, `${TableName.IdentityMetadata}.identityId`)
|
||||
.andOn(`${TableName.Membership}.scopeOrgId`, `${TableName.IdentityMetadata}.orgId`);
|
||||
})
|
||||
.where(`${TableName.IdentityProjectMembership}.projectId`, projectId)
|
||||
.select(selectAllTableCols(TableName.IdentityProjectMembershipRole))
|
||||
.where(`${TableName.Membership}.scopeOrgId`, orgId)
|
||||
.where(`${TableName.Membership}.scope`, AccessScope.Project)
|
||||
.where(`${TableName.Membership}.scopeProjectId`, projectId)
|
||||
.select(selectAllTableCols(TableName.MembershipRole))
|
||||
.select(
|
||||
db.ref("id").withSchema(TableName.IdentityProjectMembership).as("membershipId"),
|
||||
db.ref("id").withSchema(TableName.Membership).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("createdAt").withSchema(TableName.Membership).as("membershipCreatedAt"),
|
||||
db.ref("updatedAt").withSchema(TableName.Membership).as("membershipUpdatedAt"),
|
||||
db.ref("slug").withSchema(TableName.Role).as("customRoleSlug"),
|
||||
db.ref("permissions").withSchema(TableName.Role),
|
||||
db.ref("id").withSchema(TableName.AdditionalPrivilege).as("identityApId"),
|
||||
db.ref("permissions").withSchema(TableName.AdditionalPrivilege).as("identityApPermissions"),
|
||||
db.ref("temporaryMode").withSchema(TableName.AdditionalPrivilege).as("identityApTemporaryMode"),
|
||||
db.ref("isTemporary").withSchema(TableName.AdditionalPrivilege).as("identityApIsTemporary"),
|
||||
db.ref("temporaryRange").withSchema(TableName.AdditionalPrivilege).as("identityApTemporaryRange"),
|
||||
db
|
||||
.ref("temporaryAccessStartTime")
|
||||
.withSchema(TableName.IdentityProjectAdditionalPrivilege)
|
||||
.withSchema(TableName.AdditionalPrivilege)
|
||||
.as("identityApTemporaryAccessStartTime"),
|
||||
db
|
||||
.ref("temporaryAccessEndTime")
|
||||
.withSchema(TableName.IdentityProjectAdditionalPrivilege)
|
||||
.withSchema(TableName.AdditionalPrivilege)
|
||||
.as("identityApTemporaryAccessEndTime"),
|
||||
db.ref("id").withSchema(TableName.IdentityMetadata).as("metadataId"),
|
||||
db.ref("key").withSchema(TableName.IdentityMetadata).as("metadataKey"),
|
||||
@@ -838,15 +761,7 @@ export const permissionDALFactory = (db: TDbClient): TPermissionDALFactory => {
|
||||
const permissions = sqlNestRelationships({
|
||||
data: docs,
|
||||
key: "identityId",
|
||||
parentMapper: ({
|
||||
membershipId,
|
||||
membershipCreatedAt,
|
||||
membershipUpdatedAt,
|
||||
orgId,
|
||||
identityName,
|
||||
projectType,
|
||||
identityId
|
||||
}) => ({
|
||||
parentMapper: ({ membershipId, membershipCreatedAt, membershipUpdatedAt, identityName, identityId }) => ({
|
||||
id: membershipId,
|
||||
identityId,
|
||||
username: identityName,
|
||||
@@ -854,7 +769,6 @@ export const permissionDALFactory = (db: TDbClient): TPermissionDALFactory => {
|
||||
createdAt: membershipCreatedAt,
|
||||
updatedAt: membershipUpdatedAt,
|
||||
orgId,
|
||||
projectType,
|
||||
// just a prefilled value
|
||||
orgAuthEnforced: false
|
||||
}),
|
||||
|
||||
@@ -1262,7 +1262,12 @@ export const registerRoutes = async (
|
||||
projectTemplateService,
|
||||
smtpService,
|
||||
reminderService,
|
||||
notificationService
|
||||
notificationService,
|
||||
membershipGroupDAL,
|
||||
membershipIdentityDAL,
|
||||
membershipRoleDAL,
|
||||
membershipUserDAL,
|
||||
roleDAL
|
||||
});
|
||||
|
||||
const projectEnvService = projectEnvServiceFactory({
|
||||
|
||||
@@ -2,9 +2,11 @@ import { z } from "zod";
|
||||
|
||||
import {
|
||||
AccessScope,
|
||||
OrgMembershipRole,
|
||||
OrgMembershipsSchema,
|
||||
ProjectMembershipsSchema,
|
||||
ProjectUserMembershipRolesSchema,
|
||||
TemporaryPermissionMode,
|
||||
UserEncryptionKeysSchema,
|
||||
UsersSchema
|
||||
} from "@app/db/schemas";
|
||||
@@ -14,7 +16,6 @@ import { ms } from "@app/lib/ms";
|
||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
import { ProjectUserMembershipTemporaryMode } from "@app/services/project-membership/project-membership-types";
|
||||
|
||||
export const registerDeprecatedProjectMembershipRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
@@ -155,7 +156,7 @@ export const registerDeprecatedProjectMembershipRouter = async (server: FastifyZ
|
||||
membership: {
|
||||
...membership,
|
||||
userId,
|
||||
projectId: req.params.workspacId
|
||||
projectId: req.params.workspaceId
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -273,7 +274,10 @@ export const registerDeprecatedProjectMembershipRouter = async (server: FastifyZ
|
||||
}
|
||||
});
|
||||
|
||||
return { data, success: true };
|
||||
return {
|
||||
data: data.map((el) => ({ ...el, orgId: req.permission.orgId, role: OrgMembershipRole.Member })),
|
||||
success: true
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
@@ -307,7 +311,7 @@ export const registerDeprecatedProjectMembershipRouter = async (server: FastifyZ
|
||||
z.object({
|
||||
role: z.string(),
|
||||
isTemporary: z.literal(true),
|
||||
temporaryMode: z.nativeEnum(ProjectUserMembershipTemporaryMode),
|
||||
temporaryMode: z.nativeEnum(TemporaryPermissionMode),
|
||||
temporaryRange: z.string().refine((val) => ms(val) > 0, "Temporary range must be a positive number"),
|
||||
temporaryAccessStartTime: z.string().datetime()
|
||||
})
|
||||
@@ -336,7 +340,7 @@ export const registerDeprecatedProjectMembershipRouter = async (server: FastifyZ
|
||||
scopeData: {
|
||||
scope: AccessScope.Project,
|
||||
orgId: req.permission.orgId,
|
||||
projectId: req.params.projectId
|
||||
projectId: req.params.workspaceId
|
||||
},
|
||||
selector: {
|
||||
userId
|
||||
@@ -375,13 +379,22 @@ export const registerDeprecatedProjectMembershipRouter = async (server: FastifyZ
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const membership = await server.services.projectMembership.deleteProjectMembership({
|
||||
actorId: req.permission.id,
|
||||
actor: req.permission.type,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
projectId: req.params.workspaceId,
|
||||
membershipId: req.params.membershipId
|
||||
const { userId } = await server.services.convertor.userMembershipIdToUserId(
|
||||
req.params.membershipId,
|
||||
AccessScope.Project,
|
||||
req.permission.orgId
|
||||
);
|
||||
|
||||
const { membership } = await server.services.membershipUser.deleteMembership({
|
||||
permission: req.permission,
|
||||
scopeData: {
|
||||
scope: AccessScope.Project,
|
||||
orgId: req.permission.orgId,
|
||||
projectId: req.params.workspaceId
|
||||
},
|
||||
selector: {
|
||||
userId
|
||||
}
|
||||
});
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
@@ -390,12 +403,19 @@ export const registerDeprecatedProjectMembershipRouter = async (server: FastifyZ
|
||||
event: {
|
||||
type: EventType.REMOVE_PROJECT_MEMBER,
|
||||
metadata: {
|
||||
userId: membership.userId,
|
||||
userId: membership.actorUserId as string,
|
||||
email: ""
|
||||
}
|
||||
}
|
||||
});
|
||||
return { membership };
|
||||
|
||||
return {
|
||||
membership: {
|
||||
...membership,
|
||||
userId,
|
||||
projectId: req.params.workspaceId
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -86,7 +86,7 @@ export const registerOrgAdminRouter = async (server: FastifyZodProvider) => {
|
||||
});
|
||||
}
|
||||
|
||||
return { membership };
|
||||
return { membership: { ...membership, userId: req.permission.id, projectId: req.params.projectId } };
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// eslint-disable-next-line simple-import-sort/imports
|
||||
import { RawRule } from "@casl/ability";
|
||||
import { packRules } from "@casl/ability/extra";
|
||||
|
||||
@@ -23,6 +24,7 @@ import {
|
||||
import { newNamespaceAdditionalPrivilegesFactory } from "./namespace/namespace-additional-privilege-factory";
|
||||
import { newOrgAdditionalPrivilegesFactory } from "./org/org-additional-privilege-factory";
|
||||
import { newProjectAdditionalPrivilegesFactory } from "./project/project-additional-privilege-factory";
|
||||
import { ActorType } from "../auth/auth-type";
|
||||
|
||||
type TAdditionalPrivilegeServiceFactoryDep = {
|
||||
additionalPrivilegeDAL: TAdditionalPrivilegeDALFactory;
|
||||
@@ -52,11 +54,14 @@ export const additionalPrivilegeServiceFactory = ({
|
||||
const createAdditionalPrivilege = async (dto: TCreateAdditionalPrivilegesDTO) => {
|
||||
const { scopeData, data } = dto;
|
||||
const factory = scopeFactory[scopeData.scope];
|
||||
const { membershipId } = await factory.onCreateAdditionalPrivilegesGuard(dto);
|
||||
await factory.onCreateAdditionalPrivilegesGuard(dto);
|
||||
const scope = factory.getScopeField(dto.scopeData);
|
||||
const dbActorField = data.actorType === ActorType.IDENTITY ? "actorIdentityId" : "actorUserId";
|
||||
|
||||
const existingSlug = await additionalPrivilegeDAL.findOne({
|
||||
name: data.name,
|
||||
membershipId
|
||||
[dbActorField]: data.actorId,
|
||||
[scope.key]: scope.value
|
||||
});
|
||||
if (existingSlug) throw new BadRequestError({ message: `Additional privilege with name ${data.name} exist` });
|
||||
|
||||
@@ -66,8 +71,9 @@ export const additionalPrivilegeServiceFactory = ({
|
||||
|
||||
if (!data.isTemporary) {
|
||||
const additionalPrivilege = await additionalPrivilegeDAL.create({
|
||||
membershipId,
|
||||
name: data.name,
|
||||
[dbActorField]: data.actorId,
|
||||
[scope.key]: scope.value,
|
||||
isTemporary: data.isTemporary,
|
||||
permissions: JSON.stringify(packRules(data.permissions as RawRule[]))
|
||||
});
|
||||
@@ -83,7 +89,8 @@ export const additionalPrivilegeServiceFactory = ({
|
||||
|
||||
const relativeTempAllocatedTimeInMs = ms(data.temporaryRange);
|
||||
const additionalPrivilege = await additionalPrivilegeDAL.create({
|
||||
membershipId,
|
||||
[dbActorField]: data.actorId,
|
||||
[scope.key]: scope.value,
|
||||
name: data.name,
|
||||
isTemporary: data.isTemporary,
|
||||
permissions: data.permissions,
|
||||
@@ -103,11 +110,14 @@ export const additionalPrivilegeServiceFactory = ({
|
||||
const updateAdditionalPrivilege = async (dto: TUpdateAdditionalPrivilegesDTO) => {
|
||||
const { scopeData, data } = dto;
|
||||
const factory = scopeFactory[scopeData.scope];
|
||||
const { membershipId } = await factory.onUpdateAdditionalPrivilegesGuard(dto);
|
||||
await factory.onUpdateAdditionalPrivilegesGuard(dto);
|
||||
const scope = factory.getScopeField(dto.scopeData);
|
||||
const dbActorField = dto.selector.actorType === ActorType.IDENTITY ? "actorIdentityId" : "actorUserId";
|
||||
|
||||
const existingPrivilege = await additionalPrivilegeDAL.findOne({
|
||||
id: dto.selector.id,
|
||||
membershipId
|
||||
[dbActorField]: dto.selector.actorId,
|
||||
[scope.key]: scope.value
|
||||
});
|
||||
if (!existingPrivilege)
|
||||
throw new NotFoundError({ message: `Additional privilege with name ${data.name} doesn't exist` });
|
||||
@@ -135,8 +145,7 @@ export const additionalPrivilegeServiceFactory = ({
|
||||
}
|
||||
|
||||
const relativeTempAllocatedTimeInMs = ms(updatedData.temporaryRange);
|
||||
const additionalPrivilege = await additionalPrivilegeDAL.create({
|
||||
membershipId,
|
||||
const additionalPrivilege = await additionalPrivilegeDAL.updateById(existingPrivilege.id, {
|
||||
name: updatedData.name,
|
||||
isTemporary: updatedData.isTemporary,
|
||||
permissions: updatedData.permissions,
|
||||
@@ -156,11 +165,14 @@ export const additionalPrivilegeServiceFactory = ({
|
||||
const deleteAdditionalPrivilege = async (dto: TDeleteAdditionalPrivilegesDTO) => {
|
||||
const { scopeData, selector } = dto;
|
||||
const factory = scopeFactory[scopeData.scope];
|
||||
const { membershipId } = await factory.onDeleteAdditionalPrivilegesGuard(dto);
|
||||
await factory.onDeleteAdditionalPrivilegesGuard(dto);
|
||||
const scope = factory.getScopeField(dto.scopeData);
|
||||
const dbActorField = dto.selector.actorType === ActorType.IDENTITY ? "actorIdentityId" : "actorUserId";
|
||||
|
||||
const existingPrivilege = await additionalPrivilegeDAL.findOne({
|
||||
id: selector.id,
|
||||
membershipId
|
||||
[dbActorField]: dto.selector.actorId,
|
||||
[scope.key]: scope.value
|
||||
});
|
||||
if (!existingPrivilege)
|
||||
throw new NotFoundError({ message: `Additional privilege with id ${selector.id} doesn't exist` });
|
||||
@@ -174,10 +186,14 @@ export const additionalPrivilegeServiceFactory = ({
|
||||
const getAdditionalPrivilegeById = async (dto: TGetAdditionalPrivilegesByIdDTO) => {
|
||||
const { scopeData, selector } = dto;
|
||||
const factory = scopeFactory[scopeData.scope];
|
||||
const { membershipId } = await factory.onGetAdditionalPrivilegesByIdGuard(dto);
|
||||
await factory.onGetAdditionalPrivilegesByIdGuard(dto);
|
||||
const scope = factory.getScopeField(dto.scopeData);
|
||||
const dbActorField = dto.selector.actorType === ActorType.IDENTITY ? "actorIdentityId" : "actorUserId";
|
||||
|
||||
const additionalPrivilege = await additionalPrivilegeDAL.findOne({
|
||||
id: selector.id,
|
||||
membershipId
|
||||
[dbActorField]: dto.selector.actorId,
|
||||
[scope.key]: scope.value
|
||||
});
|
||||
if (!additionalPrivilege)
|
||||
throw new NotFoundError({ message: `Additional privilege with id ${selector.id} doesn't exist` });
|
||||
@@ -190,10 +206,14 @@ export const additionalPrivilegeServiceFactory = ({
|
||||
const getAdditionalPrivilegeByName = async (dto: TGetAdditionalPrivilegesByNameDTO) => {
|
||||
const { scopeData, selector } = dto;
|
||||
const factory = scopeFactory[scopeData.scope];
|
||||
const { membershipId } = await factory.onGetAdditionalPrivilegesByIdGuard(dto);
|
||||
await factory.onGetAdditionalPrivilegesByIdGuard(dto);
|
||||
const dbActorField = dto.selector.actorType === ActorType.IDENTITY ? "actorIdentityId" : "actorUserId";
|
||||
const scope = factory.getScopeField(dto.scopeData);
|
||||
|
||||
const additionalPrivilege = await additionalPrivilegeDAL.findOne({
|
||||
name: selector.name,
|
||||
membershipId
|
||||
[dbActorField]: dto.selector.actorId,
|
||||
[scope.key]: scope.value
|
||||
});
|
||||
if (!additionalPrivilege)
|
||||
throw new NotFoundError({ message: `Additional privilege with name ${selector.name} doesn't exist` });
|
||||
@@ -206,9 +226,13 @@ export const additionalPrivilegeServiceFactory = ({
|
||||
const listAdditionalPrivileges = async (dto: TListAdditionalPrivilegesDTO) => {
|
||||
const { scopeData } = dto;
|
||||
const factory = scopeFactory[scopeData.scope];
|
||||
const { membershipId } = await factory.onListAdditionalPrivilegesGuard(dto);
|
||||
await factory.onListAdditionalPrivilegesGuard(dto);
|
||||
const scope = factory.getScopeField(dto.scopeData);
|
||||
const dbActorField = dto.selector.actorType === ActorType.IDENTITY ? "actorIdentityId" : "actorUserId";
|
||||
|
||||
const additionalPrivileges = await additionalPrivilegeDAL.find({
|
||||
membershipId
|
||||
[dbActorField]: dto.selector.actorId,
|
||||
[scope.key]: scope.value
|
||||
});
|
||||
|
||||
return {
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
import { AccessScopeData, MembershipActors, TemporaryPermissionMode } from "@app/db/schemas";
|
||||
import { AccessScopeData, TemporaryPermissionMode } from "@app/db/schemas";
|
||||
import { OrgServiceActor } from "@app/lib/types";
|
||||
|
||||
import { ActorType } from "../auth/auth-type";
|
||||
|
||||
export interface TAdditionalPrivilegesScopeFactory {
|
||||
onCreateAdditionalPrivilegesGuard: (arg: TCreateAdditionalPrivilegesDTO) => Promise<{ membershipId: string }>;
|
||||
onUpdateAdditionalPrivilegesGuard: (arg: TUpdateAdditionalPrivilegesDTO) => Promise<{ membershipId: string }>;
|
||||
onDeleteAdditionalPrivilegesGuard: (arg: TDeleteAdditionalPrivilegesDTO) => Promise<{ membershipId: string }>;
|
||||
onListAdditionalPrivilegesGuard: (arg: TListAdditionalPrivilegesDTO) => Promise<{ membershipId: string }>;
|
||||
onCreateAdditionalPrivilegesGuard: (arg: TCreateAdditionalPrivilegesDTO) => Promise<void>;
|
||||
onUpdateAdditionalPrivilegesGuard: (arg: TUpdateAdditionalPrivilegesDTO) => Promise<void>;
|
||||
onDeleteAdditionalPrivilegesGuard: (arg: TDeleteAdditionalPrivilegesDTO) => Promise<void>;
|
||||
onListAdditionalPrivilegesGuard: (arg: TListAdditionalPrivilegesDTO) => Promise<void>;
|
||||
onGetAdditionalPrivilegesByIdGuard: (
|
||||
arg: TGetAdditionalPrivilegesByIdDTO | TGetAdditionalPrivilegesByNameDTO
|
||||
) => Promise<{ membershipId: string }>;
|
||||
) => Promise<void>;
|
||||
getScopeField: (scope: AccessScopeData) => { key: "orgId" | "namespaceId" | "projectId"; value: string };
|
||||
}
|
||||
|
||||
@@ -17,7 +19,7 @@ export type TCreateAdditionalPrivilegesDTO = {
|
||||
scopeData: AccessScopeData;
|
||||
data: {
|
||||
actorId: string;
|
||||
actorType: MembershipActors;
|
||||
actorType: ActorType.USER | ActorType.IDENTITY;
|
||||
name: string;
|
||||
permissions: unknown;
|
||||
isTemporary: boolean;
|
||||
@@ -33,7 +35,7 @@ export type TUpdateAdditionalPrivilegesDTO = {
|
||||
selector: {
|
||||
id: string;
|
||||
actorId: string;
|
||||
actorType: MembershipActors;
|
||||
actorType: ActorType.USER | ActorType.IDENTITY;
|
||||
};
|
||||
data: Partial<{
|
||||
name: string;
|
||||
@@ -50,7 +52,7 @@ export type TListAdditionalPrivilegesDTO = {
|
||||
scopeData: AccessScopeData;
|
||||
selector: {
|
||||
actorId: string;
|
||||
actorType: MembershipActors;
|
||||
actorType: ActorType.USER | ActorType.IDENTITY;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -60,7 +62,7 @@ export type TDeleteAdditionalPrivilegesDTO = {
|
||||
selector: {
|
||||
id: string;
|
||||
actorId: string;
|
||||
actorType: MembershipActors;
|
||||
actorType: ActorType.USER | ActorType.IDENTITY;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -70,7 +72,7 @@ export type TGetAdditionalPrivilegesByIdDTO = {
|
||||
selector: {
|
||||
id: string;
|
||||
actorId: string;
|
||||
actorType: MembershipActors;
|
||||
actorType: ActorType.USER | ActorType.IDENTITY;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -80,6 +82,6 @@ export type TGetAdditionalPrivilegesByNameDTO = {
|
||||
selector: {
|
||||
name: string;
|
||||
actorId: string;
|
||||
actorType: MembershipActors;
|
||||
actorType: ActorType.USER | ActorType.IDENTITY;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ForbiddenError } from "@casl/ability";
|
||||
|
||||
import { AccessScope, ActionProjectType, MembershipActors } from "@app/db/schemas";
|
||||
import { AccessScope, ActionProjectType } from "@app/db/schemas";
|
||||
import {
|
||||
constructPermissionErrorMessage,
|
||||
validatePrivilegeChangeOperation
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
ProjectPermissionMemberActions,
|
||||
ProjectPermissionSub
|
||||
} from "@app/ee/services/permission/project-permission";
|
||||
import { BadRequestError, InternalServerError, PermissionBoundaryError } from "@app/lib/errors";
|
||||
import { BadRequestError, PermissionBoundaryError } from "@app/lib/errors";
|
||||
import { OrgServiceActor } from "@app/lib/types";
|
||||
import { ActorType } from "@app/services/auth/auth-type";
|
||||
import { TMembershipDALFactory } from "@app/services/membership/membership-dal";
|
||||
@@ -41,16 +41,6 @@ export const newProjectAdditionalPrivilegesFactory = ({
|
||||
});
|
||||
};
|
||||
|
||||
const $getActorType = (type: MembershipActors) => {
|
||||
if (type === MembershipActors.Group)
|
||||
throw new InternalServerError({ message: "Group additional privilege not implemented for projects" });
|
||||
|
||||
if (type === MembershipActors.Identity) return ActorType.IDENTITY;
|
||||
if (type === MembershipActors.User) return ActorType.USER;
|
||||
|
||||
throw new InternalServerError({ message: `Group additional privilege not implemented for actor: ${String(type)}` });
|
||||
};
|
||||
|
||||
const getScopeField: TAdditionalPrivilegesScopeFactory["getScopeField"] = (dto) => {
|
||||
if (dto.scope === AccessScope.Project) {
|
||||
return { key: "projectId" as const, value: dto.projectId };
|
||||
@@ -61,11 +51,11 @@ export const newProjectAdditionalPrivilegesFactory = ({
|
||||
const onCreateAdditionalPrivilegesGuard: TAdditionalPrivilegesScopeFactory["onCreateAdditionalPrivilegesGuard"] =
|
||||
async (dto) => {
|
||||
const scope = getScopeField(dto.scopeData);
|
||||
const actorType = $getActorType(dto.data.actorType);
|
||||
|
||||
const { permission } = await $getPermission(dto.permission, scope.value);
|
||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionMemberActions.Edit, ProjectPermissionSub.Member);
|
||||
|
||||
const { actorType } = dto.data;
|
||||
const { shouldUseNewPrivilegeSystem } = await orgDAL.findById(dto.permission.orgId);
|
||||
const { permission: targetUserPermission, memberships } = await $getPermission(
|
||||
{ ...dto.permission, type: actorType, id: dto.data.actorId },
|
||||
@@ -100,13 +90,12 @@ export const newProjectAdditionalPrivilegesFactory = ({
|
||||
(el) => el[actorType === ActorType.IDENTITY ? "actorIdentityId" : "actorUserId"] === dto.data.actorId
|
||||
);
|
||||
if (!membership) throw new BadRequestError({ message: "Actor doesn't have membership" });
|
||||
return { membershipId: membership.id };
|
||||
};
|
||||
|
||||
const onUpdateAdditionalPrivilegesGuard: TAdditionalPrivilegesScopeFactory["onUpdateAdditionalPrivilegesGuard"] =
|
||||
async (dto) => {
|
||||
const scope = getScopeField(dto.scopeData);
|
||||
const actorType = $getActorType(dto.selector.actorType);
|
||||
const { actorType } = dto.selector;
|
||||
|
||||
const { permission } = await $getPermission(dto.permission, scope.value);
|
||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionMemberActions.Edit, ProjectPermissionSub.Member);
|
||||
@@ -145,13 +134,12 @@ export const newProjectAdditionalPrivilegesFactory = ({
|
||||
(el) => el[actorType === ActorType.IDENTITY ? "actorIdentityId" : "actorUserId"] === dto.selector.actorId
|
||||
);
|
||||
if (!membership) throw new BadRequestError({ message: "Actor doesn't have membership" });
|
||||
return { membershipId: membership.id };
|
||||
};
|
||||
|
||||
const onDeleteAdditionalPrivilegesGuard: TAdditionalPrivilegesScopeFactory["onDeleteAdditionalPrivilegesGuard"] =
|
||||
async (dto) => {
|
||||
const scope = getScopeField(dto.scopeData);
|
||||
const actorType = $getActorType(dto.selector.actorType);
|
||||
const { actorType } = dto.selector;
|
||||
|
||||
const { permission } = await $getPermission(dto.permission, scope.value);
|
||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionMemberActions.Edit, ProjectPermissionSub.Member);
|
||||
@@ -163,14 +151,13 @@ export const newProjectAdditionalPrivilegesFactory = ({
|
||||
});
|
||||
|
||||
if (!membership) throw new BadRequestError({ message: "Actor doesn't have membership" });
|
||||
return { membershipId: membership.id };
|
||||
};
|
||||
|
||||
const onListAdditionalPrivilegesGuard: TAdditionalPrivilegesScopeFactory["onListAdditionalPrivilegesGuard"] = async (
|
||||
dto
|
||||
) => {
|
||||
const scope = getScopeField(dto.scopeData);
|
||||
const actorType = $getActorType(dto.selector.actorType);
|
||||
const { actorType } = dto.selector;
|
||||
|
||||
const permissionSet =
|
||||
actorType === ActorType.USER
|
||||
@@ -186,13 +173,12 @@ export const newProjectAdditionalPrivilegesFactory = ({
|
||||
});
|
||||
|
||||
if (!membership) throw new BadRequestError({ message: "Actor doesn't have membership" });
|
||||
return { membershipId: membership.id };
|
||||
};
|
||||
|
||||
const onGetAdditionalPrivilegesByIdGuard: TAdditionalPrivilegesScopeFactory["onGetAdditionalPrivilegesByIdGuard"] =
|
||||
async (dto) => {
|
||||
const scope = getScopeField(dto.scopeData);
|
||||
const actorType = $getActorType(dto.selector.actorType);
|
||||
const { actorType } = dto.selector;
|
||||
|
||||
const permissionSet =
|
||||
actorType === ActorType.USER
|
||||
@@ -208,7 +194,6 @@ export const newProjectAdditionalPrivilegesFactory = ({
|
||||
});
|
||||
|
||||
if (!membership) throw new BadRequestError({ message: "Actor doesn't have membership" });
|
||||
return { membershipId: membership.id };
|
||||
};
|
||||
|
||||
return {
|
||||
|
||||
@@ -86,18 +86,20 @@ export const convertorServiceFactory = ({
|
||||
return { membershipId: membership.id, membership };
|
||||
};
|
||||
|
||||
const additionalPrivilegeIdToMembershipId = async (privilegeId: string, scope: AccessScope, orgId: string) => {
|
||||
const membership = await additionalPrivilegeDAL.getMembershipById(privilegeId);
|
||||
if (!membership || membership.scope !== scope || membership.scopeOrgId !== orgId) {
|
||||
const additionalPrivilegeIdToDoc = async (privilegeId: string) => {
|
||||
const doc = await additionalPrivilegeDAL.findOne({
|
||||
id: privilegeId
|
||||
});
|
||||
if (!doc) {
|
||||
throw new NotFoundError({ message: `Privilege with id ${privilegeId} not found` });
|
||||
}
|
||||
|
||||
return { membership, membershipId: membership.id };
|
||||
return { privilege: doc };
|
||||
};
|
||||
const additionalPrivilegeNameToId = async (privilegeName: string, membershipId: string) => {
|
||||
const additionalPrivilegeNameToDoc = async (privilegeName: string, projectId: string) => {
|
||||
const privilege = await additionalPrivilegeDAL.findOne({
|
||||
name: privilegeName,
|
||||
membershipId
|
||||
projectId
|
||||
});
|
||||
if (!privilege) {
|
||||
throw new NotFoundError({ message: `Privilege with slug ${privilegeName} not found` });
|
||||
@@ -111,8 +113,8 @@ export const convertorServiceFactory = ({
|
||||
userMembershipIdToUserId,
|
||||
groupMembershipIdToGroupId,
|
||||
identityMembershipIdToIdentityId,
|
||||
additionalPrivilegeIdToMembershipId,
|
||||
additionalPrivilegeNameToId,
|
||||
additionalPrivilegeIdToDoc,
|
||||
additionalPrivilegeNameToDoc,
|
||||
identityIdToMembershipId
|
||||
};
|
||||
};
|
||||
|
||||
@@ -123,7 +123,8 @@ export const orgAdminServiceFactory = ({
|
||||
{
|
||||
scopeProjectId: projectId,
|
||||
actorUserId: actorId,
|
||||
scope: AccessScope.Project
|
||||
scope: AccessScope.Project,
|
||||
scopeOrgId: actorOrgId
|
||||
},
|
||||
tx
|
||||
);
|
||||
|
||||
@@ -305,7 +305,7 @@ export const orgDALFactory = (db: TDbClient) => {
|
||||
.select(
|
||||
db.ref("id").withSchema(TableName.Membership),
|
||||
db.ref("inviteEmail").withSchema(TableName.Membership),
|
||||
db.ref("actorOrgId").withSchema(TableName.Membership).as("orgId"),
|
||||
db.ref("scopeOrgId").withSchema(TableName.Membership).as("orgId"),
|
||||
db.ref("role").withSchema(TableName.MembershipRole),
|
||||
db.ref("customRoleId").withSchema(TableName.MembershipRole).as("roleId"),
|
||||
db.ref("status").withSchema(TableName.Membership),
|
||||
|
||||
@@ -2,7 +2,7 @@ import { AccessScope, ActionProjectType, TableName } from "@app/db/schemas";
|
||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
|
||||
import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { validateHandlebarTemplate } from "@app/lib/template/validate-handlebars";
|
||||
import { unpackPermissions } from "@app/server/routes/sanitizedSchema/permission";
|
||||
import { UnpackedPermissionSchema, unpackPermissions } from "@app/server/routes/sanitizedSchema/permission";
|
||||
|
||||
import { newNamespaceRoleFactory } from "./namespace/namespace-role-factory";
|
||||
import { newOrgRoleFactory } from "./org/org-role-factory";
|
||||
@@ -188,7 +188,7 @@ export const roleServiceFactory = ({
|
||||
const predefinedRole = await factory.getPredefinedRoles(scopeData);
|
||||
const selectedRole = predefinedRole.find((el) => el.slug === dto.selector.slug);
|
||||
if (!selectedRole) throw new BadRequestError({ message: `Role with slug ${dto.selector.slug} not found` });
|
||||
return selectedRole;
|
||||
return { ...selectedRole, permissions: UnpackedPermissionSchema.array().parse(selectedRole.permissions) };
|
||||
}
|
||||
|
||||
const role = await roleDAL.findOne({
|
||||
|
||||
@@ -946,12 +946,13 @@ export const superAdminServiceFactory = ({
|
||||
}
|
||||
}
|
||||
|
||||
const membershipRole = await membershipRoleDAL.findOne({ membershipId });
|
||||
const [organizationMembership] = await membershipUserDAL.delete({
|
||||
scopeOrgId: organizationId,
|
||||
scope: AccessScope.Organization,
|
||||
id: membershipId
|
||||
});
|
||||
return organizationMembership;
|
||||
return { ...organizationMembership, role: membershipRole.role, orgId: organizationId };
|
||||
};
|
||||
|
||||
const joinOrganization = async (orgId: string, actor: OrgServiceActor) => {
|
||||
@@ -988,14 +989,14 @@ export const superAdminServiceFactory = ({
|
||||
},
|
||||
tx
|
||||
);
|
||||
await membershipRoleDAL.create(
|
||||
const membershipRole = await membershipRoleDAL.create(
|
||||
{
|
||||
membershipId: membership.id,
|
||||
role: OrgMembershipRole.Admin
|
||||
},
|
||||
tx
|
||||
);
|
||||
return membership;
|
||||
return { ...membership, role: membershipRole.role, orgId: org.id };
|
||||
});
|
||||
|
||||
return orgMembership;
|
||||
@@ -1052,7 +1053,7 @@ export const superAdminServiceFactory = ({
|
||||
}
|
||||
});
|
||||
|
||||
return orgMembership;
|
||||
return { ...orgMembership, orgId: organizationId, role: "" };
|
||||
};
|
||||
|
||||
const getIdentities = async ({ offset, limit, searchTerm }: TAdminGetIdentitiesDTO) => {
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
} from "@app/hooks/api/roles/queries";
|
||||
|
||||
import { OrgPermissionSet } from "./types";
|
||||
import { useCallback } from "react";
|
||||
|
||||
export const useOrgPermission = () => {
|
||||
const organizationId = useRouteContext({
|
||||
@@ -17,16 +18,24 @@ export const useOrgPermission = () => {
|
||||
select: (el) => el.organizationId
|
||||
});
|
||||
|
||||
const { data } = useSuspenseQuery({
|
||||
const {
|
||||
data: { permission, memberships = [] }
|
||||
} = useSuspenseQuery({
|
||||
queryKey: roleQueryKeys.getUserOrgPermissions({ orgId: organizationId }),
|
||||
queryFn: () => fetchUserOrgPermissions({ orgId: organizationId }),
|
||||
select: (res) => {
|
||||
const rule = unpackRules<RawRuleOf<MongoAbility<OrgPermissionSet>>>(res.permissions);
|
||||
const ability = createMongoAbility<OrgPermissionSet>(rule, { conditionsMatcher });
|
||||
return { permission: ability, membership: res.membership };
|
||||
return { permission: ability, memberships: res.memberships };
|
||||
},
|
||||
staleTime: Infinity
|
||||
});
|
||||
|
||||
return data;
|
||||
const hasOrgRole = useCallback(
|
||||
(role: string) =>
|
||||
memberships?.some((membership) => membership.roles.some((el) => role === el.role)),
|
||||
[]
|
||||
);
|
||||
|
||||
return { permission, memberships, hasOrgRole };
|
||||
};
|
||||
|
||||
@@ -20,7 +20,7 @@ export const useProjectPermission = () => {
|
||||
}
|
||||
|
||||
const {
|
||||
data: { permission, membership, assumedPrivilegeDetails }
|
||||
data: { permission, memberships, assumedPrivilegeDetails }
|
||||
} = useSuspenseQuery({
|
||||
queryKey: roleQueryKeys.getUserProjectPermissions({ projectId }),
|
||||
queryFn: () => fetchUserProjectPermissions({ projectId }),
|
||||
@@ -31,18 +31,16 @@ export const useProjectPermission = () => {
|
||||
return {
|
||||
permission: ability,
|
||||
assumedPrivilegeDetails: data.assumedPrivilegeDetails,
|
||||
membership: {
|
||||
...data.membership,
|
||||
roles: data.membership.roles.map(({ role }) => role)
|
||||
}
|
||||
memberships: data.memberships
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
const hasProjectRole = useCallback(
|
||||
(role: string) => membership?.roles?.includes(role) || false,
|
||||
(role: string) =>
|
||||
memberships?.some((membership) => membership.roles.some((el) => role === el.role)),
|
||||
[]
|
||||
);
|
||||
|
||||
return { permission, membership, hasProjectRole, assumedPrivilegeDetails };
|
||||
return { permission, memberships, hasProjectRole, assumedPrivilegeDetails };
|
||||
};
|
||||
|
||||
@@ -11,7 +11,7 @@ import { groupBy } from "@app/lib/fn/array";
|
||||
import { omit } from "@app/lib/fn/object";
|
||||
|
||||
import { ActorType } from "../auditLogs/enums";
|
||||
import { OrgUser, TProjectMembership } from "../users/types";
|
||||
import { TUserMembership } from "../users/types";
|
||||
import {
|
||||
TGetUserOrgPermissionsDTO,
|
||||
TGetUserProjectPermissionDTO,
|
||||
@@ -109,11 +109,11 @@ export const useGetOrgRole = (orgId: string, roleId: string) =>
|
||||
});
|
||||
|
||||
export const fetchUserOrgPermissions = async ({ orgId }: TGetUserOrgPermissionsDTO) => {
|
||||
if (orgId === "") return { permissions: [], membership: null };
|
||||
if (orgId === "") return { permissions: [], memberships: [] };
|
||||
|
||||
const { data } = await apiRequest.get<{
|
||||
permissions: PackRule<RawRuleOf<MongoAbility<OrgPermissionSet>>>[];
|
||||
membership: OrgUser;
|
||||
memberships: Array<TUserMembership & { roles: { role: string }[] }>;
|
||||
}>(`/api/v1/organization/${orgId}/permissions`);
|
||||
|
||||
return data;
|
||||
@@ -127,7 +127,7 @@ export const useGetUserOrgPermissions = ({ orgId }: TGetUserOrgPermissionsDTO) =
|
||||
select: (data) => {
|
||||
const rule = unpackRules<RawRuleOf<MongoAbility<OrgPermissionSet>>>(data.permissions);
|
||||
const ability = createMongoAbility<OrgPermissionSet>(rule, { conditionsMatcher });
|
||||
return { permission: ability, membership: data.membership };
|
||||
return { permission: ability, memberships: data.memberships };
|
||||
}
|
||||
});
|
||||
|
||||
@@ -135,7 +135,7 @@ export const fetchUserProjectPermissions = async ({ projectId }: TGetUserProject
|
||||
const { data } = await apiRequest.get<{
|
||||
data: {
|
||||
permissions: PackRule<RawRuleOf<MongoAbility<OrgPermissionSet>>>[];
|
||||
membership: Omit<TProjectMembership, "roles"> & { roles: { role: string }[] };
|
||||
memberships: Array<TUserMembership & { roles: { role: string }[] }>;
|
||||
assumedPrivilegeDetails?: {
|
||||
actorId: string;
|
||||
actorType: ActorType;
|
||||
@@ -181,11 +181,7 @@ export const useGetUserProjectPermissions = ({ projectId }: TGetUserProjectPermi
|
||||
};
|
||||
}
|
||||
});
|
||||
const membership = {
|
||||
...data.membership,
|
||||
roles: data.membership.roles.map(({ role }) => role)
|
||||
};
|
||||
|
||||
return { permission: ability, membership };
|
||||
return { permission: ability, memberships: data.memberships };
|
||||
}
|
||||
});
|
||||
|
||||
@@ -72,6 +72,13 @@ export type OrgUser = {
|
||||
lastLoginTime?: string;
|
||||
};
|
||||
|
||||
export type TUserMembership = {
|
||||
id: string;
|
||||
scope: string;
|
||||
scopeOrgId: string;
|
||||
actorUserId: string;
|
||||
};
|
||||
|
||||
export type TProjectMembership = {
|
||||
id: string;
|
||||
createdAt: string;
|
||||
|
||||
@@ -7,6 +7,7 @@ import { createNotification } from "@app/components/notifications";
|
||||
import { Button, Checkbox, Modal, ModalContent, Tooltip } from "@app/components/v2";
|
||||
import { useOrgPermission } from "@app/context";
|
||||
import { useUpgradePrivilegeSystem } from "@app/hooks/api";
|
||||
import { OrgMembershipRole } from "@app/helpers/roles";
|
||||
|
||||
const formSchema = z.object({
|
||||
isProjectPrivilegesUpdated: z.literal(true),
|
||||
@@ -21,7 +22,7 @@ type Props = {
|
||||
};
|
||||
|
||||
export const UpgradePrivilegeSystemModal = ({ isOpen, onOpenChange }: Props) => {
|
||||
const { membership } = useOrgPermission();
|
||||
const { hasOrgRole } = useOrgPermission();
|
||||
const [step, setStep] = useState<"info" | "upgrade">("info");
|
||||
|
||||
const {
|
||||
@@ -65,7 +66,7 @@ export const UpgradePrivilegeSystemModal = ({ isOpen, onOpenChange }: Props) =>
|
||||
setStep("info");
|
||||
};
|
||||
|
||||
const isAdmin = membership?.role === "admin";
|
||||
const isAdmin = hasOrgRole(OrgMembershipRole.Admin);
|
||||
|
||||
return (
|
||||
<Modal isOpen={isOpen} onOpenChange={handleClose}>
|
||||
@@ -274,7 +275,7 @@ export const UpgradePrivilegeSystemModal = ({ isOpen, onOpenChange }: Props) =>
|
||||
<Tooltip
|
||||
content={
|
||||
!isAdmin
|
||||
? `You cannot perform this upgrade because you are not an organization admin. (Your current role: ${membership?.role ?? "Unknown"})`
|
||||
? `You cannot perform this upgrade because you are not an organization admin.`
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
|
||||
@@ -4,12 +4,12 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { Button } from "@app/components/v2";
|
||||
import { useOrgPermission } from "@app/context";
|
||||
import { usePopUp } from "@app/hooks";
|
||||
import { ProjectMembershipRole } from "@app/hooks/api/roles/types";
|
||||
|
||||
import { SelectImportFromPlatformModal } from "./components/SelectImportFromPlatformModal";
|
||||
import { OrgMembershipRole } from "@app/helpers/roles";
|
||||
|
||||
export const ExternalMigrationsTab = () => {
|
||||
const { membership } = useOrgPermission();
|
||||
const { hasOrgRole } = useOrgPermission();
|
||||
|
||||
const { popUp, handlePopUpOpen, handlePopUpToggle } = usePopUp(["selectImportPlatform"] as const);
|
||||
|
||||
@@ -41,7 +41,7 @@ export const ExternalMigrationsTab = () => {
|
||||
onClick={() => {
|
||||
handlePopUpOpen("selectImportPlatform");
|
||||
}}
|
||||
isDisabled={membership?.role !== ProjectMembershipRole.Admin}
|
||||
isDisabled={hasOrgRole(OrgMembershipRole.Admin)}
|
||||
leftIcon={<FontAwesomeIcon icon={faPlus} />}
|
||||
>
|
||||
Import
|
||||
|
||||
@@ -6,12 +6,13 @@ import { useOrganization, useOrgPermission } from "@app/context";
|
||||
import { useDeleteOrgById } from "@app/hooks/api";
|
||||
import { clearSession } from "@app/hooks/api/users/queries";
|
||||
import { usePopUp } from "@app/hooks/usePopUp";
|
||||
import { OrgMembershipRole } from "@app/helpers/roles";
|
||||
|
||||
export const OrgDeleteSection = () => {
|
||||
const navigate = useNavigate();
|
||||
const { currentOrg } = useOrganization();
|
||||
|
||||
const { membership } = useOrgPermission();
|
||||
const { hasOrgRole } = useOrgPermission();
|
||||
|
||||
const { popUp, handlePopUpOpen, handlePopUpToggle } = usePopUp(["deleteOrg"] as const);
|
||||
|
||||
@@ -52,7 +53,7 @@ export const OrgDeleteSection = () => {
|
||||
variant="outline_bg"
|
||||
type="submit"
|
||||
onClick={() => handlePopUpOpen("deleteOrg")}
|
||||
isDisabled={Boolean(membership && membership.role !== "admin")}
|
||||
isDisabled={Boolean(!hasOrgRole(OrgMembershipRole.Admin))}
|
||||
>
|
||||
{`Delete ${currentOrg?.name}`}
|
||||
</Button>
|
||||
|
||||
@@ -3,14 +3,15 @@ import { useOrgPermission } from "@app/context";
|
||||
import { OrgDeleteSection } from "../OrgDeleteSection";
|
||||
import { OrgIncidentContactsSection } from "../OrgIncidentContactsSection";
|
||||
import { OrgNameChangeSection } from "../OrgNameChangeSection";
|
||||
import { OrgMembershipRole } from "@app/helpers/roles";
|
||||
|
||||
export const OrgGeneralTab = () => {
|
||||
const { membership } = useOrgPermission();
|
||||
const { hasOrgRole } = useOrgPermission();
|
||||
return (
|
||||
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-6">
|
||||
<OrgNameChangeSection />
|
||||
<OrgIncidentContactsSection />
|
||||
{membership && membership.role === "admin" && <OrgDeleteSection />}
|
||||
{hasOrgRole(OrgMembershipRole.Admin) && <OrgDeleteSection />}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -20,7 +20,7 @@ export const AuditLogsRetentionSection = () => {
|
||||
const { mutateAsync: updateAuditLogsRetention } = useUpdateWorkspaceAuditLogsRetention();
|
||||
|
||||
const { currentProject } = useProject();
|
||||
const { membership } = useProjectPermission();
|
||||
const { hasProjectRole } = useProjectPermission();
|
||||
const { subscription } = useSubscription();
|
||||
const { popUp, handlePopUpOpen, handlePopUpToggle } = usePopUp(["upgradePlan"] as const);
|
||||
|
||||
@@ -82,7 +82,7 @@ export const AuditLogsRetentionSection = () => {
|
||||
return null;
|
||||
}
|
||||
|
||||
const isAdmin = membership.roles.includes(ProjectMembershipRole.Admin);
|
||||
const isAdmin = hasProjectRole(ProjectMembershipRole.Admin);
|
||||
return (
|
||||
<>
|
||||
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
||||
|
||||
@@ -10,7 +10,8 @@ import {
|
||||
ProjectPermissionSub,
|
||||
useOrganization,
|
||||
useProject,
|
||||
useProjectPermission
|
||||
useProjectPermission,
|
||||
useUser
|
||||
} from "@app/context";
|
||||
import { useToggle } from "@app/hooks";
|
||||
import { useDeleteWorkspace, useGetWorkspaceUsers, useLeaveProject } from "@app/hooks/api";
|
||||
@@ -24,8 +25,9 @@ export const DeleteProjectSection = () => {
|
||||
"leaveWorkspace"
|
||||
] as const);
|
||||
|
||||
const { user } = useUser();
|
||||
const { currentOrg } = useOrganization();
|
||||
const { hasProjectRole, membership } = useProjectPermission();
|
||||
const { hasProjectRole } = useProjectPermission();
|
||||
const { currentProject } = useProject();
|
||||
const [isDeleting, setIsDeleting] = useToggle();
|
||||
const [isLeaving, setIsLeaving] = useToggle();
|
||||
@@ -39,14 +41,14 @@ export const DeleteProjectSection = () => {
|
||||
const isNoAccessMember = hasProjectRole("no-access");
|
||||
|
||||
const isOnlyAdminMember = useMemo(() => {
|
||||
if (!members || !membership || !hasProjectRole("admin")) return false;
|
||||
if (!members || !hasProjectRole("admin")) return false;
|
||||
|
||||
const adminMembers = members.filter(
|
||||
(member) => member.roles.map((r) => r.role).includes("admin") && member.id !== membership.id // exclude the current user
|
||||
(member) => member.roles.map((r) => r.role).includes("admin") && member.user.id !== user.id // exclude the current user
|
||||
);
|
||||
|
||||
return !adminMembers.length;
|
||||
}, [members, membership]);
|
||||
}, [members, user]);
|
||||
|
||||
const handleDeleteWorkspaceSubmit = async () => {
|
||||
setIsDeleting.on();
|
||||
|
||||
@@ -38,7 +38,7 @@ export const SecretV2MigrationSection = () => {
|
||||
currentProject?.upgradeStatus === ProjectUpgradeStatus.InProgress ? 2000 : false
|
||||
}
|
||||
);
|
||||
const { membership } = useProjectPermission();
|
||||
const { hasProjectRole } = useProjectPermission();
|
||||
const migrateProjectToV3 = useMigrateProjectToV3();
|
||||
const { handleSubmit, control, reset } = useForm({ resolver: zodResolver(formSchema) });
|
||||
useEffect(() => {
|
||||
@@ -81,7 +81,7 @@ export const SecretV2MigrationSection = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const isAdmin = membership?.roles.includes(ProjectMembershipRole.Admin);
|
||||
const isAdmin = hasProjectRole(ProjectMembershipRole.Admin);
|
||||
return (
|
||||
<div className="mt-4 flex max-w-2xl flex-col rounded-lg border border-primary/50 bg-primary/10 px-6 py-5">
|
||||
{isUpgrading && (
|
||||
|
||||
@@ -6,7 +6,7 @@ import { ProjectMembershipRole } from "@app/hooks/api/roles/types";
|
||||
|
||||
export const BackfillSecretReferenceSecretion = () => {
|
||||
const { currentProject } = useProject();
|
||||
const { membership } = useProjectPermission();
|
||||
const { hasProjectRole } = useProjectPermission();
|
||||
const backfillSecretReferences = useBackfillSecretReference();
|
||||
|
||||
if (!currentProject) return null;
|
||||
@@ -21,7 +21,7 @@ export const BackfillSecretReferenceSecretion = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const isAdmin = membership.roles.includes(ProjectMembershipRole.Admin);
|
||||
const isAdmin = hasProjectRole(ProjectMembershipRole.Admin);
|
||||
return (
|
||||
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
||||
<div className="flex w-full items-center justify-between">
|
||||
|
||||
@@ -18,7 +18,7 @@ export const PointInTimeVersionLimitSection = () => {
|
||||
const { mutateAsync: updateProject } = useUpdateProject();
|
||||
|
||||
const { currentProject, projectId } = useProject();
|
||||
const { membership } = useProjectPermission();
|
||||
const { hasProjectRole } = useProjectPermission();
|
||||
|
||||
const {
|
||||
control,
|
||||
@@ -52,7 +52,7 @@ export const PointInTimeVersionLimitSection = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const isAdmin = membership.roles.includes(ProjectMembershipRole.Admin);
|
||||
const isAdmin = hasProjectRole(ProjectMembershipRole.Admin);
|
||||
return (
|
||||
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
||||
<div className="flex w-full items-center justify-between">
|
||||
|
||||
@@ -24,7 +24,7 @@ type TForm = z.infer<typeof formSchema>;
|
||||
|
||||
export const SecretDetectionIgnoreValuesSection = () => {
|
||||
const { currentProject } = useProject();
|
||||
const { membership } = useProjectPermission();
|
||||
const { hasProjectRole } = useProjectPermission();
|
||||
const { mutateAsync: updateProject } = useUpdateProject();
|
||||
|
||||
const {
|
||||
@@ -73,7 +73,7 @@ export const SecretDetectionIgnoreValuesSection = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const isAdmin = membership.roles.includes(ProjectMembershipRole.Admin);
|
||||
const isAdmin = hasProjectRole(ProjectMembershipRole.Admin);
|
||||
|
||||
if (!currentProject) return null;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user