mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
feat: completed all nit changes in review
This commit is contained in:
@@ -20,7 +20,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Create an additional privilege for identity.",
|
||||
description: "Add an additional privilege for identity.",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
@@ -91,7 +91,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Update a specific privilege of an identity.",
|
||||
description: "Update a specific identity privilege.",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
@@ -167,7 +167,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Delete a specific privilege of an identity.",
|
||||
description: "Delete the specified identity privilege.",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
@@ -202,7 +202,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Retrieve details of a specific privilege by privilege id.",
|
||||
description: "Retrieve details of a specific privilege by id.",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
@@ -237,7 +237,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Retrieve details of a specific privilege by privilege slug.",
|
||||
description: "Retrieve details of a specific privilege by slug.",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
@@ -277,7 +277,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
description: "List of a specific privilege of an identity in a project.",
|
||||
description: "List privileges for the specified identity by project.",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
|
||||
@@ -76,7 +76,7 @@ export const identityProjectAdditionalPrivilegeV2ServiceFactory = ({
|
||||
slug,
|
||||
projectMembershipId: identityProjectMembership.id
|
||||
});
|
||||
if (existingSlug) throw new BadRequestError({ message: "Additional privilege of provided slug exist" });
|
||||
if (existingSlug) throw new BadRequestError({ message: "Additional privilege with provided slug already exists" });
|
||||
|
||||
if (!dto.isTemporary) {
|
||||
const additionalPrivilege = await identityProjectAdditionalPrivilegeDAL.create({
|
||||
@@ -117,7 +117,7 @@ export const identityProjectAdditionalPrivilegeV2ServiceFactory = ({
|
||||
actorAuthMethod
|
||||
}: TUpdateIdentityPrivilegeByIdDTO) => {
|
||||
const identityPrivilege = await identityProjectAdditionalPrivilegeDAL.findById(id);
|
||||
if (!identityPrivilege) throw new NotFoundError({ message: "Identity additional privilege not found" });
|
||||
if (!identityPrivilege) throw new NotFoundError({ message: `Identity privilege with ${id} not found` });
|
||||
|
||||
const identityProjectMembership = await identityProjectDAL.findOne({ id: identityPrivilege.projectMembershipId });
|
||||
if (!identityProjectMembership)
|
||||
@@ -150,7 +150,7 @@ export const identityProjectAdditionalPrivilegeV2ServiceFactory = ({
|
||||
projectMembershipId: identityProjectMembership.id
|
||||
});
|
||||
if (existingSlug && existingSlug.id !== identityPrivilege.id)
|
||||
throw new BadRequestError({ message: "Additional privilege of provided slug exist" });
|
||||
throw new BadRequestError({ message: "Additional privilege with provided slug already exists" });
|
||||
}
|
||||
|
||||
const isTemporary = typeof data?.isTemporary !== "undefined" ? data.isTemporary : identityPrivilege.isTemporary;
|
||||
@@ -189,7 +189,7 @@ export const identityProjectAdditionalPrivilegeV2ServiceFactory = ({
|
||||
|
||||
const deleteById = async ({ actorId, id, actor, actorOrgId, actorAuthMethod }: TDeleteIdentityPrivilegeByIdDTO) => {
|
||||
const identityPrivilege = await identityProjectAdditionalPrivilegeDAL.findById(id);
|
||||
if (!identityPrivilege) throw new NotFoundError({ message: "Identity additional privilege not found" });
|
||||
if (!identityPrivilege) throw new NotFoundError({ message: `Identity privilege with ${id} not found` });
|
||||
|
||||
const identityProjectMembership = await identityProjectDAL.findOne({ id: identityPrivilege.projectMembershipId });
|
||||
if (!identityProjectMembership)
|
||||
@@ -231,7 +231,7 @@ export const identityProjectAdditionalPrivilegeV2ServiceFactory = ({
|
||||
actorAuthMethod
|
||||
}: TGetIdentityPrivilegeDetailsByIdDTO) => {
|
||||
const identityPrivilege = await identityProjectAdditionalPrivilegeDAL.findById(id);
|
||||
if (!identityPrivilege) throw new NotFoundError({ message: "Identity additional privilege not found" });
|
||||
if (!identityPrivilege) throw new NotFoundError({ message: `Identity privilege with ${id} not found` });
|
||||
|
||||
const identityProjectMembership = await identityProjectDAL.findOne({ id: identityPrivilege.projectMembershipId });
|
||||
if (!identityProjectMembership)
|
||||
@@ -264,7 +264,7 @@ export const identityProjectAdditionalPrivilegeV2ServiceFactory = ({
|
||||
actorAuthMethod
|
||||
}: TGetIdentityPrivilegeDetailsBySlugDTO) => {
|
||||
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||
if (!project) throw new NotFoundError({ message: "Project not found" });
|
||||
if (!project) throw new NotFoundError({ message: `Project with slug ${slug} not found` });
|
||||
const projectId = project.id;
|
||||
|
||||
const identityProjectMembership = await identityProjectDAL.findOne({ identityId, projectId });
|
||||
|
||||
@@ -2,8 +2,10 @@ import { ForbiddenError, MongoAbility, RawRuleOf } from "@casl/ability";
|
||||
import { PackRule, unpackRules } from "@casl/ability/extra";
|
||||
import ms from "ms";
|
||||
|
||||
import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { isAtLeastAsPrivileged } from "@app/lib/casl";
|
||||
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { UnpackedPermissionSchema } from "@app/server/routes/santizedSchemas/permission";
|
||||
import { ActorType } from "@app/services/auth/auth-type";
|
||||
import { TProjectMembershipDALFactory } from "@app/services/project-membership/project-membership-dal";
|
||||
|
||||
import { TPermissionServiceFactory } from "../permission/permission-service";
|
||||
@@ -50,7 +52,7 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({
|
||||
}: TCreateUserPrivilegeDTO) => {
|
||||
const projectMembership = await projectMembershipDAL.findById(projectMembershipId);
|
||||
if (!projectMembership)
|
||||
throw new NotFoundError({ message: `Project membership with ID '${projectMembershipId}' not found` });
|
||||
throw new NotFoundError({ message: `Project membership with ID ${projectMembershipId} found` });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
@@ -60,13 +62,24 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({
|
||||
actorOrgId
|
||||
);
|
||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Member);
|
||||
const { permission: entityPermission } = await permissionService.getProjectPermission(
|
||||
ActorType.USER,
|
||||
projectMembership.userId,
|
||||
projectMembership.projectId,
|
||||
actorAuthMethod,
|
||||
actorOrgId
|
||||
);
|
||||
const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, entityPermission);
|
||||
if (!hasRequiredPriviledges)
|
||||
throw new ForbiddenRequestError({ message: "Failed to update more privileged identity" });
|
||||
|
||||
const existingSlug = await projectUserAdditionalPrivilegeDAL.findOne({
|
||||
slug,
|
||||
projectId: projectMembership.projectId,
|
||||
userId: projectMembership.userId
|
||||
});
|
||||
if (existingSlug) throw new BadRequestError({ message: "Additional privilege of provided slug exist" });
|
||||
if (existingSlug)
|
||||
throw new BadRequestError({ message: `Additional privilege with provided slug ${slug} already exists` });
|
||||
|
||||
if (!dto.isTemporary) {
|
||||
const additionalPrivilege = await projectUserAdditionalPrivilegeDAL.create({
|
||||
@@ -109,7 +122,7 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({
|
||||
}: TUpdateUserPrivilegeDTO) => {
|
||||
const userPrivilege = await projectUserAdditionalPrivilegeDAL.findById(privilegeId);
|
||||
if (!userPrivilege)
|
||||
throw new NotFoundError({ message: `User additional privilege with ID '${privilegeId}' not found` });
|
||||
throw new NotFoundError({ message: `User additional privilege with ID ${privilegeId} not found` });
|
||||
|
||||
const projectMembership = await projectMembershipDAL.findOne({
|
||||
userId: userPrivilege.userId,
|
||||
@@ -129,6 +142,16 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({
|
||||
actorOrgId
|
||||
);
|
||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Member);
|
||||
const { permission: entityPermission } = await permissionService.getProjectPermission(
|
||||
ActorType.USER,
|
||||
projectMembership.userId,
|
||||
projectMembership.projectId,
|
||||
actorAuthMethod,
|
||||
actorOrgId
|
||||
);
|
||||
const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, entityPermission);
|
||||
if (!hasRequiredPriviledges)
|
||||
throw new ForbiddenRequestError({ message: "Failed to update more privileged identity" });
|
||||
|
||||
if (dto?.slug) {
|
||||
const existingSlug = await projectUserAdditionalPrivilegeDAL.findOne({
|
||||
@@ -137,7 +160,7 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({
|
||||
projectId: projectMembership.projectId
|
||||
});
|
||||
if (existingSlug && existingSlug.id !== userPrivilege.id)
|
||||
throw new BadRequestError({ message: "Additional privilege of provided slug exist" });
|
||||
throw new BadRequestError({ message: `Additional privilege with provided slug ${dto.slug} already exists` });
|
||||
}
|
||||
|
||||
const isTemporary = typeof dto?.isTemporary !== "undefined" ? dto.isTemporary : userPrivilege.isTemporary;
|
||||
@@ -178,7 +201,7 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({
|
||||
const deleteById = async ({ actorId, actor, actorOrgId, actorAuthMethod, privilegeId }: TDeleteUserPrivilegeDTO) => {
|
||||
const userPrivilege = await projectUserAdditionalPrivilegeDAL.findById(privilegeId);
|
||||
if (!userPrivilege)
|
||||
throw new NotFoundError({ message: `User additional privilege with ID '${privilegeId}' not found` });
|
||||
throw new NotFoundError({ message: `User additional privilege with ID ${privilegeId} not found` });
|
||||
|
||||
const projectMembership = await projectMembershipDAL.findOne({
|
||||
userId: userPrivilege.userId,
|
||||
@@ -214,7 +237,7 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({
|
||||
}: TGetUserPrivilegeDetailsDTO) => {
|
||||
const userPrivilege = await projectUserAdditionalPrivilegeDAL.findById(privilegeId);
|
||||
if (!userPrivilege)
|
||||
throw new NotFoundError({ message: `User additional privilege with ID '${privilegeId}' not found` });
|
||||
throw new NotFoundError({ message: `User additional privilege with ID ${privilegeId} not found` });
|
||||
|
||||
const projectMembership = await projectMembershipDAL.findOne({
|
||||
userId: userPrivilege.userId,
|
||||
@@ -249,7 +272,7 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({
|
||||
}: TListUserPrivilegesDTO) => {
|
||||
const projectMembership = await projectMembershipDAL.findById(projectMembershipId);
|
||||
if (!projectMembership)
|
||||
throw new NotFoundError({ message: `Project membership with ID '${projectMembershipId}' not found` });
|
||||
throw new NotFoundError({ message: `Project membership with ID ${projectMembershipId} not found` });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
|
||||
@@ -974,27 +974,27 @@ export const PROJECT_USER_ADDITIONAL_PRIVILEGE = {
|
||||
|
||||
export const IDENTITY_ADDITIONAL_PRIVILEGE_V2 = {
|
||||
CREATE: {
|
||||
identityId: "The ID of the identity to create.",
|
||||
identityId: "The ID of the identity to create the privilege for",
|
||||
projectId: "The ID of the project of the identity in.",
|
||||
slug: "The slug of the privilege to create.",
|
||||
permission: "The permission for the privilege.",
|
||||
isTemporary: "Whether the privilege is temporary.",
|
||||
isTemporary: "Whether the privilege is temporary or permanent.",
|
||||
temporaryMode: "Type of temporary access given. Types: relative",
|
||||
temporaryRange: "TTL for the temporay time. Eg: 1m, 1h, 1d",
|
||||
temporaryAccessStartTime: "ISO time for which temporary access should begin."
|
||||
temporaryRange: "The TTL for the temporary access given",
|
||||
temporaryAccessStartTime: "The start time in ISO format when the temporary access should begin."
|
||||
},
|
||||
UPDATE: {
|
||||
id: "The id of the privilege of the identity.",
|
||||
id: "The ID of the identity privilege.",
|
||||
identityId: "The ID of the identity to update.",
|
||||
slug: "The slug of the privilege to update.",
|
||||
privilegePermission: "The permission for the privilege.",
|
||||
isTemporary: "Whether the privilege is temporary.",
|
||||
temporaryMode: "Type of temporary access given. Types: relative",
|
||||
temporaryRange: "TTL for the temporay time. Eg: 1m, 1h, 1d",
|
||||
temporaryAccessStartTime: "ISO time for which temporary access should begin."
|
||||
temporaryRange: "The TTL for the temporary access given",
|
||||
temporaryAccessStartTime: "The start time in ISO format when the temporary access should begin."
|
||||
},
|
||||
DELETE: {
|
||||
id: "the id of the privilege of the identity.",
|
||||
id: "The ID of the identity privilege.",
|
||||
identityId: "The ID of the identity to delete.",
|
||||
slug: "The slug of the privilege to delete."
|
||||
},
|
||||
@@ -1004,10 +1004,10 @@ export const IDENTITY_ADDITIONAL_PRIVILEGE_V2 = {
|
||||
slug: "The slug of the privilege."
|
||||
},
|
||||
GET_BY_ID: {
|
||||
id: "The id of the privilege of the identity."
|
||||
id: "The ID of the identity privilege."
|
||||
},
|
||||
LIST: {
|
||||
projectId: "The ID of the project of the identity in.",
|
||||
projectId: "The ID of the project that the identity is in.",
|
||||
identityId: "The ID of the identity to list."
|
||||
}
|
||||
};
|
||||
|
||||
@@ -118,7 +118,7 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const membership = await server.services.projectMembership.getProjectMembershipById({
|
||||
actorId: req.permission.id,
|
||||
|
||||
@@ -38,7 +38,7 @@ const glob: JsInterpreter<FieldCondition<string>> = (node, object, context) => {
|
||||
const conditionsMatcher = buildMongoQueryMatcher({ $glob }, { glob });
|
||||
|
||||
export const roleQueryKeys = {
|
||||
getProjectRoles: (projectId: string) => ["roles", { projectSlug: projectId }] as const,
|
||||
getProjectRoles: (projectId: string) => ["roles", { projectId }] as const,
|
||||
getProjectRoleBySlug: (projectId: string, roleSlug: string) =>
|
||||
["roles", { projectId, roleSlug }] as const,
|
||||
getOrgRoles: (orgId: string) => ["org-roles", { orgId }] as const,
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
import { useTranslation } from "react-i18next";
|
||||
import Head from "next/head";
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
import { useTranslation } from "react-i18next";
|
||||
import Head from "next/head";
|
||||
|
||||
|
||||
@@ -56,10 +56,10 @@ export const IdentityDetailsPage = withProjectPermission(
|
||||
</h3>
|
||||
<div>
|
||||
<ProjectPermissionCan
|
||||
I={ProjectPermissionActions.Edit}
|
||||
I={ProjectPermissionActions.Delete}
|
||||
a={ProjectPermissionSub.Identity}
|
||||
renderTooltip
|
||||
allowedLabel="Edit role"
|
||||
allowedLabel="Remove from project"
|
||||
>
|
||||
{(isAllowed) => (
|
||||
<Button
|
||||
|
||||
@@ -206,9 +206,7 @@ export const IdentityProjectAdditionalPrivilegeModifySection = ({
|
||||
<IconButton ariaLabel="go-back" variant="plain" onClick={onGoBack}>
|
||||
<FontAwesomeIcon icon={faChevronLeft} />
|
||||
</IconButton>
|
||||
<h3 className="text-lg font-semibold text-mineshaft-100">
|
||||
Modify Additional Privilege
|
||||
</h3>
|
||||
<h3 className="text-lg font-semibold text-mineshaft-100">Edit Additional Privilege</h3>
|
||||
</div>
|
||||
<div className="flex items-center space-x-4">
|
||||
{isDirty && (
|
||||
|
||||
@@ -98,7 +98,7 @@ export const IdentityProjectAdditionalPrivilegeSection = ({ identityMembershipDe
|
||||
>
|
||||
<div className="flex items-center justify-between border-b border-mineshaft-400 pb-4">
|
||||
<h3 className="text-lg font-semibold text-mineshaft-100">
|
||||
Project Additional Privilege
|
||||
Project Additional Privileges
|
||||
</h3>
|
||||
|
||||
<ProjectPermissionCan
|
||||
@@ -174,7 +174,7 @@ export const IdentityProjectAdditionalPrivilegeSection = ({ identityMembershipDe
|
||||
}}
|
||||
onClick={() => handlePopUpOpen("modifyPrivilege", privilegeDetails)}
|
||||
>
|
||||
<Td className="capitalize">{privilegeDetails.slug}</Td>
|
||||
<Td>{privilegeDetails.slug}</Td>
|
||||
<Td>
|
||||
<Tooltip asChild={false} content={toolTipText}>
|
||||
<Tag
|
||||
|
||||
@@ -72,7 +72,7 @@ export const IdentityRoleDetailsSection = ({
|
||||
I={ProjectPermissionActions.Edit}
|
||||
a={ProjectPermissionSub.Identity}
|
||||
renderTooltip
|
||||
allowedLabel="Edit role"
|
||||
allowedLabel="Edit Role(s)"
|
||||
>
|
||||
{(isAllowed) => (
|
||||
<IconButton
|
||||
|
||||
@@ -54,10 +54,10 @@ export const MemberDetailsPage = withProjectPermission(
|
||||
<h3 className="text-xl font-semibold text-mineshaft-100">Project User Access</h3>
|
||||
<div>
|
||||
<ProjectPermissionCan
|
||||
I={ProjectPermissionActions.Edit}
|
||||
I={ProjectPermissionActions.Delete}
|
||||
a={ProjectPermissionSub.Member}
|
||||
renderTooltip
|
||||
allowedLabel="Edit role"
|
||||
allowedLabel="Remove from project"
|
||||
>
|
||||
{(isAllowed) => (
|
||||
<Button
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { faFolder, faPlus, faTrash } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { format,formatDistance } from "date-fns";
|
||||
import { format, formatDistance } from "date-fns";
|
||||
import { AnimatePresence, motion } from "framer-motion";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
@@ -19,7 +19,8 @@ import {
|
||||
Th,
|
||||
THead,
|
||||
Tooltip,
|
||||
Tr} from "@app/components/v2";
|
||||
Tr
|
||||
} from "@app/components/v2";
|
||||
import {
|
||||
ProjectPermissionActions,
|
||||
ProjectPermissionSub,
|
||||
@@ -104,7 +105,7 @@ export const MemberProjectAdditionalPrivilegeSection = ({ membershipDetails }: P
|
||||
>
|
||||
<div className="flex items-center justify-between border-b border-mineshaft-400 pb-4">
|
||||
<h3 className="text-lg font-semibold text-mineshaft-100">
|
||||
Project Additional Privilege
|
||||
Project Additional Privileges
|
||||
</h3>
|
||||
{userId !== membershipDetails?.user?.id &&
|
||||
membershipDetails?.status !== "invited" && (
|
||||
@@ -180,7 +181,7 @@ export const MemberProjectAdditionalPrivilegeSection = ({ membershipDetails }: P
|
||||
}}
|
||||
onClick={() => handlePopUpOpen("modifyPrivilege", privilegeDetails)}
|
||||
>
|
||||
<Td className="capitalize">{privilegeDetails.slug}</Td>
|
||||
<Td>{privilegeDetails.slug}</Td>
|
||||
<Td>
|
||||
<Tooltip asChild={false} content={toolTipText}>
|
||||
<Tag
|
||||
|
||||
@@ -163,7 +163,7 @@ export const MembershipProjectAdditionalPrivilegeModifySection = ({
|
||||
onGoBack();
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
createNotification({ type: "error", text: "Failed to update role" });
|
||||
createNotification({ type: "error", text: "Failed to update privilege" });
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -20,7 +20,8 @@ import {
|
||||
Th,
|
||||
THead,
|
||||
Tooltip,
|
||||
Tr} from "@app/components/v2";
|
||||
Tr
|
||||
} from "@app/components/v2";
|
||||
import {
|
||||
ProjectPermissionActions,
|
||||
ProjectPermissionSub,
|
||||
@@ -81,7 +82,7 @@ export const MemberRoleDetailsSection = ({
|
||||
I={ProjectPermissionActions.Edit}
|
||||
a={ProjectPermissionSub.Member}
|
||||
renderTooltip
|
||||
allowedLabel="Edit role"
|
||||
allowedLabel="Edit role(s)"
|
||||
>
|
||||
{(isAllowed) => (
|
||||
<IconButton
|
||||
|
||||
@@ -19,16 +19,19 @@ export const IdentityRoleForm = ({ identityProjectMember, onOpenUpgradeModal }:
|
||||
identityProjectMember={identityProjectMember}
|
||||
onOpenUpgradeModal={onOpenUpgradeModal}
|
||||
/>
|
||||
<Alert className="mt-4">
|
||||
<Alert
|
||||
title="Additional privileges have been moved and now offer full permission customization."
|
||||
className="mt-4 border-primary/50 bg-primary/10"
|
||||
>
|
||||
<AlertDescription>
|
||||
Additional privileges now offer full permissions and have been moved to a new screen.
|
||||
<br />
|
||||
<Link
|
||||
href={`/project/${currentWorkspace?.id || ""}/identitiesq/${
|
||||
href={`/project/${currentWorkspace?.id || ""}/identities/${
|
||||
identityProjectMember?.identity?.id
|
||||
}`}
|
||||
>
|
||||
<span className="cursor-pointer text-primary">Click here to access them.</span>
|
||||
<span className="cursor-pointer text-primary underline underline-offset-2">
|
||||
Click here to access them now
|
||||
</span>
|
||||
</Link>
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
|
||||
@@ -15,12 +15,15 @@ export const MemberRoleForm = ({ projectMember, onOpenUpgradeModal }: Props) =>
|
||||
return (
|
||||
<div>
|
||||
<MemberRbacSection projectMember={projectMember} onOpenUpgradeModal={onOpenUpgradeModal} />
|
||||
<Alert className="mt-4">
|
||||
<Alert
|
||||
title="Additional privileges have been moved and now offer full permission customization."
|
||||
className="mt-4 border-primary/50 bg-primary/10"
|
||||
>
|
||||
<AlertDescription>
|
||||
Additional privileges now offer full permissions and have been moved to a new screen.
|
||||
<br />
|
||||
<Link href={`/project/${currentWorkspace?.id || ""}/members/${projectMember?.id}`}>
|
||||
<span className="cursor-pointer text-primary">Click here to access them.</span>
|
||||
<span className="cursor-pointer text-primary underline underline-offset-2">
|
||||
Click here to access them now
|
||||
</span>
|
||||
</Link>
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
|
||||
Reference in New Issue
Block a user