fix: update event permissions system (#4355)

* fix: update project permission types

* fix: permissions

* fix: PR changes

* chore: update docs

* fix:  greptile changes

* fix: secret imports router changes

* fix: type change

* fix: lint

* fix: type change

* fix: check plan type in publish

* fix: permissions

* fix: import change

* fix: lint fix
This commit is contained in:
Sid
2025-08-14 13:47:59 +05:30
committed by GitHub
parent a3b6fa9a53
commit 273a7b9657
19 changed files with 461 additions and 188 deletions
@@ -143,6 +143,13 @@ export enum ProjectPermissionSecretScanningConfigActions {
Update = "update-configs"
}
export enum ProjectPermissionSecretEventActions {
SubscribeCreated = "subscribe-on-created",
SubscribeUpdated = "subscribe-on-updated",
SubscribeDeleted = "subscribe-on-deleted",
SubscribeImportMutations = "subscribe-on-import-mutations"
}
export enum PermissionConditionOperators {
$IN = "$in",
$ALL = "$all",
@@ -172,7 +179,8 @@ export type ConditionalProjectPermissionSubject =
| ProjectPermissionSub.CertificateTemplates
| ProjectPermissionSub.SecretFolders
| ProjectPermissionSub.SecretImports
| ProjectPermissionSub.SecretRotation;
| ProjectPermissionSub.SecretRotation
| ProjectPermissionSub.SecretEvents;
export const formatedConditionsOperatorNames: { [K in PermissionConditionOperators]: string } = {
[PermissionConditionOperators.$EQ]: "equal to",
@@ -250,7 +258,8 @@ export enum ProjectPermissionSub {
Commits = "commits",
SecretScanningDataSources = "secret-scanning-data-sources",
SecretScanningFindings = "secret-scanning-findings",
SecretScanningConfigs = "secret-scanning-configs"
SecretScanningConfigs = "secret-scanning-configs",
SecretEvents = "secret-events"
}
export type SecretSubjectFields = {
@@ -260,6 +269,14 @@ export type SecretSubjectFields = {
secretTags: string[];
};
export type SecretEventSubjectFields = {
environment: string;
secretPath: string;
secretName: string;
secretTags: string[];
action: string;
};
export type SecretFolderSubjectFields = {
environment: string;
secretPath: string;
@@ -403,6 +420,13 @@ export type ProjectPermissionSet =
ProjectPermissionSub.SecretScanningDataSources
]
| [ProjectPermissionSecretScanningFindingActions, ProjectPermissionSub.SecretScanningFindings]
| [ProjectPermissionSecretScanningConfigActions, ProjectPermissionSub.SecretScanningConfigs];
| [ProjectPermissionSecretScanningConfigActions, ProjectPermissionSub.SecretScanningConfigs]
| [
ProjectPermissionSecretEventActions,
(
| ProjectPermissionSub.SecretEvents
| (ForcedSubject<ProjectPermissionSub.SecretEvents> & SecretEventSubjectFields)
)
];
export type TProjectPermission = MongoAbility<ProjectPermissionSet>;
@@ -21,6 +21,7 @@ import {
ProjectPermissionPkiSubscriberActions,
ProjectPermissionPkiTemplateActions,
ProjectPermissionSecretActions,
ProjectPermissionSecretEventActions,
ProjectPermissionSecretRotationActions,
ProjectPermissionSecretScanningConfigActions,
ProjectPermissionSecretScanningDataSourceActions,
@@ -188,6 +189,13 @@ const PkiTemplatePolicyActionSchema = z.object({
[ProjectPermissionPkiTemplateActions.ListCerts]: z.boolean().optional()
});
const SecretEventsPolicyActionSchema = z.object({
[ProjectPermissionSecretEventActions.SubscribeCreated]: z.boolean().optional(),
[ProjectPermissionSecretEventActions.SubscribeUpdated]: z.boolean().optional(),
[ProjectPermissionSecretEventActions.SubscribeDeleted]: z.boolean().optional(),
[ProjectPermissionSecretEventActions.SubscribeImportMutations]: z.boolean().optional()
});
const SecretRollbackPolicyActionSchema = z.object({
read: z.boolean().optional(),
create: z.boolean().optional()
@@ -356,7 +364,12 @@ export const projectRoleFormSchema = z.object({
[ProjectPermissionSub.SecretScanningFindings]:
SecretScanningFindingPolicyActionSchema.array().default([]),
[ProjectPermissionSub.SecretScanningConfigs]:
SecretScanningConfigPolicyActionSchema.array().default([])
SecretScanningConfigPolicyActionSchema.array().default([]),
[ProjectPermissionSub.SecretEvents]: SecretEventsPolicyActionSchema.extend({
conditions: ConditionSchema
})
.array()
.default([])
})
.partial()
.optional()
@@ -374,7 +387,8 @@ type TConditionalFields =
| ProjectPermissionSub.SshHosts
| ProjectPermissionSub.SecretRotation
| ProjectPermissionSub.Identity
| ProjectPermissionSub.SecretSyncs;
| ProjectPermissionSub.SecretSyncs
| ProjectPermissionSub.SecretEvents;
export const isConditionalSubjects = (
subject: ProjectPermissionSub
@@ -388,7 +402,8 @@ export const isConditionalSubjects = (
subject === ProjectPermissionSub.SecretRotation ||
subject === ProjectPermissionSub.PkiSubscribers ||
subject === ProjectPermissionSub.CertificateTemplates ||
subject === ProjectPermissionSub.SecretSyncs;
subject === ProjectPermissionSub.SecretSyncs ||
subject === ProjectPermissionSub.SecretEvents;
const convertCaslConditionToFormOperator = (caslConditions: TPermissionCondition) => {
const formConditions: z.infer<typeof ConditionSchema> = [];
@@ -494,7 +509,8 @@ export const rolePermission2Form = (permissions: TProjectPermission[] = []) => {
ProjectPermissionSub.SshCertificateAuthorities,
ProjectPermissionSub.SshCertificates,
ProjectPermissionSub.SshHostGroups,
ProjectPermissionSub.SecretSyncs
ProjectPermissionSub.SecretSyncs,
ProjectPermissionSub.SecretEvents
].includes(subject)
) {
// from above statement we are sure it won't be undefined
@@ -607,6 +623,32 @@ export const rolePermission2Form = (permissions: TProjectPermission[] = []) => {
return;
}
if (subject === ProjectPermissionSub.SecretEvents) {
const canSubscribeCreate = action.includes(
ProjectPermissionSecretEventActions.SubscribeCreated
);
const canSubscribeUpdate = action.includes(
ProjectPermissionSecretEventActions.SubscribeUpdated
);
const canSubscribeDelete = action.includes(
ProjectPermissionSecretEventActions.SubscribeDeleted
);
const canSubscribeImportMutations = action.includes(
ProjectPermissionSecretEventActions.SubscribeImportMutations
);
// from above statement we are sure it won't be undefined
formVal[subject]!.push({
"subscribe-on-created": canSubscribeCreate,
"subscribe-on-deleted": canSubscribeDelete,
"subscribe-on-updated": canSubscribeUpdate,
"subscribe-on-import-mutations": canSubscribeImportMutations,
conditions: conditions ? convertCaslConditionToFormOperator(conditions) : []
});
return;
}
// for other subjects
const canRead = action.includes(ProjectPermissionActions.Read);
const canEdit = action.includes(ProjectPermissionActions.Edit);
@@ -1114,8 +1156,7 @@ export const PROJECT_PERMISSION_OBJECT: TProjectPermissionObject = {
{ label: "Read Value", value: ProjectPermissionSecretActions.ReadValue },
{ label: "Modify", value: ProjectPermissionSecretActions.Edit },
{ label: "Remove", value: ProjectPermissionSecretActions.Delete },
{ label: "Create", value: ProjectPermissionSecretActions.Create },
{ label: "Subscribe", value: ProjectPermissionSecretActions.Subscribe }
{ label: "Create", value: ProjectPermissionSecretActions.Create }
]
},
[ProjectPermissionSub.SecretFolders]: {
@@ -1535,6 +1576,27 @@ export const PROJECT_PERMISSION_OBJECT: TProjectPermissionObject = {
value: ProjectPermissionSecretScanningConfigActions.Update
}
]
},
[ProjectPermissionSub.SecretEvents]: {
title: "Secret Events",
actions: [
{
label: "Subscribe on Created",
value: ProjectPermissionSecretEventActions.SubscribeCreated
},
{
label: "Subscribe on Deleted",
value: ProjectPermissionSecretEventActions.SubscribeDeleted
},
{
label: "Subscribe on Updated",
value: ProjectPermissionSecretEventActions.SubscribeUpdated
},
{
label: "Subscribe on Import Mutations",
value: ProjectPermissionSecretEventActions.SubscribeImportMutations
}
]
}
};
@@ -1564,7 +1626,8 @@ const SecretsManagerPermissionSubjects = (enabled = false) => ({
[ProjectPermissionSub.SecretRollback]: enabled,
[ProjectPermissionSub.SecretRotation]: enabled,
[ProjectPermissionSub.ServiceTokens]: enabled,
[ProjectPermissionSub.Commits]: enabled
[ProjectPermissionSub.Commits]: enabled,
[ProjectPermissionSub.SecretEvents]: enabled
});
const KmsPermissionSubjects = (enabled = false) => ({
@@ -32,6 +32,7 @@ import {
rolePermission2Form,
TFormSchema
} from "./ProjectRoleModifySection.utils";
import { SecretEventPermissionConditions } from "./SecretEventPermissionConditions";
import { SecretPermissionConditions } from "./SecretPermissionConditions";
import { SecretSyncPermissionConditions } from "./SecretSyncPermissionConditions";
import { SshHostPermissionConditions } from "./SshHostPermissionConditions";
@@ -72,6 +73,10 @@ export const renderConditionalComponents = (
return <SecretSyncPermissionConditions isDisabled={isDisabled} />;
}
if (subject === ProjectPermissionSub.SecretEvents) {
return <SecretEventPermissionConditions isDisabled={isDisabled} />;
}
return <GeneralPermissionConditions isDisabled={isDisabled} type={subject} />;
}
@@ -0,0 +1,22 @@
import { ProjectPermissionSub } from "@app/context/ProjectPermissionContext/types";
import { ConditionsFields } from "./ConditionsFields";
type Props = {
position?: number;
isDisabled?: boolean;
};
export const SecretEventPermissionConditions = ({ position = 0, isDisabled }: Props) => {
return (
<ConditionsFields
isDisabled={isDisabled}
subject={ProjectPermissionSub.SecretEvents}
position={position}
selectOptions={[
{ value: "environment", label: "Environment Slug" },
{ value: "secretPath", label: "Secret Path" }
]}
/>
);
};
@@ -17,8 +17,7 @@ export const SecretPermissionConditions = ({ position = 0, isDisabled }: Props)
{ value: "environment", label: "Environment Slug" },
{ value: "secretPath", label: "Secret Path" },
{ value: "secretName", label: "Secret Name" },
{ value: "secretTags", label: "Secret Tags" },
{ value: "eventType", label: "Event Type" }
{ value: "secretTags", label: "Secret Tags" }
]}
/>
);