mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
feat: added lease permission for dynamic secret
This commit is contained in:
@@ -4,7 +4,10 @@ import ms from "ms";
|
||||
import { SecretKeyEncoding } from "@app/db/schemas";
|
||||
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
|
||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
|
||||
import {
|
||||
ProjectPermissionDynamicSecretActions,
|
||||
ProjectPermissionSub
|
||||
} from "@app/ee/services/permission/project-permission";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { infisicalSymmetricDecrypt } from "@app/lib/crypto/encryption";
|
||||
import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
||||
@@ -73,7 +76,7 @@ export const dynamicSecretLeaseServiceFactory = ({
|
||||
actorOrgId
|
||||
);
|
||||
ForbiddenError.from(permission).throwUnlessCan(
|
||||
ProjectPermissionActions.Read,
|
||||
ProjectPermissionDynamicSecretActions.Lease,
|
||||
subject(ProjectPermissionSub.DynamicSecrets, { environment: environmentSlug, secretPath: path })
|
||||
);
|
||||
|
||||
@@ -146,7 +149,7 @@ export const dynamicSecretLeaseServiceFactory = ({
|
||||
actorOrgId
|
||||
);
|
||||
ForbiddenError.from(permission).throwUnlessCan(
|
||||
ProjectPermissionActions.Edit,
|
||||
ProjectPermissionDynamicSecretActions.Lease,
|
||||
subject(ProjectPermissionSub.DynamicSecrets, { environment: environmentSlug, secretPath: path })
|
||||
);
|
||||
|
||||
@@ -220,7 +223,7 @@ export const dynamicSecretLeaseServiceFactory = ({
|
||||
actorOrgId
|
||||
);
|
||||
ForbiddenError.from(permission).throwUnlessCan(
|
||||
ProjectPermissionActions.Delete,
|
||||
ProjectPermissionDynamicSecretActions.Lease,
|
||||
subject(ProjectPermissionSub.DynamicSecrets, { environment: environmentSlug, secretPath: path })
|
||||
);
|
||||
|
||||
@@ -285,7 +288,7 @@ export const dynamicSecretLeaseServiceFactory = ({
|
||||
actorOrgId
|
||||
);
|
||||
ForbiddenError.from(permission).throwUnlessCan(
|
||||
ProjectPermissionActions.Read,
|
||||
ProjectPermissionDynamicSecretActions.Lease,
|
||||
subject(ProjectPermissionSub.DynamicSecrets, { environment: environmentSlug, secretPath: path })
|
||||
);
|
||||
|
||||
@@ -321,7 +324,7 @@ export const dynamicSecretLeaseServiceFactory = ({
|
||||
actorOrgId
|
||||
);
|
||||
ForbiddenError.from(permission).throwUnlessCan(
|
||||
ProjectPermissionActions.Read,
|
||||
ProjectPermissionDynamicSecretActions.Lease,
|
||||
subject(ProjectPermissionSub.DynamicSecrets, { environment: environmentSlug, secretPath: path })
|
||||
);
|
||||
|
||||
|
||||
@@ -3,7 +3,10 @@ import { ForbiddenError, subject } from "@casl/ability";
|
||||
import { SecretKeyEncoding } from "@app/db/schemas";
|
||||
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
|
||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
|
||||
import {
|
||||
ProjectPermissionDynamicSecretActions,
|
||||
ProjectPermissionSub
|
||||
} from "@app/ee/services/permission/project-permission";
|
||||
import { infisicalSymmetricDecrypt, infisicalSymmetricEncypt } from "@app/lib/crypto/encryption";
|
||||
import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { OrderByDirection } from "@app/lib/types";
|
||||
@@ -77,7 +80,7 @@ export const dynamicSecretServiceFactory = ({
|
||||
actorOrgId
|
||||
);
|
||||
ForbiddenError.from(permission).throwUnlessCan(
|
||||
ProjectPermissionActions.Create,
|
||||
ProjectPermissionDynamicSecretActions.Create,
|
||||
subject(ProjectPermissionSub.DynamicSecrets, { environment: environmentSlug, secretPath: path })
|
||||
);
|
||||
|
||||
@@ -146,7 +149,7 @@ export const dynamicSecretServiceFactory = ({
|
||||
actorOrgId
|
||||
);
|
||||
ForbiddenError.from(permission).throwUnlessCan(
|
||||
ProjectPermissionActions.Edit,
|
||||
ProjectPermissionDynamicSecretActions.Edit,
|
||||
subject(ProjectPermissionSub.DynamicSecrets, { environment: environmentSlug, secretPath: path })
|
||||
);
|
||||
|
||||
@@ -225,7 +228,7 @@ export const dynamicSecretServiceFactory = ({
|
||||
actorOrgId
|
||||
);
|
||||
ForbiddenError.from(permission).throwUnlessCan(
|
||||
ProjectPermissionActions.Edit,
|
||||
ProjectPermissionDynamicSecretActions.Edit,
|
||||
subject(ProjectPermissionSub.DynamicSecrets, { environment: environmentSlug, secretPath: path })
|
||||
);
|
||||
|
||||
@@ -282,7 +285,7 @@ export const dynamicSecretServiceFactory = ({
|
||||
actorOrgId
|
||||
);
|
||||
ForbiddenError.from(permission).throwUnlessCan(
|
||||
ProjectPermissionActions.Edit,
|
||||
ProjectPermissionDynamicSecretActions.Edit,
|
||||
subject(ProjectPermissionSub.DynamicSecrets, { environment: environmentSlug, secretPath: path })
|
||||
);
|
||||
|
||||
@@ -328,7 +331,7 @@ export const dynamicSecretServiceFactory = ({
|
||||
// verify user has access to each env in request
|
||||
environmentSlugs.forEach((environmentSlug) =>
|
||||
ForbiddenError.from(permission).throwUnlessCan(
|
||||
ProjectPermissionActions.Read,
|
||||
ProjectPermissionDynamicSecretActions.Lease,
|
||||
subject(ProjectPermissionSub.DynamicSecrets, { environment: environmentSlug, secretPath: path })
|
||||
)
|
||||
);
|
||||
@@ -364,7 +367,7 @@ export const dynamicSecretServiceFactory = ({
|
||||
actorOrgId
|
||||
);
|
||||
ForbiddenError.from(permission).throwUnlessCan(
|
||||
ProjectPermissionActions.Read,
|
||||
ProjectPermissionDynamicSecretActions.Lease,
|
||||
subject(ProjectPermissionSub.DynamicSecrets, { environment: environmentSlug, secretPath: path })
|
||||
);
|
||||
|
||||
@@ -410,7 +413,7 @@ export const dynamicSecretServiceFactory = ({
|
||||
actorOrgId
|
||||
);
|
||||
ForbiddenError.from(permission).throwUnlessCan(
|
||||
ProjectPermissionActions.Read,
|
||||
ProjectPermissionDynamicSecretActions.Lease,
|
||||
subject(ProjectPermissionSub.DynamicSecrets, { environment: environmentSlug, secretPath: path })
|
||||
);
|
||||
|
||||
@@ -452,7 +455,7 @@ export const dynamicSecretServiceFactory = ({
|
||||
// verify user has access to each env in request
|
||||
environmentSlugs.forEach((environmentSlug) =>
|
||||
ForbiddenError.from(permission).throwUnlessCan(
|
||||
ProjectPermissionActions.Read,
|
||||
ProjectPermissionDynamicSecretActions.Lease,
|
||||
subject(ProjectPermissionSub.DynamicSecrets, { environment: environmentSlug, secretPath: path })
|
||||
)
|
||||
);
|
||||
|
||||
@@ -23,6 +23,14 @@ export enum ProjectPermissionCmekActions {
|
||||
Decrypt = "decrypt"
|
||||
}
|
||||
|
||||
export enum ProjectPermissionDynamicSecretActions {
|
||||
Read = "read",
|
||||
Create = "create",
|
||||
Edit = "edit",
|
||||
Delete = "delete",
|
||||
Lease = "lease"
|
||||
}
|
||||
|
||||
export enum ProjectPermissionSub {
|
||||
Role = "role",
|
||||
Member = "member",
|
||||
@@ -88,7 +96,7 @@ export type ProjectPermissionSet =
|
||||
)
|
||||
]
|
||||
| [
|
||||
ProjectPermissionActions,
|
||||
ProjectPermissionDynamicSecretActions,
|
||||
(
|
||||
| ProjectPermissionSub.DynamicSecrets
|
||||
| (ForcedSubject<ProjectPermissionSub.DynamicSecrets> & DynamicSecretSubjectFields)
|
||||
@@ -397,7 +405,7 @@ export const ProjectPermissionV2Schema = z.discriminatedUnion("subject", [
|
||||
z.object({
|
||||
subject: z.literal(ProjectPermissionSub.DynamicSecrets).describe("The entity this permission pertains to."),
|
||||
inverted: z.boolean().optional().describe("Whether rule allows or forbids."),
|
||||
action: CASL_ACTION_SCHEMA_NATIVE_ENUM(ProjectPermissionActions).describe(
|
||||
action: CASL_ACTION_SCHEMA_NATIVE_ENUM(ProjectPermissionDynamicSecretActions).describe(
|
||||
"Describe what action an entity can take."
|
||||
),
|
||||
conditions: SecretConditionV1Schema.describe(
|
||||
@@ -414,7 +422,6 @@ const buildAdminPermissionRules = () => {
|
||||
[
|
||||
ProjectPermissionSub.Secrets,
|
||||
ProjectPermissionSub.SecretFolders,
|
||||
ProjectPermissionSub.DynamicSecrets,
|
||||
ProjectPermissionSub.SecretImports,
|
||||
ProjectPermissionSub.SecretApproval,
|
||||
ProjectPermissionSub.SecretRotation,
|
||||
@@ -447,6 +454,17 @@ const buildAdminPermissionRules = () => {
|
||||
);
|
||||
});
|
||||
|
||||
can(
|
||||
[
|
||||
ProjectPermissionDynamicSecretActions.Read,
|
||||
ProjectPermissionDynamicSecretActions.Edit,
|
||||
ProjectPermissionDynamicSecretActions.Create,
|
||||
ProjectPermissionDynamicSecretActions.Delete,
|
||||
ProjectPermissionDynamicSecretActions.Lease
|
||||
],
|
||||
ProjectPermissionSub.DynamicSecrets
|
||||
);
|
||||
|
||||
can([ProjectPermissionActions.Edit, ProjectPermissionActions.Delete], ProjectPermissionSub.Project);
|
||||
can([ProjectPermissionActions.Read, ProjectPermissionActions.Create], ProjectPermissionSub.SecretRollback);
|
||||
can([ProjectPermissionActions.Edit], ProjectPermissionSub.Kms);
|
||||
@@ -489,10 +507,11 @@ const buildMemberPermissionRules = () => {
|
||||
);
|
||||
can(
|
||||
[
|
||||
ProjectPermissionActions.Read,
|
||||
ProjectPermissionActions.Edit,
|
||||
ProjectPermissionActions.Create,
|
||||
ProjectPermissionActions.Delete
|
||||
ProjectPermissionDynamicSecretActions.Read,
|
||||
ProjectPermissionDynamicSecretActions.Edit,
|
||||
ProjectPermissionDynamicSecretActions.Create,
|
||||
ProjectPermissionDynamicSecretActions.Delete,
|
||||
ProjectPermissionDynamicSecretActions.Lease
|
||||
],
|
||||
ProjectPermissionSub.DynamicSecrets
|
||||
);
|
||||
@@ -629,7 +648,7 @@ const buildViewerPermissionRules = () => {
|
||||
|
||||
can(ProjectPermissionActions.Read, ProjectPermissionSub.Secrets);
|
||||
can(ProjectPermissionActions.Read, ProjectPermissionSub.SecretFolders);
|
||||
can(ProjectPermissionActions.Read, ProjectPermissionSub.DynamicSecrets);
|
||||
can(ProjectPermissionDynamicSecretActions.Read, ProjectPermissionSub.DynamicSecrets);
|
||||
can(ProjectPermissionActions.Read, ProjectPermissionSub.SecretImports);
|
||||
can(ProjectPermissionActions.Read, ProjectPermissionSub.SecretApproval);
|
||||
can(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback);
|
||||
|
||||
@@ -3,7 +3,10 @@ import { z } from "zod";
|
||||
|
||||
import { SecretFoldersSchema, SecretImportsSchema, SecretTagsSchema } from "@app/db/schemas";
|
||||
import { EventType, UserAgentType } from "@app/ee/services/audit-log/audit-log-types";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
|
||||
import {
|
||||
ProjectPermissionDynamicSecretActions,
|
||||
ProjectPermissionSub
|
||||
} from "@app/ee/services/permission/project-permission";
|
||||
import { DASHBOARD } from "@app/lib/api-docs";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
import { removeTrailingSlash } from "@app/lib/fn";
|
||||
@@ -195,7 +198,7 @@ export const registerDashboardRouter = async (server: FastifyZodProvider) => {
|
||||
const allowedDynamicSecretEnviroments = // filter envs user has access to
|
||||
environments.filter((environment) =>
|
||||
permission.can(
|
||||
ProjectPermissionActions.Read,
|
||||
ProjectPermissionDynamicSecretActions.Lease,
|
||||
subject(ProjectPermissionSub.DynamicSecrets, { environment, secretPath })
|
||||
)
|
||||
);
|
||||
|
||||
@@ -3,5 +3,6 @@ export type { ProjectPermissionSet, TProjectPermission } from "./types";
|
||||
export {
|
||||
ProjectPermissionActions,
|
||||
ProjectPermissionCmekActions,
|
||||
ProjectPermissionDynamicSecretActions,
|
||||
ProjectPermissionSub
|
||||
} from "./types";
|
||||
|
||||
@@ -7,6 +7,14 @@ export enum ProjectPermissionActions {
|
||||
Delete = "delete"
|
||||
}
|
||||
|
||||
export enum ProjectPermissionDynamicSecretActions {
|
||||
Read = "read",
|
||||
Create = "create",
|
||||
Edit = "edit",
|
||||
Delete = "delete",
|
||||
Lease = "lease"
|
||||
}
|
||||
|
||||
export enum ProjectPermissionCmekActions {
|
||||
Read = "read",
|
||||
Create = "create",
|
||||
@@ -108,7 +116,7 @@ export type ProjectPermissionSet =
|
||||
)
|
||||
]
|
||||
| [
|
||||
ProjectPermissionActions,
|
||||
ProjectPermissionDynamicSecretActions,
|
||||
(
|
||||
| ProjectPermissionSub.DynamicSecrets
|
||||
| (ForcedSubject<ProjectPermissionSub.DynamicSecrets> & DynamicSecretSubjectFields)
|
||||
|
||||
@@ -11,6 +11,7 @@ export type { TProjectPermission } from "./ProjectPermissionContext";
|
||||
export {
|
||||
ProjectPermissionActions,
|
||||
ProjectPermissionCmekActions,
|
||||
ProjectPermissionDynamicSecretActions,
|
||||
ProjectPermissionProvider,
|
||||
ProjectPermissionSub,
|
||||
useProjectPermission
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
} from "@app/context";
|
||||
import {
|
||||
PermissionConditionOperators,
|
||||
ProjectPermissionDynamicSecretActions,
|
||||
TPermissionCondition,
|
||||
TPermissionConditionOperators
|
||||
} from "@app/context/ProjectPermissionContext/types";
|
||||
@@ -28,6 +29,14 @@ const CmekPolicyActionSchema = z.object({
|
||||
decrypt: z.boolean().optional()
|
||||
});
|
||||
|
||||
const DynamicSecretPolicyActionSchema = z.object({
|
||||
read: z.boolean().optional(),
|
||||
edit: z.boolean().optional(),
|
||||
delete: z.boolean().optional(),
|
||||
create: z.boolean().optional(),
|
||||
lease: z.boolean().optional()
|
||||
});
|
||||
|
||||
const SecretRollbackPolicyActionSchema = z.object({
|
||||
read: z.boolean().optional(),
|
||||
create: z.boolean().optional()
|
||||
@@ -90,7 +99,7 @@ export const formSchema = z.object({
|
||||
})
|
||||
.array()
|
||||
.default([]),
|
||||
[ProjectPermissionSub.DynamicSecrets]: GeneralPolicyActionSchema.extend({
|
||||
[ProjectPermissionSub.DynamicSecrets]: DynamicSecretPolicyActionSchema.extend({
|
||||
inverted: z.boolean().optional(),
|
||||
conditions: ConditionSchema
|
||||
})
|
||||
@@ -174,9 +183,9 @@ export const rolePermission2Form = (permissions: TProjectPermission[] = []) => {
|
||||
if (
|
||||
[
|
||||
ProjectPermissionSub.Secrets,
|
||||
ProjectPermissionSub.DynamicSecrets,
|
||||
ProjectPermissionSub.SecretFolders,
|
||||
ProjectPermissionSub.SecretImports,
|
||||
ProjectPermissionSub.DynamicSecrets,
|
||||
ProjectPermissionSub.Member,
|
||||
ProjectPermissionSub.Groups,
|
||||
ProjectPermissionSub.Identity,
|
||||
@@ -199,25 +208,50 @@ export const rolePermission2Form = (permissions: TProjectPermission[] = []) => {
|
||||
ProjectPermissionSub.Kms
|
||||
].includes(subject)
|
||||
) {
|
||||
const canRead = action.includes(ProjectPermissionActions.Read);
|
||||
const canEdit = action.includes(ProjectPermissionActions.Edit);
|
||||
const canDelete = action.includes(ProjectPermissionActions.Delete);
|
||||
const canCreate = action.includes(ProjectPermissionActions.Create);
|
||||
|
||||
// from above statement we are sure it won't be undefined
|
||||
if (isConditionalSubjects(subject)) {
|
||||
if (!formVal[subject]) formVal[subject] = [];
|
||||
formVal[subject]!.push({
|
||||
read: canRead,
|
||||
create: canCreate,
|
||||
edit: canEdit,
|
||||
delete: canDelete,
|
||||
conditions: conditions ? convertCaslConditionToFormOperator(conditions) : [],
|
||||
inverted
|
||||
});
|
||||
|
||||
if (subject === ProjectPermissionSub.DynamicSecrets) {
|
||||
const canRead = action.includes(ProjectPermissionDynamicSecretActions.Read);
|
||||
const canEdit = action.includes(ProjectPermissionDynamicSecretActions.Edit);
|
||||
const canDelete = action.includes(ProjectPermissionDynamicSecretActions.Delete);
|
||||
const canCreate = action.includes(ProjectPermissionDynamicSecretActions.Create);
|
||||
const canLease = action.includes(ProjectPermissionDynamicSecretActions.Lease);
|
||||
|
||||
// from above statement we are sure it won't be undefined
|
||||
formVal[subject]!.push({
|
||||
read: canRead,
|
||||
create: canCreate,
|
||||
edit: canEdit,
|
||||
delete: canDelete,
|
||||
conditions: conditions ? convertCaslConditionToFormOperator(conditions) : [],
|
||||
inverted,
|
||||
lease: canLease
|
||||
});
|
||||
} else {
|
||||
// for other subjects
|
||||
const canRead = action.includes(ProjectPermissionActions.Read);
|
||||
const canEdit = action.includes(ProjectPermissionActions.Edit);
|
||||
const canDelete = action.includes(ProjectPermissionActions.Delete);
|
||||
const canCreate = action.includes(ProjectPermissionActions.Create);
|
||||
formVal[subject]!.push({
|
||||
read: canRead,
|
||||
create: canCreate,
|
||||
edit: canEdit,
|
||||
delete: canDelete,
|
||||
conditions: conditions ? convertCaslConditionToFormOperator(conditions) : [],
|
||||
inverted
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// deduplicate multiple rules for other policies
|
||||
// because they don't have condition it doesn't make sense for multiple rules
|
||||
const canRead = action.includes(ProjectPermissionActions.Read);
|
||||
const canEdit = action.includes(ProjectPermissionActions.Edit);
|
||||
const canDelete = action.includes(ProjectPermissionActions.Delete);
|
||||
const canCreate = action.includes(ProjectPermissionActions.Create);
|
||||
|
||||
if (!formVal[subject]) formVal[subject] = [{}];
|
||||
if (canRead) formVal[subject as ProjectPermissionSub.Member]![0].read = true;
|
||||
if (canEdit) formVal[subject as ProjectPermissionSub.Member]![0].edit = true;
|
||||
@@ -317,7 +351,7 @@ export type TProjectPermissionObject = {
|
||||
label: string;
|
||||
value: keyof Omit<
|
||||
NonNullable<NonNullable<TFormSchema["permissions"]>[K]>[number],
|
||||
"conditions"
|
||||
"conditions" | "inverted"
|
||||
>;
|
||||
}[];
|
||||
};
|
||||
@@ -357,7 +391,8 @@ export const PROJECT_PERMISSION_OBJECT: TProjectPermissionObject = {
|
||||
{ label: "Read", value: "read" },
|
||||
{ label: "Create", value: "create" },
|
||||
{ label: "Modify", value: "edit" },
|
||||
{ label: "Remove", value: "delete" }
|
||||
{ label: "Remove", value: "delete" },
|
||||
{ label: "Lease", value: "lease" }
|
||||
]
|
||||
},
|
||||
[ProjectPermissionSub.Cmek]: {
|
||||
|
||||
@@ -12,6 +12,7 @@ import { PermissionDeniedBanner } from "@app/components/permissions";
|
||||
import { ContentLoader, Pagination } from "@app/components/v2";
|
||||
import {
|
||||
ProjectPermissionActions,
|
||||
ProjectPermissionDynamicSecretActions,
|
||||
ProjectPermissionSub,
|
||||
useProjectPermission,
|
||||
useWorkspace
|
||||
@@ -93,7 +94,7 @@ export const SecretMainPage = () => {
|
||||
);
|
||||
|
||||
const canReadDynamicSecret = permission.can(
|
||||
ProjectPermissionActions.Read,
|
||||
ProjectPermissionDynamicSecretActions.Lease,
|
||||
subject(ProjectPermissionSub.DynamicSecrets, { environment, secretPath })
|
||||
);
|
||||
|
||||
|
||||
@@ -45,7 +45,12 @@ import {
|
||||
Tooltip,
|
||||
UpgradePlanModal
|
||||
} from "@app/components/v2";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useSubscription } from "@app/context";
|
||||
import {
|
||||
ProjectPermissionActions,
|
||||
ProjectPermissionDynamicSecretActions,
|
||||
ProjectPermissionSub,
|
||||
useSubscription
|
||||
} from "@app/context";
|
||||
import { usePopUp } from "@app/hooks";
|
||||
import { useCreateFolder, useDeleteSecretBatch, useMoveSecrets } from "@app/hooks/api";
|
||||
import { fetchProjectSecrets } from "@app/hooks/api/secrets/queries";
|
||||
@@ -482,8 +487,8 @@ export const ActionBar = ({
|
||||
)}
|
||||
</ProjectPermissionCan>
|
||||
<ProjectPermissionCan
|
||||
I={ProjectPermissionActions.Create}
|
||||
a={subject(ProjectPermissionSub.Secrets, {
|
||||
I={ProjectPermissionDynamicSecretActions.Create}
|
||||
a={subject(ProjectPermissionSub.DynamicSecrets, {
|
||||
environment,
|
||||
secretPath,
|
||||
secretName: "*",
|
||||
|
||||
@@ -26,7 +26,7 @@ import {
|
||||
Tooltip,
|
||||
Tr
|
||||
} from "@app/components/v2";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/context";
|
||||
import { ProjectPermissionDynamicSecretActions, ProjectPermissionSub } from "@app/context";
|
||||
import { usePopUp } from "@app/hooks";
|
||||
import { useGetDynamicSecretLeases, useRevokeDynamicSecretLease } from "@app/hooks/api";
|
||||
import { DynamicSecretLeaseStatus } from "@app/hooks/api/dynamicSecretLease/types";
|
||||
@@ -139,7 +139,7 @@ export const DynamicSecretLease = ({
|
||||
<Td>
|
||||
<div className="flex items-center space-x-4">
|
||||
<ProjectPermissionCan
|
||||
I={ProjectPermissionActions.Edit}
|
||||
I={ProjectPermissionDynamicSecretActions.Lease}
|
||||
a={subject(ProjectPermissionSub.DynamicSecrets, { environment, secretPath })}
|
||||
renderTooltip
|
||||
allowedLabel="Renew"
|
||||
@@ -158,7 +158,7 @@ export const DynamicSecretLease = ({
|
||||
)}
|
||||
</ProjectPermissionCan>
|
||||
<ProjectPermissionCan
|
||||
I={ProjectPermissionActions.Delete}
|
||||
I={ProjectPermissionDynamicSecretActions.Lease}
|
||||
a={subject(ProjectPermissionSub.DynamicSecrets, { environment, secretPath })}
|
||||
renderTooltip
|
||||
allowedLabel="Delete"
|
||||
@@ -178,7 +178,7 @@ export const DynamicSecretLease = ({
|
||||
</ProjectPermissionCan>
|
||||
{status === DynamicSecretLeaseStatus.FailedDeletion && (
|
||||
<ProjectPermissionCan
|
||||
I={ProjectPermissionActions.Delete}
|
||||
I={ProjectPermissionDynamicSecretActions.Lease}
|
||||
a={subject(ProjectPermissionSub.DynamicSecrets, {
|
||||
environment,
|
||||
secretPath
|
||||
@@ -211,9 +211,19 @@ export const DynamicSecretLease = ({
|
||||
</TableContainer>
|
||||
{!isLeaseLoading && Boolean(leases?.length) && (
|
||||
<div className="mt-6 flex items-center space-x-4">
|
||||
<Button onClick={onClickNewLease} size="xs">
|
||||
New Lease
|
||||
</Button>
|
||||
<ProjectPermissionCan
|
||||
I={ProjectPermissionDynamicSecretActions.Lease}
|
||||
a={subject(ProjectPermissionSub.DynamicSecrets, {
|
||||
environment,
|
||||
secretPath
|
||||
})}
|
||||
>
|
||||
{(isAllowed) => (
|
||||
<Button onClick={onClickNewLease} size="xs" isDisabled={!isAllowed}>
|
||||
New Lease
|
||||
</Button>
|
||||
)}
|
||||
</ProjectPermissionCan>
|
||||
<Button onClick={onClose} variant="plain" colorSchema="secondary" size="xs">
|
||||
Close
|
||||
</Button>
|
||||
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
Tag,
|
||||
Tooltip
|
||||
} from "@app/components/v2";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/context";
|
||||
import { ProjectPermissionDynamicSecretActions, ProjectPermissionSub } from "@app/context";
|
||||
import { usePopUp } from "@app/hooks";
|
||||
import { useDeleteDynamicSecret } from "@app/hooks/api";
|
||||
import {
|
||||
@@ -132,17 +132,27 @@ export const DynamicSecretListView = ({
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center space-x-2 px-4 py-2">
|
||||
<Button
|
||||
size="xs"
|
||||
className="m-0 py-0.5 px-2 opacity-0 group-hover:opacity-100"
|
||||
isDisabled={isRevoking}
|
||||
onClick={(evt) => {
|
||||
evt.stopPropagation();
|
||||
handlePopUpOpen("createDynamicSecretLease", secret);
|
||||
}}
|
||||
<ProjectPermissionCan
|
||||
I={ProjectPermissionDynamicSecretActions.Lease}
|
||||
a={subject(ProjectPermissionSub.DynamicSecrets, { environment, secretPath })}
|
||||
renderTooltip
|
||||
allowedLabel="Edit"
|
||||
>
|
||||
Generate
|
||||
</Button>
|
||||
{(isAllowed) => (
|
||||
<Button
|
||||
size="xs"
|
||||
className="m-0 py-0.5 px-2 opacity-0 group-hover:opacity-100"
|
||||
isDisabled={isRevoking || !isAllowed}
|
||||
onClick={(evt) => {
|
||||
evt.stopPropagation();
|
||||
handlePopUpOpen("createDynamicSecretLease", secret);
|
||||
}}
|
||||
>
|
||||
Generate
|
||||
</Button>
|
||||
)}
|
||||
</ProjectPermissionCan>
|
||||
|
||||
{secret.status === DynamicSecretStatus.FailedDeletion && (
|
||||
<Tooltip content="This action will remove the secret from internal storage, but it will remain in external systems. Use this option only after you've confirmed that your external leases are handled.">
|
||||
<Button
|
||||
@@ -165,7 +175,7 @@ export const DynamicSecretListView = ({
|
||||
</div>
|
||||
<div className="flex items-center space-x-4 border-l border-mineshaft-600 px-3 py-3">
|
||||
<ProjectPermissionCan
|
||||
I={ProjectPermissionActions.Edit}
|
||||
I={ProjectPermissionDynamicSecretActions.Edit}
|
||||
a={subject(ProjectPermissionSub.DynamicSecrets, { environment, secretPath })}
|
||||
renderTooltip
|
||||
allowedLabel="Edit"
|
||||
@@ -187,7 +197,7 @@ export const DynamicSecretListView = ({
|
||||
)}
|
||||
</ProjectPermissionCan>
|
||||
<ProjectPermissionCan
|
||||
I={ProjectPermissionActions.Delete}
|
||||
I={ProjectPermissionDynamicSecretActions.Delete}
|
||||
a={subject(ProjectPermissionSub.DynamicSecrets, { environment, secretPath })}
|
||||
renderTooltip
|
||||
allowedLabel="Delete"
|
||||
|
||||
Reference in New Issue
Block a user