Compare commits

..

5 Commits

Author SHA1 Message Date
Daniel Hougaard
8bb68f9889 Update identity-project-service.ts 2025-04-10 17:53:17 +04:00
Daniel Hougaard
1c121ec30d feat(project-identity): get project identity by membership ID 2025-04-10 17:48:41 +04:00
Maidul Islam
8cbfeffe4c Merge pull request #3386 from Infisical/disable-ratelimits-onselfhost
Remove rate limits on self host
2025-04-09 21:01:51 -04:00
Akhil Mohan
2940300164 Merge pull request #3385 from akhilmhdh/feat/add-max-role
Added max to $OR in search function
2025-04-09 22:37:36 +05:30
=
9356ab7cbc feat: added max to search or 2025-04-09 22:04:31 +05:30
5 changed files with 110 additions and 3 deletions

View File

@@ -39,5 +39,5 @@ export type TSearchResource = {
};
export const buildSearchZodSchema = <T extends TSearchResource>(schema: z.ZodObject<T>) => {
return schema.extend({ $or: schema.array().optional() }).optional();
return schema.extend({ $or: schema.array().max(5).optional() }).optional();
};

View File

@@ -351,4 +351,56 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider)
return { identityMembership };
}
});
server.route({
method: "GET",
url: "/identity-memberships/:identityMembershipId",
config: {
rateLimit: readLimit
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
params: z.object({
identityMembershipId: z.string().trim()
}),
response: {
200: z.object({
identityMembership: z.object({
id: z.string(),
identityId: z.string(),
createdAt: z.date(),
updatedAt: z.date(),
roles: z.array(
z.object({
id: z.string(),
role: z.string(),
customRoleId: z.string().optional().nullable(),
customRoleName: z.string().optional().nullable(),
customRoleSlug: z.string().optional().nullable(),
isTemporary: z.boolean(),
temporaryMode: z.string().optional().nullable(),
temporaryRange: z.string().nullable().optional(),
temporaryAccessStartTime: z.date().nullable().optional(),
temporaryAccessEndTime: z.date().nullable().optional()
})
),
identity: IdentitiesSchema.pick({ name: true, id: true }).extend({
authMethods: z.array(z.string())
}),
project: SanitizedProjectSchema.pick({ name: true, id: true })
})
})
}
},
handler: async (req) => {
const identityMembership = await server.services.identityProject.getProjectIdentityByMembershipId({
actor: req.permission.type,
actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId,
identityMembershipId: req.params.identityMembershipId
});
return { identityMembership };
}
});
};

View File

@@ -21,6 +21,7 @@ import {
TCreateProjectIdentityDTO,
TDeleteProjectIdentityDTO,
TGetProjectIdentityByIdentityIdDTO,
TGetProjectIdentityByMembershipIdDTO,
TListProjectIdentityDTO,
TUpdateProjectIdentityDTO
} from "./identity-project-types";
@@ -370,11 +371,48 @@ export const identityProjectServiceFactory = ({
return identityMembership;
};
const getProjectIdentityByMembershipId = async ({
identityMembershipId,
actor,
actorId,
actorAuthMethod,
actorOrgId
}: TGetProjectIdentityByMembershipIdDTO) => {
const membership = await identityProjectDAL.findOne({ id: identityMembershipId });
if (!membership) {
throw new NotFoundError({
message: `Project membership with ID '${identityMembershipId}' not found`
});
}
const { permission } = await permissionService.getProjectPermission({
actor,
actorId,
projectId: membership.projectId,
actorAuthMethod,
actorOrgId,
actionProjectType: ActionProjectType.Any
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionIdentityActions.Read,
subject(ProjectPermissionSub.Identity, { identityId: membership.identityId })
);
const [identityMembership] = await identityProjectDAL.findByProjectId(membership.projectId, {
identityId: membership.identityId
});
return identityMembership;
};
return {
createProjectIdentity,
updateProjectIdentity,
deleteProjectIdentity,
listProjectIdentities,
getProjectIdentityByIdentityId
getProjectIdentityByIdentityId,
getProjectIdentityByMembershipId
};
};

View File

@@ -52,6 +52,10 @@ export type TGetProjectIdentityByIdentityIdDTO = {
identityId: string;
} & TProjectPermission;
export type TGetProjectIdentityByMembershipIdDTO = {
identityMembershipId: string;
} & Omit<TProjectPermission, "projectId">;
export enum ProjectIdentityOrderBy {
Name = "name"
}

View File

@@ -86,7 +86,20 @@ const Page = () => {
title={identityMembershipDetails?.identity?.name}
description={`Identity joined on ${identityMembershipDetails?.createdAt && formatRelative(new Date(identityMembershipDetails?.createdAt || ""), new Date())}`}
>
<div>
<div className="flex items-center gap-2">
<Button
variant="outline_bg"
size="xs"
onClick={() => {
navigator.clipboard.writeText(identityMembershipDetails.id);
createNotification({
text: "Membership ID copied to clipboard",
type: "success"
});
}}
>
Copy Membership ID
</Button>
<ProjectPermissionCan
I={ProjectPermissionActions.Delete}
a={subject(ProjectPermissionSub.Identity, {