mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-08 12:28:54 +00:00
Improve Audit Logs permissions
This commit is contained in:
@@ -6,9 +6,9 @@ import { getConfig } from "@app/lib/config/env";
|
|||||||
import { BadRequestError } from "@app/lib/errors";
|
import { BadRequestError } from "@app/lib/errors";
|
||||||
import { ActorType } from "@app/services/auth/auth-type";
|
import { ActorType } from "@app/services/auth/auth-type";
|
||||||
|
|
||||||
import { OrgPermissionActions, OrgPermissionSubjects } from "../permission/org-permission";
|
import { OrgPermissionAuditLogsActions, OrgPermissionSubjects } from "../permission/org-permission";
|
||||||
import { TPermissionServiceFactory } from "../permission/permission-service-types";
|
import { TPermissionServiceFactory } from "../permission/permission-service-types";
|
||||||
import { ProjectPermissionActions, ProjectPermissionSub } from "../permission/project-permission";
|
import { ProjectPermissionAuditLogsActions, ProjectPermissionSub } from "../permission/project-permission";
|
||||||
import { TAuditLogDALFactory } from "./audit-log-dal";
|
import { TAuditLogDALFactory } from "./audit-log-dal";
|
||||||
import { TAuditLogQueueServiceFactory } from "./audit-log-queue";
|
import { TAuditLogQueueServiceFactory } from "./audit-log-queue";
|
||||||
import { EventType, TAuditLogServiceFactory } from "./audit-log-types";
|
import { EventType, TAuditLogServiceFactory } from "./audit-log-types";
|
||||||
@@ -41,7 +41,10 @@ export const auditLogServiceFactory = ({
|
|||||||
actorOrgId,
|
actorOrgId,
|
||||||
actionProjectType: ActionProjectType.Any
|
actionProjectType: ActionProjectType.Any
|
||||||
});
|
});
|
||||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.AuditLogs);
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
|
ProjectPermissionAuditLogsActions.Read,
|
||||||
|
ProjectPermissionSub.AuditLogs
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
// Organization-wide logs
|
// Organization-wide logs
|
||||||
const { permission } = await permissionService.getOrgPermission(
|
const { permission } = await permissionService.getOrgPermission(
|
||||||
@@ -52,7 +55,10 @@ export const auditLogServiceFactory = ({
|
|||||||
actorOrgId
|
actorOrgId
|
||||||
);
|
);
|
||||||
|
|
||||||
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.AuditLogs);
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
|
OrgPermissionAuditLogsActions.Read,
|
||||||
|
OrgPermissionSubjects.AuditLogs
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If project ID is not provided, then we need to return all the audit logs for the organization itself.
|
// If project ID is not provided, then we need to return all the audit logs for the organization itself.
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { AbilityBuilder, createMongoAbility, MongoAbility } from "@casl/ability"
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
ProjectPermissionActions,
|
ProjectPermissionActions,
|
||||||
|
ProjectPermissionAuditLogsActions,
|
||||||
ProjectPermissionCertificateActions,
|
ProjectPermissionCertificateActions,
|
||||||
ProjectPermissionCmekActions,
|
ProjectPermissionCmekActions,
|
||||||
ProjectPermissionCommitsActions,
|
ProjectPermissionCommitsActions,
|
||||||
@@ -394,7 +395,7 @@ const buildMemberPermissionRules = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
can([ProjectPermissionActions.Read], ProjectPermissionSub.Role);
|
can([ProjectPermissionActions.Read], ProjectPermissionSub.Role);
|
||||||
can([ProjectPermissionActions.Read], ProjectPermissionSub.AuditLogs);
|
can([ProjectPermissionAuditLogsActions.Read], ProjectPermissionSub.AuditLogs);
|
||||||
can([ProjectPermissionActions.Read], ProjectPermissionSub.IpAllowList);
|
can([ProjectPermissionActions.Read], ProjectPermissionSub.IpAllowList);
|
||||||
|
|
||||||
// double check if all CRUD are needed for CA and Certificates
|
// double check if all CRUD are needed for CA and Certificates
|
||||||
@@ -502,7 +503,7 @@ const buildViewerPermissionRules = () => {
|
|||||||
can(ProjectPermissionActions.Read, ProjectPermissionSub.Settings);
|
can(ProjectPermissionActions.Read, ProjectPermissionSub.Settings);
|
||||||
can(ProjectPermissionActions.Read, ProjectPermissionSub.Environments);
|
can(ProjectPermissionActions.Read, ProjectPermissionSub.Environments);
|
||||||
can(ProjectPermissionActions.Read, ProjectPermissionSub.Tags);
|
can(ProjectPermissionActions.Read, ProjectPermissionSub.Tags);
|
||||||
can(ProjectPermissionActions.Read, ProjectPermissionSub.AuditLogs);
|
can(ProjectPermissionAuditLogsActions.Read, ProjectPermissionSub.AuditLogs);
|
||||||
can(ProjectPermissionActions.Read, ProjectPermissionSub.IpAllowList);
|
can(ProjectPermissionActions.Read, ProjectPermissionSub.IpAllowList);
|
||||||
can(ProjectPermissionActions.Read, ProjectPermissionSub.CertificateAuthorities);
|
can(ProjectPermissionActions.Read, ProjectPermissionSub.CertificateAuthorities);
|
||||||
can(ProjectPermissionCertificateActions.Read, ProjectPermissionSub.Certificates);
|
can(ProjectPermissionCertificateActions.Read, ProjectPermissionSub.Certificates);
|
||||||
|
|||||||
@@ -23,6 +23,10 @@ export enum OrgPermissionAppConnectionActions {
|
|||||||
Connect = "connect"
|
Connect = "connect"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum OrgPermissionAuditLogsActions {
|
||||||
|
Read = "read"
|
||||||
|
}
|
||||||
|
|
||||||
export enum OrgPermissionKmipActions {
|
export enum OrgPermissionKmipActions {
|
||||||
Proxy = "proxy",
|
Proxy = "proxy",
|
||||||
Setup = "setup"
|
Setup = "setup"
|
||||||
@@ -125,7 +129,7 @@ export type OrgPermissionSet =
|
|||||||
| [OrgPermissionBillingActions, OrgPermissionSubjects.Billing]
|
| [OrgPermissionBillingActions, OrgPermissionSubjects.Billing]
|
||||||
| [OrgPermissionIdentityActions, OrgPermissionSubjects.Identity]
|
| [OrgPermissionIdentityActions, OrgPermissionSubjects.Identity]
|
||||||
| [OrgPermissionActions, OrgPermissionSubjects.Kms]
|
| [OrgPermissionActions, OrgPermissionSubjects.Kms]
|
||||||
| [OrgPermissionActions, OrgPermissionSubjects.AuditLogs]
|
| [OrgPermissionAuditLogsActions, OrgPermissionSubjects.AuditLogs]
|
||||||
| [OrgPermissionActions, OrgPermissionSubjects.ProjectTemplates]
|
| [OrgPermissionActions, OrgPermissionSubjects.ProjectTemplates]
|
||||||
| [OrgPermissionGatewayActions, OrgPermissionSubjects.Gateway]
|
| [OrgPermissionGatewayActions, OrgPermissionSubjects.Gateway]
|
||||||
| [
|
| [
|
||||||
@@ -214,7 +218,9 @@ export const OrgPermissionSchema = z.discriminatedUnion("subject", [
|
|||||||
}),
|
}),
|
||||||
z.object({
|
z.object({
|
||||||
subject: z.literal(OrgPermissionSubjects.AuditLogs).describe("The entity this permission pertains to."),
|
subject: z.literal(OrgPermissionSubjects.AuditLogs).describe("The entity this permission pertains to."),
|
||||||
action: CASL_ACTION_SCHEMA_NATIVE_ENUM(OrgPermissionActions).describe("Describe what action an entity can take.")
|
action: CASL_ACTION_SCHEMA_NATIVE_ENUM(OrgPermissionAuditLogsActions).describe(
|
||||||
|
"Describe what action an entity can take."
|
||||||
|
)
|
||||||
}),
|
}),
|
||||||
z.object({
|
z.object({
|
||||||
subject: z.literal(OrgPermissionSubjects.ProjectTemplates).describe("The entity this permission pertains to."),
|
subject: z.literal(OrgPermissionSubjects.ProjectTemplates).describe("The entity this permission pertains to."),
|
||||||
@@ -340,10 +346,7 @@ const buildAdminPermission = () => {
|
|||||||
can(OrgPermissionActions.Edit, OrgPermissionSubjects.Kms);
|
can(OrgPermissionActions.Edit, OrgPermissionSubjects.Kms);
|
||||||
can(OrgPermissionActions.Delete, OrgPermissionSubjects.Kms);
|
can(OrgPermissionActions.Delete, OrgPermissionSubjects.Kms);
|
||||||
|
|
||||||
can(OrgPermissionActions.Read, OrgPermissionSubjects.AuditLogs);
|
can(OrgPermissionAuditLogsActions.Read, OrgPermissionSubjects.AuditLogs);
|
||||||
can(OrgPermissionActions.Create, OrgPermissionSubjects.AuditLogs);
|
|
||||||
can(OrgPermissionActions.Edit, OrgPermissionSubjects.AuditLogs);
|
|
||||||
can(OrgPermissionActions.Delete, OrgPermissionSubjects.AuditLogs);
|
|
||||||
|
|
||||||
can(OrgPermissionActions.Read, OrgPermissionSubjects.ProjectTemplates);
|
can(OrgPermissionActions.Read, OrgPermissionSubjects.ProjectTemplates);
|
||||||
can(OrgPermissionActions.Create, OrgPermissionSubjects.ProjectTemplates);
|
can(OrgPermissionActions.Create, OrgPermissionSubjects.ProjectTemplates);
|
||||||
@@ -416,7 +419,7 @@ const buildMemberPermission = () => {
|
|||||||
can(OrgPermissionIdentityActions.Edit, OrgPermissionSubjects.Identity);
|
can(OrgPermissionIdentityActions.Edit, OrgPermissionSubjects.Identity);
|
||||||
can(OrgPermissionIdentityActions.Delete, OrgPermissionSubjects.Identity);
|
can(OrgPermissionIdentityActions.Delete, OrgPermissionSubjects.Identity);
|
||||||
|
|
||||||
can(OrgPermissionActions.Read, OrgPermissionSubjects.AuditLogs);
|
can(OrgPermissionAuditLogsActions.Read, OrgPermissionSubjects.AuditLogs);
|
||||||
|
|
||||||
can(OrgPermissionAppConnectionActions.Connect, OrgPermissionSubjects.AppConnections);
|
can(OrgPermissionAppConnectionActions.Connect, OrgPermissionSubjects.AppConnections);
|
||||||
can(OrgPermissionGatewayActions.ListGateways, OrgPermissionSubjects.Gateway);
|
can(OrgPermissionGatewayActions.ListGateways, OrgPermissionSubjects.Gateway);
|
||||||
|
|||||||
@@ -164,6 +164,10 @@ export enum ProjectPermissionSecretEventActions {
|
|||||||
SubscribeImportMutations = "subscribe-on-import-mutations"
|
SubscribeImportMutations = "subscribe-on-import-mutations"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum ProjectPermissionAuditLogsActions {
|
||||||
|
Read = "read"
|
||||||
|
}
|
||||||
|
|
||||||
export enum ProjectPermissionSub {
|
export enum ProjectPermissionSub {
|
||||||
Role = "role",
|
Role = "role",
|
||||||
Member = "member",
|
Member = "member",
|
||||||
@@ -304,7 +308,7 @@ export type ProjectPermissionSet =
|
|||||||
| [ProjectPermissionGroupActions, ProjectPermissionSub.Groups]
|
| [ProjectPermissionGroupActions, ProjectPermissionSub.Groups]
|
||||||
| [ProjectPermissionActions, ProjectPermissionSub.Integrations]
|
| [ProjectPermissionActions, ProjectPermissionSub.Integrations]
|
||||||
| [ProjectPermissionActions, ProjectPermissionSub.Webhooks]
|
| [ProjectPermissionActions, ProjectPermissionSub.Webhooks]
|
||||||
| [ProjectPermissionActions, ProjectPermissionSub.AuditLogs]
|
| [ProjectPermissionAuditLogsActions, ProjectPermissionSub.AuditLogs]
|
||||||
| [ProjectPermissionActions, ProjectPermissionSub.Environments]
|
| [ProjectPermissionActions, ProjectPermissionSub.Environments]
|
||||||
| [ProjectPermissionActions, ProjectPermissionSub.IpAllowList]
|
| [ProjectPermissionActions, ProjectPermissionSub.IpAllowList]
|
||||||
| [ProjectPermissionActions, ProjectPermissionSub.Settings]
|
| [ProjectPermissionActions, ProjectPermissionSub.Settings]
|
||||||
@@ -645,7 +649,7 @@ const GeneralPermissionSchema = [
|
|||||||
}),
|
}),
|
||||||
z.object({
|
z.object({
|
||||||
subject: z.literal(ProjectPermissionSub.AuditLogs).describe("The entity this permission pertains to."),
|
subject: z.literal(ProjectPermissionSub.AuditLogs).describe("The entity this permission pertains to."),
|
||||||
action: CASL_ACTION_SCHEMA_NATIVE_ENUM(ProjectPermissionActions).describe(
|
action: CASL_ACTION_SCHEMA_NATIVE_ENUM(ProjectPermissionAuditLogsActions).describe(
|
||||||
"Describe what action an entity can take."
|
"Describe what action an entity can take."
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ export { useOrgPermission } from "./OrgPermissionContext";
|
|||||||
export type { TOrgPermission } from "./types";
|
export type { TOrgPermission } from "./types";
|
||||||
export {
|
export {
|
||||||
OrgPermissionActions,
|
OrgPermissionActions,
|
||||||
|
OrgPermissionAuditLogsActions,
|
||||||
OrgPermissionBillingActions,
|
OrgPermissionBillingActions,
|
||||||
OrgPermissionGroupActions,
|
OrgPermissionGroupActions,
|
||||||
OrgPermissionIdentityActions,
|
OrgPermissionIdentityActions,
|
||||||
|
|||||||
@@ -71,6 +71,10 @@ export enum OrgPermissionAppConnectionActions {
|
|||||||
Connect = "connect"
|
Connect = "connect"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum OrgPermissionAuditLogsActions {
|
||||||
|
Read = "read"
|
||||||
|
}
|
||||||
|
|
||||||
export enum OrgPermissionKmipActions {
|
export enum OrgPermissionKmipActions {
|
||||||
Proxy = "proxy",
|
Proxy = "proxy",
|
||||||
Setup = "setup"
|
Setup = "setup"
|
||||||
@@ -118,7 +122,7 @@ export type OrgPermissionSet =
|
|||||||
| [OrgPermissionBillingActions, OrgPermissionSubjects.Billing]
|
| [OrgPermissionBillingActions, OrgPermissionSubjects.Billing]
|
||||||
| [OrgPermissionActions, OrgPermissionSubjects.Kms]
|
| [OrgPermissionActions, OrgPermissionSubjects.Kms]
|
||||||
| [OrgPermissionAdminConsoleAction, OrgPermissionSubjects.AdminConsole]
|
| [OrgPermissionAdminConsoleAction, OrgPermissionSubjects.AdminConsole]
|
||||||
| [OrgPermissionActions, OrgPermissionSubjects.AuditLogs]
|
| [OrgPermissionAuditLogsActions, OrgPermissionSubjects.AuditLogs]
|
||||||
| [OrgPermissionActions, OrgPermissionSubjects.ProjectTemplates]
|
| [OrgPermissionActions, OrgPermissionSubjects.ProjectTemplates]
|
||||||
| [OrgPermissionAppConnectionActions, OrgPermissionSubjects.AppConnections]
|
| [OrgPermissionAppConnectionActions, OrgPermissionSubjects.AppConnections]
|
||||||
| [OrgPermissionIdentityActions, OrgPermissionSubjects.Identity]
|
| [OrgPermissionIdentityActions, OrgPermissionSubjects.Identity]
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ export { useProjectPermission } from "./ProjectPermissionContext";
|
|||||||
export type { ProjectPermissionSet, TProjectPermission } from "./types";
|
export type { ProjectPermissionSet, TProjectPermission } from "./types";
|
||||||
export {
|
export {
|
||||||
ProjectPermissionActions,
|
ProjectPermissionActions,
|
||||||
|
ProjectPermissionAuditLogsActions,
|
||||||
ProjectPermissionCertificateActions,
|
ProjectPermissionCertificateActions,
|
||||||
ProjectPermissionCmekActions,
|
ProjectPermissionCmekActions,
|
||||||
ProjectPermissionDynamicSecretActions,
|
ProjectPermissionDynamicSecretActions,
|
||||||
|
|||||||
@@ -150,6 +150,10 @@ export enum ProjectPermissionSecretEventActions {
|
|||||||
SubscribeImportMutations = "subscribe-on-import-mutations"
|
SubscribeImportMutations = "subscribe-on-import-mutations"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum ProjectPermissionAuditLogsActions {
|
||||||
|
Read = "read"
|
||||||
|
}
|
||||||
|
|
||||||
export enum PermissionConditionOperators {
|
export enum PermissionConditionOperators {
|
||||||
$IN = "$in",
|
$IN = "$in",
|
||||||
$ALL = "$all",
|
$ALL = "$all",
|
||||||
@@ -365,7 +369,7 @@ export type ProjectPermissionSet =
|
|||||||
| [ProjectPermissionActions, ProjectPermissionSub.Groups]
|
| [ProjectPermissionActions, ProjectPermissionSub.Groups]
|
||||||
| [ProjectPermissionActions, ProjectPermissionSub.Integrations]
|
| [ProjectPermissionActions, ProjectPermissionSub.Integrations]
|
||||||
| [ProjectPermissionActions, ProjectPermissionSub.Webhooks]
|
| [ProjectPermissionActions, ProjectPermissionSub.Webhooks]
|
||||||
| [ProjectPermissionActions, ProjectPermissionSub.AuditLogs]
|
| [ProjectPermissionAuditLogsActions, ProjectPermissionSub.AuditLogs]
|
||||||
| [ProjectPermissionActions, ProjectPermissionSub.Environments]
|
| [ProjectPermissionActions, ProjectPermissionSub.Environments]
|
||||||
| [ProjectPermissionActions, ProjectPermissionSub.IpAllowList]
|
| [ProjectPermissionActions, ProjectPermissionSub.IpAllowList]
|
||||||
| [ProjectPermissionActions, ProjectPermissionSub.Settings]
|
| [ProjectPermissionActions, ProjectPermissionSub.Settings]
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ export { useOrganization } from "./OrganizationContext";
|
|||||||
export type { TOrgPermission } from "./OrgPermissionContext";
|
export type { TOrgPermission } from "./OrgPermissionContext";
|
||||||
export {
|
export {
|
||||||
OrgPermissionActions,
|
OrgPermissionActions,
|
||||||
|
OrgPermissionAuditLogsActions,
|
||||||
OrgPermissionBillingActions,
|
OrgPermissionBillingActions,
|
||||||
OrgPermissionGroupActions,
|
OrgPermissionGroupActions,
|
||||||
OrgPermissionIdentityActions,
|
OrgPermissionIdentityActions,
|
||||||
@@ -11,6 +12,7 @@ export {
|
|||||||
export type { TProjectPermission } from "./ProjectPermissionContext";
|
export type { TProjectPermission } from "./ProjectPermissionContext";
|
||||||
export {
|
export {
|
||||||
ProjectPermissionActions,
|
ProjectPermissionActions,
|
||||||
|
ProjectPermissionAuditLogsActions,
|
||||||
ProjectPermissionCertificateActions,
|
ProjectPermissionCertificateActions,
|
||||||
ProjectPermissionCmekActions,
|
ProjectPermissionCmekActions,
|
||||||
ProjectPermissionDynamicSecretActions,
|
ProjectPermissionDynamicSecretActions,
|
||||||
|
|||||||
@@ -4,9 +4,15 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|||||||
import ms from "ms";
|
import ms from "ms";
|
||||||
|
|
||||||
import { UpgradePlanModal } from "@app/components/license/UpgradePlanModal";
|
import { UpgradePlanModal } from "@app/components/license/UpgradePlanModal";
|
||||||
import { OrgPermissionActions, OrgPermissionSubjects, useSubscription } from "@app/context";
|
import {
|
||||||
|
OrgPermissionAuditLogsActions,
|
||||||
|
OrgPermissionSubjects,
|
||||||
|
ProjectPermissionAuditLogsActions,
|
||||||
|
ProjectPermissionSub,
|
||||||
|
useSubscription
|
||||||
|
} from "@app/context";
|
||||||
import { Timezone } from "@app/helpers/datetime";
|
import { Timezone } from "@app/helpers/datetime";
|
||||||
import { withPermission } from "@app/hoc";
|
import { withPermission, withProjectPermission } from "@app/hoc";
|
||||||
import { Workspace } from "@app/hooks/api/workspace/types";
|
import { Workspace } from "@app/hooks/api/workspace/types";
|
||||||
import { usePopUp } from "@app/hooks/usePopUp";
|
import { usePopUp } from "@app/hooks/usePopUp";
|
||||||
|
|
||||||
@@ -28,153 +34,173 @@ type Props = {
|
|||||||
project?: Workspace;
|
project?: Workspace;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const LogsSection = withPermission(
|
const LogsSectionComponent = ({
|
||||||
({ presets, refetchInterval, showFilters = true, pageView = false, project }: Props) => {
|
presets,
|
||||||
const { subscription } = useSubscription();
|
refetchInterval,
|
||||||
|
showFilters = true,
|
||||||
|
pageView = false,
|
||||||
|
project
|
||||||
|
}: Props) => {
|
||||||
|
const { subscription } = useSubscription();
|
||||||
|
const { popUp, handlePopUpOpen, handlePopUpToggle } = usePopUp(["upgradePlan"] as const);
|
||||||
|
const [logFilter, setLogFilter] = useState<TAuditLogFilterFormData>({
|
||||||
|
eventType: presets?.eventType || [],
|
||||||
|
actor: presets?.actorId,
|
||||||
|
eventMetadata: presets?.eventMetadata
|
||||||
|
});
|
||||||
|
const [timezone, setTimezone] = useState<Timezone>(Timezone.Local);
|
||||||
|
|
||||||
const { popUp, handlePopUpOpen, handlePopUpToggle } = usePopUp(["upgradePlan"] as const);
|
const [dateFilter, setDateFilter] = useState<TAuditLogDateFilterFormData>(
|
||||||
const [logFilter, setLogFilter] = useState<TAuditLogFilterFormData>({
|
presets?.endDate || presets?.startDate
|
||||||
eventType: presets?.eventType || [],
|
? {
|
||||||
actor: presets?.actorId,
|
type: AuditLogDateFilterType.Absolute,
|
||||||
eventMetadata: presets?.eventMetadata
|
startDate: presets?.startDate || new Date(Number(new Date()) - ms("1h")),
|
||||||
});
|
endDate: presets?.endDate || new Date()
|
||||||
const [timezone, setTimezone] = useState<Timezone>(Timezone.Local);
|
}
|
||||||
|
: {
|
||||||
|
startDate: new Date(Number(new Date()) - ms("1h")),
|
||||||
|
endDate: new Date(),
|
||||||
|
type: AuditLogDateFilterType.Relative,
|
||||||
|
relativeModeValue: "1h"
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const [dateFilter, setDateFilter] = useState<TAuditLogDateFilterFormData>(
|
useEffect(() => {
|
||||||
presets?.endDate || presets?.startDate
|
if (subscription && !subscription.auditLogs) {
|
||||||
? {
|
handlePopUpOpen("upgradePlan");
|
||||||
type: AuditLogDateFilterType.Absolute,
|
}
|
||||||
startDate: presets?.startDate || new Date(Number(new Date()) - ms("1h")),
|
}, [subscription]);
|
||||||
endDate: presets?.endDate || new Date()
|
|
||||||
}
|
|
||||||
: {
|
|
||||||
startDate: new Date(Number(new Date()) - ms("1h")),
|
|
||||||
endDate: new Date(),
|
|
||||||
type: AuditLogDateFilterType.Relative,
|
|
||||||
relativeModeValue: "1h"
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (subscription && !subscription.auditLogs) {
|
|
||||||
handlePopUpOpen("upgradePlan");
|
|
||||||
}
|
|
||||||
}, [subscription]);
|
|
||||||
|
|
||||||
if (pageView)
|
|
||||||
return (
|
|
||||||
<div className="w-full rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
|
||||||
<div className="mb-4 flex flex-wrap items-center justify-between gap-y-2">
|
|
||||||
<div>
|
|
||||||
<div className="flex items-center gap-1 whitespace-nowrap">
|
|
||||||
<p className="text-xl font-semibold text-mineshaft-100">Audit History</p>
|
|
||||||
<a
|
|
||||||
href="https://infisical.com/docs/documentation/platform/audit-logs"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
<div className="ml-1 mt-[0.1rem] inline-block rounded-md bg-yellow/20 px-1.5 text-sm text-yellow opacity-80 hover:opacity-100">
|
|
||||||
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
|
|
||||||
<span>Docs</span>
|
|
||||||
<FontAwesomeIcon
|
|
||||||
icon={faArrowUpRightFromSquare}
|
|
||||||
className="mb-[0.07rem] ml-1.5 text-[10px]"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-wrap items-center gap-2 lg:justify-end">
|
|
||||||
{showFilters && (
|
|
||||||
<LogsDateFilter
|
|
||||||
filter={dateFilter}
|
|
||||||
setFilter={setDateFilter}
|
|
||||||
timezone={timezone}
|
|
||||||
setTimezone={setTimezone}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{showFilters && (
|
|
||||||
<LogsFilter
|
|
||||||
project={project}
|
|
||||||
presets={presets}
|
|
||||||
setFilter={setLogFilter}
|
|
||||||
filter={logFilter}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="space-y-2">
|
|
||||||
<LogsTable
|
|
||||||
refetchInterval={refetchInterval}
|
|
||||||
filter={{
|
|
||||||
secretPath: logFilter.secretPath || undefined,
|
|
||||||
secretKey: logFilter.secretKey || undefined,
|
|
||||||
eventMetadata: logFilter?.eventMetadata,
|
|
||||||
projectId: project?.id || logFilter?.project?.id,
|
|
||||||
actorType: presets?.actorType,
|
|
||||||
limit: 15,
|
|
||||||
eventType: logFilter?.eventType,
|
|
||||||
userAgentType: logFilter?.userAgentType,
|
|
||||||
startDate: dateFilter?.startDate,
|
|
||||||
endDate: dateFilter?.endDate,
|
|
||||||
environment: logFilter?.environment?.slug,
|
|
||||||
actor: logFilter?.actor
|
|
||||||
}}
|
|
||||||
timezone={timezone}
|
|
||||||
/>
|
|
||||||
<UpgradePlanModal
|
|
||||||
isOpen={popUp.upgradePlan.isOpen}
|
|
||||||
onOpenChange={(isOpen) => {
|
|
||||||
handlePopUpToggle("upgradePlan", isOpen);
|
|
||||||
}}
|
|
||||||
text="You can use audit logs if you switch to a paid Infisical plan."
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
|
if (pageView)
|
||||||
return (
|
return (
|
||||||
<div className="space-y-2">
|
<div className="w-full rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
||||||
<div className="flex flex-wrap items-center gap-2 lg:justify-end">
|
<div className="mb-4 flex flex-wrap items-center justify-between gap-y-2">
|
||||||
{showFilters && (
|
<div>
|
||||||
<LogsDateFilter
|
<div className="flex items-center gap-1 whitespace-nowrap">
|
||||||
filter={dateFilter}
|
<p className="text-xl font-semibold text-mineshaft-100">Audit History</p>
|
||||||
setFilter={setDateFilter}
|
<a
|
||||||
timezone={timezone}
|
href="https://infisical.com/docs/documentation/platform/audit-logs"
|
||||||
setTimezone={setTimezone}
|
target="_blank"
|
||||||
/>
|
rel="noopener noreferrer"
|
||||||
)}
|
>
|
||||||
{showFilters && (
|
<div className="ml-1 mt-[0.1rem] inline-block rounded-md bg-yellow/20 px-1.5 text-sm text-yellow opacity-80 hover:opacity-100">
|
||||||
<LogsFilter presets={presets} setFilter={setLogFilter} filter={logFilter} />
|
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
|
||||||
)}
|
<span>Docs</span>
|
||||||
|
<FontAwesomeIcon
|
||||||
|
icon={faArrowUpRightFromSquare}
|
||||||
|
className="mb-[0.07rem] ml-1.5 text-[10px]"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-wrap items-center gap-2 lg:justify-end">
|
||||||
|
{showFilters && (
|
||||||
|
<LogsDateFilter
|
||||||
|
filter={dateFilter}
|
||||||
|
setFilter={setDateFilter}
|
||||||
|
timezone={timezone}
|
||||||
|
setTimezone={setTimezone}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{showFilters && (
|
||||||
|
<LogsFilter
|
||||||
|
project={project}
|
||||||
|
presets={presets}
|
||||||
|
setFilter={setLogFilter}
|
||||||
|
filter={logFilter}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-2">
|
||||||
|
<LogsTable
|
||||||
|
refetchInterval={refetchInterval}
|
||||||
|
filter={{
|
||||||
|
secretPath: logFilter.secretPath || undefined,
|
||||||
|
secretKey: logFilter.secretKey || undefined,
|
||||||
|
eventMetadata: logFilter?.eventMetadata,
|
||||||
|
projectId: project?.id || logFilter?.project?.id,
|
||||||
|
actorType: presets?.actorType,
|
||||||
|
limit: 15,
|
||||||
|
eventType: logFilter?.eventType,
|
||||||
|
userAgentType: logFilter?.userAgentType,
|
||||||
|
startDate: dateFilter?.startDate,
|
||||||
|
endDate: dateFilter?.endDate,
|
||||||
|
environment: logFilter?.environment?.slug,
|
||||||
|
actor: logFilter?.actor
|
||||||
|
}}
|
||||||
|
timezone={timezone}
|
||||||
|
/>
|
||||||
|
<UpgradePlanModal
|
||||||
|
isOpen={popUp.upgradePlan.isOpen}
|
||||||
|
onOpenChange={(isOpen) => {
|
||||||
|
handlePopUpToggle("upgradePlan", isOpen);
|
||||||
|
}}
|
||||||
|
text="You can use audit logs if you switch to a paid Infisical plan."
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<LogsTable
|
|
||||||
refetchInterval={refetchInterval}
|
|
||||||
filter={{
|
|
||||||
secretPath: logFilter.secretPath || undefined,
|
|
||||||
secretKey: logFilter.secretKey || undefined,
|
|
||||||
eventMetadata: logFilter?.eventMetadata,
|
|
||||||
projectId: logFilter?.project?.id,
|
|
||||||
actorType: presets?.actorType,
|
|
||||||
limit: 15,
|
|
||||||
eventType: logFilter?.eventType,
|
|
||||||
userAgentType: logFilter?.userAgentType,
|
|
||||||
startDate: dateFilter?.startDate,
|
|
||||||
endDate: dateFilter?.endDate,
|
|
||||||
environment: logFilter?.environment?.slug,
|
|
||||||
actor: logFilter?.actor
|
|
||||||
}}
|
|
||||||
timezone={timezone}
|
|
||||||
/>
|
|
||||||
<UpgradePlanModal
|
|
||||||
isOpen={popUp.upgradePlan.isOpen}
|
|
||||||
onOpenChange={(isOpen) => {
|
|
||||||
handlePopUpToggle("upgradePlan", isOpen);
|
|
||||||
}}
|
|
||||||
text="You can use audit logs if you switch to a paid Infisical plan."
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
},
|
|
||||||
{ action: OrgPermissionActions.Read, subject: OrgPermissionSubjects.AuditLogs }
|
return (
|
||||||
);
|
<div className="space-y-2">
|
||||||
|
<div className="flex flex-wrap items-center gap-2 lg:justify-end">
|
||||||
|
{showFilters && (
|
||||||
|
<LogsDateFilter
|
||||||
|
filter={dateFilter}
|
||||||
|
setFilter={setDateFilter}
|
||||||
|
timezone={timezone}
|
||||||
|
setTimezone={setTimezone}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{showFilters && (
|
||||||
|
<LogsFilter presets={presets} setFilter={setLogFilter} filter={logFilter} />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<LogsTable
|
||||||
|
refetchInterval={refetchInterval}
|
||||||
|
filter={{
|
||||||
|
secretPath: logFilter.secretPath || undefined,
|
||||||
|
secretKey: logFilter.secretKey || undefined,
|
||||||
|
eventMetadata: logFilter?.eventMetadata,
|
||||||
|
projectId: project?.id || logFilter?.project?.id,
|
||||||
|
actorType: presets?.actorType,
|
||||||
|
limit: 15,
|
||||||
|
eventType: logFilter?.eventType,
|
||||||
|
userAgentType: logFilter?.userAgentType,
|
||||||
|
startDate: dateFilter?.startDate,
|
||||||
|
endDate: dateFilter?.endDate,
|
||||||
|
environment: logFilter?.environment?.slug,
|
||||||
|
actor: logFilter?.actor
|
||||||
|
}}
|
||||||
|
timezone={timezone}
|
||||||
|
/>
|
||||||
|
<UpgradePlanModal
|
||||||
|
isOpen={popUp.upgradePlan.isOpen}
|
||||||
|
onOpenChange={(isOpen) => {
|
||||||
|
handlePopUpToggle("upgradePlan", isOpen);
|
||||||
|
}}
|
||||||
|
text="You can use audit logs if you switch to a paid Infisical plan."
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const LogsSection = (props: Props) => {
|
||||||
|
const { project } = props;
|
||||||
|
|
||||||
|
if (project) {
|
||||||
|
const ProjectLogsSectionWithPermission = withProjectPermission(LogsSectionComponent, {
|
||||||
|
action: ProjectPermissionAuditLogsActions.Read,
|
||||||
|
subject: ProjectPermissionSub.AuditLogs
|
||||||
|
});
|
||||||
|
return <ProjectLogsSectionWithPermission {...props} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
const OrgLogsSectionWithPermission = withPermission(LogsSectionComponent, {
|
||||||
|
action: OrgPermissionAuditLogsActions.Read,
|
||||||
|
subject: OrgPermissionSubjects.AuditLogs
|
||||||
|
});
|
||||||
|
return <OrgLogsSectionWithPermission {...props} />;
|
||||||
|
};
|
||||||
|
|||||||
+8
-1
@@ -5,6 +5,7 @@ import { OrgPermissionSubjects } from "@app/context";
|
|||||||
import {
|
import {
|
||||||
OrgGatewayPermissionActions,
|
OrgGatewayPermissionActions,
|
||||||
OrgPermissionAppConnectionActions,
|
OrgPermissionAppConnectionActions,
|
||||||
|
OrgPermissionAuditLogsActions,
|
||||||
OrgPermissionBillingActions,
|
OrgPermissionBillingActions,
|
||||||
OrgPermissionGroupActions,
|
OrgPermissionGroupActions,
|
||||||
OrgPermissionIdentityActions,
|
OrgPermissionIdentityActions,
|
||||||
@@ -23,6 +24,12 @@ const generalPermissionSchema = z
|
|||||||
})
|
})
|
||||||
.optional();
|
.optional();
|
||||||
|
|
||||||
|
const auditLogsPermissionSchema = z
|
||||||
|
.object({
|
||||||
|
[OrgPermissionAuditLogsActions.Read]: z.boolean().optional()
|
||||||
|
})
|
||||||
|
.optional();
|
||||||
|
|
||||||
const billingPermissionSchema = z
|
const billingPermissionSchema = z
|
||||||
.object({
|
.object({
|
||||||
[OrgPermissionBillingActions.Read]: z.boolean().optional(),
|
[OrgPermissionBillingActions.Read]: z.boolean().optional(),
|
||||||
@@ -121,7 +128,7 @@ export const formSchema = z.object({
|
|||||||
})
|
})
|
||||||
.optional(),
|
.optional(),
|
||||||
|
|
||||||
"audit-logs": generalPermissionSchema,
|
"audit-logs": auditLogsPermissionSchema,
|
||||||
member: generalPermissionSchema,
|
member: generalPermissionSchema,
|
||||||
groups: groupPermissionSchema,
|
groups: groupPermissionSchema,
|
||||||
role: generalPermissionSchema,
|
role: generalPermissionSchema,
|
||||||
|
|||||||
+164
@@ -0,0 +1,164 @@
|
|||||||
|
import { useEffect, useMemo } from "react";
|
||||||
|
import { Control, Controller, UseFormSetValue, useWatch } from "react-hook-form";
|
||||||
|
import { faChevronDown, faChevronRight } from "@fortawesome/free-solid-svg-icons";
|
||||||
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
|
||||||
|
import { createNotification } from "@app/components/notifications";
|
||||||
|
import { Checkbox, Select, SelectItem, Td, Tr } from "@app/components/v2";
|
||||||
|
import { OrgPermissionAuditLogsActions } from "@app/context/OrgPermissionContext/types";
|
||||||
|
import { useToggle } from "@app/hooks";
|
||||||
|
|
||||||
|
import { TFormSchema } from "../OrgRoleModifySection.utils";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
isEditable: boolean;
|
||||||
|
setValue: UseFormSetValue<TFormSchema>;
|
||||||
|
control: Control<TFormSchema>;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Permission {
|
||||||
|
NoAccess = "no-access",
|
||||||
|
ReadOnly = "read-only",
|
||||||
|
FullAccess = "full-access",
|
||||||
|
Custom = "custom"
|
||||||
|
}
|
||||||
|
|
||||||
|
const PERMISSION_ACTIONS = [
|
||||||
|
{
|
||||||
|
action: OrgPermissionAuditLogsActions.Read,
|
||||||
|
label: "View"
|
||||||
|
}
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
export const OrgPermissionAuditLogsRow = ({ isEditable, control, setValue }: Props) => {
|
||||||
|
const [isRowExpanded, setIsRowExpanded] = useToggle();
|
||||||
|
const [isCustom, setIsCustom] = useToggle();
|
||||||
|
|
||||||
|
const rule = useWatch({
|
||||||
|
control,
|
||||||
|
name: "permissions.audit-logs"
|
||||||
|
});
|
||||||
|
|
||||||
|
const selectedPermissionCategory = useMemo(() => {
|
||||||
|
const actions = Object.keys(rule || {}) as Array<keyof typeof rule>;
|
||||||
|
const totalActions = PERMISSION_ACTIONS.length;
|
||||||
|
const score = actions.map((key) => (rule?.[key] ? 1 : 0)).reduce((a, b) => a + b, 0 as number);
|
||||||
|
|
||||||
|
if (isCustom) return Permission.Custom;
|
||||||
|
if (score === 0) return Permission.NoAccess;
|
||||||
|
if (score === totalActions) return Permission.FullAccess;
|
||||||
|
if (score === 1 && rule?.[OrgPermissionAuditLogsActions.Read]) return Permission.ReadOnly;
|
||||||
|
|
||||||
|
return Permission.Custom;
|
||||||
|
}, [rule, isCustom]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (selectedPermissionCategory === Permission.Custom) setIsCustom.on();
|
||||||
|
else setIsCustom.off();
|
||||||
|
}, [selectedPermissionCategory]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const isRowCustom = selectedPermissionCategory === Permission.Custom;
|
||||||
|
if (isRowCustom) {
|
||||||
|
setIsRowExpanded.on();
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handlePermissionChange = (val: Permission) => {
|
||||||
|
if (!val) return;
|
||||||
|
if (val === Permission.Custom) {
|
||||||
|
setIsRowExpanded.on();
|
||||||
|
setIsCustom.on();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setIsCustom.off();
|
||||||
|
|
||||||
|
switch (val) {
|
||||||
|
case Permission.FullAccess:
|
||||||
|
case Permission.ReadOnly:
|
||||||
|
// For audit logs, both full access and read-only are the same - just read access
|
||||||
|
setValue(
|
||||||
|
"permissions.audit-logs",
|
||||||
|
{
|
||||||
|
[OrgPermissionAuditLogsActions.Read]: true
|
||||||
|
},
|
||||||
|
{ shouldDirty: true }
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Permission.NoAccess:
|
||||||
|
default:
|
||||||
|
setValue(
|
||||||
|
"permissions.audit-logs",
|
||||||
|
{
|
||||||
|
[OrgPermissionAuditLogsActions.Read]: false
|
||||||
|
},
|
||||||
|
{ shouldDirty: true }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Tr
|
||||||
|
className="h-10 cursor-pointer transition-colors duration-100 hover:bg-mineshaft-700"
|
||||||
|
onClick={() => setIsRowExpanded.toggle()}
|
||||||
|
>
|
||||||
|
<Td className="w-4">
|
||||||
|
<FontAwesomeIcon className="w-4" icon={isRowExpanded ? faChevronDown : faChevronRight} />
|
||||||
|
</Td>
|
||||||
|
<Td className="w-full select-none">Audit Logs</Td>
|
||||||
|
<Td>
|
||||||
|
<Select
|
||||||
|
value={selectedPermissionCategory}
|
||||||
|
className="h-8 w-40 bg-mineshaft-700"
|
||||||
|
dropdownContainerClassName="border text-left border-mineshaft-600 bg-mineshaft-800"
|
||||||
|
onValueChange={handlePermissionChange}
|
||||||
|
isDisabled={!isEditable}
|
||||||
|
position="popper"
|
||||||
|
>
|
||||||
|
<SelectItem value={Permission.NoAccess}>No Access</SelectItem>
|
||||||
|
<SelectItem value={Permission.ReadOnly}>Read Only</SelectItem>
|
||||||
|
<SelectItem value={Permission.FullAccess}>Full Access</SelectItem>
|
||||||
|
<SelectItem value={Permission.Custom}>Custom</SelectItem>
|
||||||
|
</Select>
|
||||||
|
</Td>
|
||||||
|
</Tr>
|
||||||
|
{isRowExpanded && (
|
||||||
|
<Tr>
|
||||||
|
<Td colSpan={3} className="border-mineshaft-500 bg-mineshaft-900 p-8">
|
||||||
|
<div className="flex flex-grow flex-wrap justify-start gap-x-8 gap-y-4">
|
||||||
|
{PERMISSION_ACTIONS.map(({ action, label }) => {
|
||||||
|
return (
|
||||||
|
<Controller
|
||||||
|
name={`permissions.audit-logs.${action}`}
|
||||||
|
key={`permissions.audit-logs.${action}`}
|
||||||
|
control={control}
|
||||||
|
render={({ field }) => (
|
||||||
|
<Checkbox
|
||||||
|
isChecked={Boolean(field.value)}
|
||||||
|
onCheckedChange={(e) => {
|
||||||
|
if (!isEditable) {
|
||||||
|
createNotification({
|
||||||
|
type: "error",
|
||||||
|
text: "Failed to update default role"
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
field.onChange(e);
|
||||||
|
}}
|
||||||
|
id={`permissions.audit-logs.${action}`}
|
||||||
|
>
|
||||||
|
{label}
|
||||||
|
</Checkbox>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</Td>
|
||||||
|
</Tr>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
+1
@@ -71,6 +71,7 @@ type Props = {
|
|||||||
| "gateway"
|
| "gateway"
|
||||||
| "secret-share"
|
| "secret-share"
|
||||||
| "billing"
|
| "billing"
|
||||||
|
| "audit-logs"
|
||||||
| "machine-identity-auth-template"
|
| "machine-identity-auth-template"
|
||||||
>;
|
>;
|
||||||
setValue: UseFormSetValue<TFormSchema>;
|
setValue: UseFormSetValue<TFormSchema>;
|
||||||
|
|||||||
+6
-4
@@ -16,6 +16,7 @@ import {
|
|||||||
TFormSchema
|
TFormSchema
|
||||||
} from "../OrgRoleModifySection.utils";
|
} from "../OrgRoleModifySection.utils";
|
||||||
import { OrgPermissionAdminConsoleRow } from "./OrgPermissionAdminConsoleRow";
|
import { OrgPermissionAdminConsoleRow } from "./OrgPermissionAdminConsoleRow";
|
||||||
|
import { OrgPermissionAuditLogsRow } from "./OrgPermissionAuditLogsRow";
|
||||||
import { OrgPermissionBillingRow } from "./OrgPermissionBillingRow";
|
import { OrgPermissionBillingRow } from "./OrgPermissionBillingRow";
|
||||||
import { OrgGatewayPermissionRow } from "./OrgPermissionGatewayRow";
|
import { OrgGatewayPermissionRow } from "./OrgPermissionGatewayRow";
|
||||||
import { OrgPermissionGroupRow } from "./OrgPermissionGroupRow";
|
import { OrgPermissionGroupRow } from "./OrgPermissionGroupRow";
|
||||||
@@ -39,10 +40,6 @@ const SIMPLE_PERMISSION_OPTIONS = [
|
|||||||
title: "Incident Contacts",
|
title: "Incident Contacts",
|
||||||
formName: "incident-contact"
|
formName: "incident-contact"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: "Audit Logs",
|
|
||||||
formName: "audit-logs"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: "Organization Profile",
|
title: "Organization Profile",
|
||||||
formName: "settings"
|
formName: "settings"
|
||||||
@@ -166,6 +163,11 @@ export const RolePermissionsSection = ({ roleId }: Props) => {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
<OrgPermissionAuditLogsRow
|
||||||
|
control={control}
|
||||||
|
setValue={setValue}
|
||||||
|
isEditable={isCustomRole}
|
||||||
|
/>
|
||||||
<OrgPermissionIdentityRow
|
<OrgPermissionIdentityRow
|
||||||
control={control}
|
control={control}
|
||||||
setValue={setValue}
|
setValue={setValue}
|
||||||
|
|||||||
+8
-8
@@ -12,6 +12,7 @@ import {
|
|||||||
} from "@app/context";
|
} from "@app/context";
|
||||||
import {
|
import {
|
||||||
PermissionConditionOperators,
|
PermissionConditionOperators,
|
||||||
|
ProjectPermissionAuditLogsActions,
|
||||||
ProjectPermissionCommitsActions,
|
ProjectPermissionCommitsActions,
|
||||||
ProjectPermissionDynamicSecretActions,
|
ProjectPermissionDynamicSecretActions,
|
||||||
ProjectPermissionGroupActions,
|
ProjectPermissionGroupActions,
|
||||||
@@ -41,6 +42,10 @@ const GeneralPolicyActionSchema = z.object({
|
|||||||
create: z.boolean().optional()
|
create: z.boolean().optional()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const AuditLogsPolicyActionSchema = z.object({
|
||||||
|
[ProjectPermissionAuditLogsActions.Read]: z.boolean().optional()
|
||||||
|
});
|
||||||
|
|
||||||
const CertificatePolicyActionSchema = z.object({
|
const CertificatePolicyActionSchema = z.object({
|
||||||
[ProjectPermissionCertificateActions.Create]: z.boolean().optional(),
|
[ProjectPermissionCertificateActions.Create]: z.boolean().optional(),
|
||||||
[ProjectPermissionCertificateActions.Delete]: z.boolean().optional(),
|
[ProjectPermissionCertificateActions.Delete]: z.boolean().optional(),
|
||||||
@@ -316,7 +321,7 @@ export const projectRoleFormSchema = z.object({
|
|||||||
[ProjectPermissionSub.ServiceTokens]: GeneralPolicyActionSchema.array().default([]),
|
[ProjectPermissionSub.ServiceTokens]: GeneralPolicyActionSchema.array().default([]),
|
||||||
[ProjectPermissionSub.Settings]: GeneralPolicyActionSchema.array().default([]),
|
[ProjectPermissionSub.Settings]: GeneralPolicyActionSchema.array().default([]),
|
||||||
[ProjectPermissionSub.Environments]: GeneralPolicyActionSchema.array().default([]),
|
[ProjectPermissionSub.Environments]: GeneralPolicyActionSchema.array().default([]),
|
||||||
[ProjectPermissionSub.AuditLogs]: GeneralPolicyActionSchema.array().default([]),
|
[ProjectPermissionSub.AuditLogs]: AuditLogsPolicyActionSchema.array().default([]),
|
||||||
[ProjectPermissionSub.IpAllowList]: GeneralPolicyActionSchema.array().default([]),
|
[ProjectPermissionSub.IpAllowList]: GeneralPolicyActionSchema.array().default([]),
|
||||||
[ProjectPermissionSub.CertificateAuthorities]: GeneralPolicyActionSchema.array().default([]),
|
[ProjectPermissionSub.CertificateAuthorities]: GeneralPolicyActionSchema.array().default([]),
|
||||||
[ProjectPermissionSub.Certificates]: CertificatePolicyActionSchema.array().default([]),
|
[ProjectPermissionSub.Certificates]: CertificatePolicyActionSchema.array().default([]),
|
||||||
@@ -1324,12 +1329,7 @@ export const PROJECT_PERMISSION_OBJECT: TProjectPermissionObject = {
|
|||||||
},
|
},
|
||||||
[ProjectPermissionSub.AuditLogs]: {
|
[ProjectPermissionSub.AuditLogs]: {
|
||||||
title: "Audit Logs",
|
title: "Audit Logs",
|
||||||
actions: [
|
actions: [{ label: "Read", value: ProjectPermissionAuditLogsActions.Read }]
|
||||||
{ label: "Read", value: "read" },
|
|
||||||
{ label: "Create", value: "create" },
|
|
||||||
{ label: "Modify", value: "edit" },
|
|
||||||
{ label: "Remove", value: "delete" }
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
[ProjectPermissionSub.IpAllowList]: {
|
[ProjectPermissionSub.IpAllowList]: {
|
||||||
title: "IP Allowlist",
|
title: "IP Allowlist",
|
||||||
@@ -1721,7 +1721,7 @@ const projectManagerTemplate = (
|
|||||||
permissions: [
|
permissions: [
|
||||||
{
|
{
|
||||||
subject: ProjectPermissionSub.AuditLogs,
|
subject: ProjectPermissionSub.AuditLogs,
|
||||||
actions: Object.values(ProjectPermissionActions)
|
actions: Object.values(ProjectPermissionAuditLogsActions)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
subject: ProjectPermissionSub.Groups,
|
subject: ProjectPermissionSub.Groups,
|
||||||
|
|||||||
+3
-1
@@ -1,7 +1,7 @@
|
|||||||
import { Link } from "@tanstack/react-router";
|
import { Link } from "@tanstack/react-router";
|
||||||
|
|
||||||
import { EmptyState } from "@app/components/v2";
|
import { EmptyState } from "@app/components/v2";
|
||||||
import { useSubscription } from "@app/context";
|
import { useSubscription, useWorkspace } from "@app/context";
|
||||||
import { EventType } from "@app/hooks/api/auditLogs/enums";
|
import { EventType } from "@app/hooks/api/auditLogs/enums";
|
||||||
import { TIntegrationWithEnv } from "@app/hooks/api/integrations/types";
|
import { TIntegrationWithEnv } from "@app/hooks/api/integrations/types";
|
||||||
import { LogsSection } from "@app/pages/organization/AuditLogsPage/components/LogsSection";
|
import { LogsSection } from "@app/pages/organization/AuditLogsPage/components/LogsSection";
|
||||||
@@ -15,6 +15,7 @@ type Props = {
|
|||||||
|
|
||||||
export const IntegrationAuditLogsSection = ({ integration }: Props) => {
|
export const IntegrationAuditLogsSection = ({ integration }: Props) => {
|
||||||
const { subscription } = useSubscription();
|
const { subscription } = useSubscription();
|
||||||
|
const { currentWorkspace } = useWorkspace();
|
||||||
|
|
||||||
const auditLogsRetentionDays = subscription?.auditLogsRetentionDays ?? 30;
|
const auditLogsRetentionDays = subscription?.auditLogsRetentionDays ?? 30;
|
||||||
|
|
||||||
@@ -30,6 +31,7 @@ export const IntegrationAuditLogsSection = ({ integration }: Props) => {
|
|||||||
<LogsSection
|
<LogsSection
|
||||||
refetchInterval={4000}
|
refetchInterval={4000}
|
||||||
showFilters={false}
|
showFilters={false}
|
||||||
|
project={currentWorkspace}
|
||||||
presets={{
|
presets={{
|
||||||
eventMetadata: { integrationId: integration.id },
|
eventMetadata: { integrationId: integration.id },
|
||||||
startDate: new Date(
|
startDate: new Date(
|
||||||
|
|||||||
+3
-1
@@ -2,7 +2,7 @@ import { faFingerprint } from "@fortawesome/free-solid-svg-icons";
|
|||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import { Link } from "@tanstack/react-router";
|
import { Link } from "@tanstack/react-router";
|
||||||
|
|
||||||
import { useSubscription } from "@app/context";
|
import { useSubscription, useWorkspace } from "@app/context";
|
||||||
import { EventType } from "@app/hooks/api/auditLogs/enums";
|
import { EventType } from "@app/hooks/api/auditLogs/enums";
|
||||||
import { TSecretSync } from "@app/hooks/api/secretSyncs";
|
import { TSecretSync } from "@app/hooks/api/secretSyncs";
|
||||||
import { LogsSection } from "@app/pages/organization/AuditLogsPage/components/LogsSection";
|
import { LogsSection } from "@app/pages/organization/AuditLogsPage/components/LogsSection";
|
||||||
@@ -19,6 +19,7 @@ type Props = {
|
|||||||
|
|
||||||
export const SecretSyncAuditLogsSection = ({ secretSync }: Props) => {
|
export const SecretSyncAuditLogsSection = ({ secretSync }: Props) => {
|
||||||
const { subscription } = useSubscription();
|
const { subscription } = useSubscription();
|
||||||
|
const { currentWorkspace } = useWorkspace();
|
||||||
|
|
||||||
const auditLogsRetentionDays = subscription?.auditLogsRetentionDays ?? 30;
|
const auditLogsRetentionDays = subscription?.auditLogsRetentionDays ?? 30;
|
||||||
|
|
||||||
@@ -36,6 +37,7 @@ export const SecretSyncAuditLogsSection = ({ secretSync }: Props) => {
|
|||||||
<LogsSection
|
<LogsSection
|
||||||
refetchInterval={4000}
|
refetchInterval={4000}
|
||||||
showFilters={false}
|
showFilters={false}
|
||||||
|
project={currentWorkspace}
|
||||||
presets={{
|
presets={{
|
||||||
eventMetadata: { syncId: secretSync.id },
|
eventMetadata: { syncId: secretSync.id },
|
||||||
startDate: new Date(
|
startDate: new Date(
|
||||||
|
|||||||
Reference in New Issue
Block a user