feat: switched audit log stream from project level to org level

This commit is contained in:
Akhil Mohan
2024-05-03 00:23:59 +05:30
parent fa18ca41ac
commit 68a1aa6f46
18 changed files with 92 additions and 147 deletions
@@ -13,8 +13,8 @@ export async function up(knex: Knex): Promise<void> {
t.text("encryptedTokenTag"); t.text("encryptedTokenTag");
t.string("encryptedTokenAlgorithm"); t.string("encryptedTokenAlgorithm");
t.string("encryptedTokenKeyEncoding"); t.string("encryptedTokenKeyEncoding");
t.string("projectId").notNullable(); t.uuid("orgId").notNullable();
t.foreign("projectId").references("id").inTable(TableName.Project).onDelete("CASCADE"); t.foreign("orgId").references("id").inTable(TableName.Organization).onDelete("CASCADE");
t.timestamps(true, true, true); t.timestamps(true, true, true);
}); });
} }
+1 -1
View File
@@ -15,7 +15,7 @@ export const AuditLogStreamsSchema = z.object({
encryptedTokenTag: z.string().nullable().optional(), encryptedTokenTag: z.string().nullable().optional(),
encryptedTokenAlgorithm: z.string().nullable().optional(), encryptedTokenAlgorithm: z.string().nullable().optional(),
encryptedTokenKeyEncoding: z.string().nullable().optional(), encryptedTokenKeyEncoding: z.string().nullable().optional(),
projectId: z.string(), orgId: z.string().uuid(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date() updatedAt: z.date()
}); });
@@ -21,7 +21,6 @@ export const registerAuditLogStreamRouter = async (server: FastifyZodProvider) =
} }
], ],
body: z.object({ body: z.object({
projectSlug: z.string().min(1).describe(AUDIT_LOG_STREAMS.CREATE.projectSlug),
url: z.string().min(1).describe(AUDIT_LOG_STREAMS.CREATE.url), url: z.string().min(1).describe(AUDIT_LOG_STREAMS.CREATE.url),
token: z.string().optional().describe(AUDIT_LOG_STREAMS.CREATE.token) token: z.string().optional().describe(AUDIT_LOG_STREAMS.CREATE.token)
}), }),
@@ -38,7 +37,6 @@ export const registerAuditLogStreamRouter = async (server: FastifyZodProvider) =
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
actorAuthMethod: req.permission.authMethod, actorAuthMethod: req.permission.authMethod,
projectSlug: req.body.projectSlug,
url: req.body.url, url: req.body.url,
token: req.body.token token: req.body.token
}); });
@@ -174,9 +172,6 @@ export const registerAuditLogStreamRouter = async (server: FastifyZodProvider) =
bearerAuth: [] bearerAuth: []
} }
], ],
querystring: z.object({
projectSlug: z.string().describe(AUDIT_LOG_STREAMS.LIST.projectSlug)
}),
response: { response: {
200: z.object({ 200: z.object({
auditLogStreams: SanitizedAuditLogStreamSchema.array() auditLogStreams: SanitizedAuditLogStreamSchema.array()
@@ -189,8 +184,7 @@ export const registerAuditLogStreamRouter = async (server: FastifyZodProvider) =
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
actorAuthMethod: req.permission.authMethod, actorAuthMethod: req.permission.authMethod
projectSlug: req.query.projectSlug
}); });
return { auditLogStreams }; return { auditLogStreams };
@@ -4,11 +4,10 @@ import { SecretKeyEncoding } from "@app/db/schemas";
import { infisicalSymmetricDecrypt, infisicalSymmetricEncypt } from "@app/lib/crypto/encryption"; import { infisicalSymmetricDecrypt, infisicalSymmetricEncypt } from "@app/lib/crypto/encryption";
import { BadRequestError } from "@app/lib/errors"; import { BadRequestError } from "@app/lib/errors";
import { validateLocalIps } from "@app/lib/validator"; import { validateLocalIps } from "@app/lib/validator";
import { TProjectDALFactory } from "@app/services/project/project-dal";
import { TLicenseServiceFactory } from "../license/license-service"; import { TLicenseServiceFactory } from "../license/license-service";
import { OrgPermissionActions, OrgPermissionSubjects } from "../permission/org-permission";
import { TPermissionServiceFactory } from "../permission/permission-service"; import { TPermissionServiceFactory } from "../permission/permission-service";
import { ProjectPermissionActions, ProjectPermissionSub } from "../permission/project-permission";
import { TAuditLogStreamDALFactory } from "./audit-log-stream-dal"; import { TAuditLogStreamDALFactory } from "./audit-log-stream-dal";
import { import {
TCreateAuditLogStreamDTO, TCreateAuditLogStreamDTO,
@@ -20,8 +19,7 @@ import {
type TAuditLogStreamServiceFactoryDep = { type TAuditLogStreamServiceFactoryDep = {
auditLogStreamDAL: TAuditLogStreamDALFactory; auditLogStreamDAL: TAuditLogStreamDALFactory;
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">; permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
projectDAL: Pick<TProjectDALFactory, "findProjectBySlug">;
licenseService: Pick<TLicenseServiceFactory, "getPlan">; licenseService: Pick<TLicenseServiceFactory, "getPlan">;
}; };
@@ -30,40 +28,29 @@ export type TAuditLogStreamServiceFactory = ReturnType<typeof auditLogStreamServ
export const auditLogStreamServiceFactory = ({ export const auditLogStreamServiceFactory = ({
auditLogStreamDAL, auditLogStreamDAL,
permissionService, permissionService,
projectDAL,
licenseService licenseService
}: TAuditLogStreamServiceFactoryDep) => { }: TAuditLogStreamServiceFactoryDep) => {
const create = async ({ const create = async ({ url, actor, token, actorId, actorOrgId, actorAuthMethod }: TCreateAuditLogStreamDTO) => {
projectSlug, if (!actorOrgId) throw new BadRequestError({ message: "Missing org id from token" });
url,
actor,
token,
actorId,
actorOrgId,
actorAuthMethod
}: TCreateAuditLogStreamDTO) => {
const plan = await licenseService.getPlan(actorOrgId); const plan = await licenseService.getPlan(actorOrgId);
if (!plan.auditLogStreams) if (!plan.auditLogStreams)
throw new BadRequestError({ throw new BadRequestError({
message: "Failed to create audit log streams due to plan restriction. Upgrade plan to create group." message: "Failed to create audit log streams due to plan restriction. Upgrade plan to create group."
}); });
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId); const { permission } = await permissionService.getOrgPermission(
if (!project) throw new BadRequestError({ message: "Project not found" });
const projectId = project.id;
const { permission } = await permissionService.getProjectPermission(
actor, actor,
actorId, actorId,
projectId, actorOrgId,
actorAuthMethod, actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Settings); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Settings);
validateLocalIps(url); validateLocalIps(url);
const totalStreams = await auditLogStreamDAL.find({ projectId }); const totalStreams = await auditLogStreamDAL.find({ orgId: actorOrgId });
if (totalStreams.length >= plan.auditLogStreamLimit) { if (totalStreams.length >= plan.auditLogStreamLimit) {
throw new BadRequestError({ throw new BadRequestError({
message: message:
@@ -72,7 +59,7 @@ export const auditLogStreamServiceFactory = ({
} }
const encryptedToken = token ? infisicalSymmetricEncypt(token) : undefined; const encryptedToken = token ? infisicalSymmetricEncypt(token) : undefined;
const logStream = await auditLogStreamDAL.create({ const logStream = await auditLogStreamDAL.create({
projectId, orgId: actorOrgId,
url, url,
...(encryptedToken ...(encryptedToken
? { ? {
@@ -96,6 +83,8 @@ export const auditLogStreamServiceFactory = ({
actorOrgId, actorOrgId,
actorAuthMethod actorAuthMethod
}: TUpdateAuditLogStreamDTO) => { }: TUpdateAuditLogStreamDTO) => {
if (!actorOrgId) throw new BadRequestError({ message: "Missing org id from token" });
const plan = await licenseService.getPlan(actorOrgId); const plan = await licenseService.getPlan(actorOrgId);
if (!plan.auditLogStreams) if (!plan.auditLogStreams)
throw new BadRequestError({ throw new BadRequestError({
@@ -105,20 +94,13 @@ export const auditLogStreamServiceFactory = ({
const logStream = await auditLogStreamDAL.findById(id); const logStream = await auditLogStreamDAL.findById(id);
if (!logStream) throw new BadRequestError({ message: "Audit log stream not found" }); if (!logStream) throw new BadRequestError({ message: "Audit log stream not found" });
const { projectId } = logStream; const { orgId } = logStream;
const { permission } = await permissionService.getProjectPermission( const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId);
actor, ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Settings);
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Settings);
if (url) validateLocalIps(url); if (url) validateLocalIps(url);
const encryptedToken = token ? infisicalSymmetricEncypt(token) : undefined; const encryptedToken = token ? infisicalSymmetricEncypt(token) : undefined;
const updatedLogStream = await auditLogStreamDAL.updateById(id, { const updatedLogStream = await auditLogStreamDAL.updateById(id, {
projectId,
url, url,
...(encryptedToken ...(encryptedToken
? { ? {
@@ -134,18 +116,14 @@ export const auditLogStreamServiceFactory = ({
}; };
const deleteById = async ({ id, actor, actorId, actorOrgId, actorAuthMethod }: TDeleteAuditLogStreamDTO) => { const deleteById = async ({ id, actor, actorId, actorOrgId, actorAuthMethod }: TDeleteAuditLogStreamDTO) => {
if (!actorOrgId) throw new BadRequestError({ message: "Missing org id from token" });
const logStream = await auditLogStreamDAL.findById(id); const logStream = await auditLogStreamDAL.findById(id);
if (!logStream) throw new BadRequestError({ message: "Audit log stream not found" }); if (!logStream) throw new BadRequestError({ message: "Audit log stream not found" });
const { projectId } = logStream; const { orgId } = logStream;
const { permission } = await permissionService.getProjectPermission( const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId);
actor, ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Delete, OrgPermissionSubjects.Settings);
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Settings);
const deletedLogStream = await auditLogStreamDAL.deleteById(id); const deletedLogStream = await auditLogStreamDAL.deleteById(id);
return deletedLogStream; return deletedLogStream;
@@ -155,15 +133,10 @@ export const auditLogStreamServiceFactory = ({
const logStream = await auditLogStreamDAL.findById(id); const logStream = await auditLogStreamDAL.findById(id);
if (!logStream) throw new BadRequestError({ message: "Audit log stream not found" }); if (!logStream) throw new BadRequestError({ message: "Audit log stream not found" });
const { projectId } = logStream; const { orgId } = logStream;
const { permission } = await permissionService.getProjectPermission( const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId);
actor, ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Settings);
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Settings);
const token = const token =
logStream?.encryptedTokenCiphertext && logStream?.encryptedTokenIV && logStream?.encryptedTokenTag logStream?.encryptedTokenCiphertext && logStream?.encryptedTokenIV && logStream?.encryptedTokenTag
? infisicalSymmetricDecrypt({ ? infisicalSymmetricDecrypt({
@@ -177,21 +150,17 @@ export const auditLogStreamServiceFactory = ({
return { ...logStream, token }; return { ...logStream, token };
}; };
const list = async ({ projectSlug, actor, actorId, actorOrgId, actorAuthMethod }: TListAuditLogStreamDTO) => { const list = async ({ actor, actorId, actorOrgId, actorAuthMethod }: TListAuditLogStreamDTO) => {
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId); const { permission } = await permissionService.getOrgPermission(
if (!project) throw new BadRequestError({ message: "Project not found" });
const projectId = project.id;
const { permission } = await permissionService.getProjectPermission(
actor, actor,
actorId, actorId,
projectId, actorOrgId,
actorAuthMethod, actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Settings); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Settings);
const logStreams = await auditLogStreamDAL.find({ projectId }); const logStreams = await auditLogStreamDAL.find({ orgId: actorOrgId });
return logStreams; return logStreams;
}; };
@@ -1,25 +1,22 @@
import { TProjectPermission } from "@app/lib/types"; import { TOrgPermission } from "@app/lib/types";
export type TCreateAuditLogStreamDTO = Omit<TProjectPermission, "projectId"> & { export type TCreateAuditLogStreamDTO = Omit<TOrgPermission, "orgId"> & {
projectSlug: string;
url: string; url: string;
token?: string; token?: string;
}; };
export type TUpdateAuditLogStreamDTO = Omit<TProjectPermission, "projectId"> & { export type TUpdateAuditLogStreamDTO = Omit<TOrgPermission, "orgId"> & {
id: string; id: string;
url?: string; url?: string;
token?: string; token?: string;
}; };
export type TDeleteAuditLogStreamDTO = Omit<TProjectPermission, "projectId"> & { export type TDeleteAuditLogStreamDTO = Omit<TOrgPermission, "orgId"> & {
id: string; id: string;
}; };
export type TListAuditLogStreamDTO = Omit<TProjectPermission, "projectId"> & { export type TListAuditLogStreamDTO = Omit<TOrgPermission, "orgId">;
projectSlug: string;
};
export type TGetDetailsAuditLogStreamDTO = Omit<TProjectPermission, "projectId"> & { export type TGetDetailsAuditLogStreamDTO = Omit<TOrgPermission, "orgId"> & {
id: string; id: string;
}; };
@@ -71,7 +71,7 @@ export const auditLogQueueServiceFactory = ({
userAgentType userAgentType
}); });
const logStreams = projectId ? await auditLogStreamDAL.find({ projectId }) : []; const logStreams = orgId ? await auditLogStreamDAL.find({ orgId }) : [];
await Promise.allSettled( await Promise.allSettled(
logStreams.map( logStreams.map(
async ({ url, encryptedTokenTag, encryptedTokenIV, encryptedTokenKeyEncoding, encryptedTokenCiphertext }) => { async ({ url, encryptedTokenTag, encryptedTokenIV, encryptedTokenKeyEncoding, encryptedTokenCiphertext }) => {
-4
View File
@@ -617,7 +617,6 @@ export const INTEGRATION = {
export const AUDIT_LOG_STREAMS = { export const AUDIT_LOG_STREAMS = {
CREATE: { CREATE: {
projectSlug: "The slug of the project to create audit log stream.",
url: "The socket URL to push logs to.", url: "The socket URL to push logs to.",
token: "Authentication token for the external provider used for identification." token: "Authentication token for the external provider used for identification."
}, },
@@ -629,9 +628,6 @@ export const AUDIT_LOG_STREAMS = {
DELETE: { DELETE: {
id: "The ID of the audit log stream to delete." id: "The ID of the audit log stream to delete."
}, },
LIST: {
projectSlug: "The slug of the project to list audit log streams."
},
GET_BY_ID: { GET_BY_ID: {
id: "The ID of the audit log stream to get details." id: "The ID of the audit log stream to get details."
} }
+1 -1
View File
@@ -17,7 +17,7 @@ export type TOrgPermission = {
actorId: string; actorId: string;
orgId: string; orgId: string;
actorAuthMethod: ActorAuthMethod; actorAuthMethod: ActorAuthMethod;
actorOrgId: string | undefined; actorOrgId: string;
}; };
export type TProjectPermission = { export type TProjectPermission = {
-1
View File
@@ -251,7 +251,6 @@ export const registerRoutes = async (
}); });
const auditLogService = auditLogServiceFactory({ auditLogDAL, permissionService, auditLogQueue }); const auditLogService = auditLogServiceFactory({ auditLogDAL, permissionService, auditLogQueue });
const auditLogStreamService = auditLogStreamServiceFactory({ const auditLogStreamService = auditLogStreamServiceFactory({
projectDAL,
licenseService, licenseService,
permissionService, permissionService,
auditLogStreamDAL auditLogStreamDAL
@@ -21,8 +21,8 @@ export const useCreateAuditLogStream = () => {
); );
return data; return data;
}, },
onSuccess: (_, { projectSlug }) => { onSuccess: (_, { orgId }) => {
queryClient.invalidateQueries(auditLogStreamKeys.list(projectSlug)); queryClient.invalidateQueries(auditLogStreamKeys.list(orgId));
} }
}); });
}; };
@@ -38,8 +38,8 @@ export const useUpdateAuditLogStream = () => {
); );
return data; return data;
}, },
onSuccess: (_, { projectSlug }) => { onSuccess: (_, { orgId }) => {
queryClient.invalidateQueries(auditLogStreamKeys.list(projectSlug)); queryClient.invalidateQueries(auditLogStreamKeys.list(orgId));
} }
}); });
}; };
@@ -54,8 +54,8 @@ export const useDeleteAuditLogStream = () => {
); );
return data; return data;
}, },
onSuccess: (_, { projectSlug }) => { onSuccess: (_, { orgId }) => {
queryClient.invalidateQueries(auditLogStreamKeys.list(projectSlug)); queryClient.invalidateQueries(auditLogStreamKeys.list(orgId));
} }
}); });
}; };
@@ -5,28 +5,23 @@ import { apiRequest } from "@app/config/request";
import { TAuditLogStream } from "./types"; import { TAuditLogStream } from "./types";
export const auditLogStreamKeys = { export const auditLogStreamKeys = {
list: (projectSlug: string) => ["audit-log-stream", { projectSlug }], list: (orgId: string) => ["audit-log-stream", { orgId }],
getById: (id: string) => ["audit-log-stream-details", { id }] getById: (id: string) => ["audit-log-stream-details", { id }]
}; };
const fetchAuditLogStreams = async (projectSlug: string) => { const fetchAuditLogStreams = async () => {
const { data } = await apiRequest.get<{ auditLogStreams: TAuditLogStream[] }>( const { data } = await apiRequest.get<{ auditLogStreams: TAuditLogStream[] }>(
"/api/v1/audit-log-streams", "/api/v1/audit-log-streams"
{
params: {
projectSlug
}
}
); );
return data.auditLogStreams; return data.auditLogStreams;
}; };
export const useGetAuditLogStreams = (projectSlug: string) => export const useGetAuditLogStreams = (orgId: string) =>
useQuery({ useQuery({
queryKey: auditLogStreamKeys.list(projectSlug), queryKey: auditLogStreamKeys.list(orgId),
queryFn: () => fetchAuditLogStreams(projectSlug), queryFn: () => fetchAuditLogStreams(),
enabled: Boolean(projectSlug) enabled: Boolean(orgId)
}); });
const fetchAuditLogStreamDetails = async (id: string) => { const fetchAuditLogStreamDetails = async (id: string) => {
@@ -5,19 +5,19 @@ export type TAuditLogStream = {
}; };
export type TCreateAuditLogStreamDTO = { export type TCreateAuditLogStreamDTO = {
projectSlug: string;
url: string; url: string;
token?: string; token?: string;
orgId: string;
}; };
export type TUpdateAuditLogStreamDTO = { export type TUpdateAuditLogStreamDTO = {
id: string; id: string;
projectSlug: string;
url?: string; url?: string;
token?: string; token?: string;
orgId: string;
}; };
export type TDeleteAuditLogStreamDTO = { export type TDeleteAuditLogStreamDTO = {
id: string; id: string;
projectSlug: string; orgId: string;
}; };
@@ -3,7 +3,7 @@ import { z } from "zod";
import { createNotification } from "@app/components/notifications"; import { createNotification } from "@app/components/notifications";
import { Button, FormControl, Input, Spinner } from "@app/components/v2"; import { Button, FormControl, Input, Spinner } from "@app/components/v2";
import { useWorkspace } from "@app/context"; import { useOrganization } from "@app/context";
import { import {
useCreateAuditLogStream, useCreateAuditLogStream,
useGetAuditLogStreamDetails, useGetAuditLogStreamDetails,
@@ -23,8 +23,8 @@ type TForm = z.infer<typeof formSchema>;
export const AuditLogStreamForm = ({ id = "", onClose }: Props) => { export const AuditLogStreamForm = ({ id = "", onClose }: Props) => {
const isEdit = Boolean(id); const isEdit = Boolean(id);
const { currentWorkspace } = useWorkspace(); const { currentOrg } = useOrganization();
const projectSlug = currentWorkspace?.slug || ""; const orgId = currentOrg?.id || "";
const auditLogStream = useGetAuditLogStreamDetails(id); const auditLogStream = useGetAuditLogStreamDetails(id);
const createAuditLogStream = useCreateAuditLogStream(); const createAuditLogStream = useCreateAuditLogStream();
@@ -43,7 +43,7 @@ export const AuditLogStreamForm = ({ id = "", onClose }: Props) => {
try { try {
await updateAuditLogStream.mutateAsync({ await updateAuditLogStream.mutateAsync({
id, id,
projectSlug, orgId,
token, token,
url url
}); });
@@ -69,7 +69,7 @@ export const AuditLogStreamForm = ({ id = "", onClose }: Props) => {
} }
try { try {
await createAuditLogStream.mutateAsync({ await createAuditLogStream.mutateAsync({
projectSlug, orgId,
token, token,
url url
}); });
@@ -2,7 +2,7 @@ import { faPlug, faPlus } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { createNotification } from "@app/components/notifications"; import { createNotification } from "@app/components/notifications";
import { ProjectPermissionCan } from "@app/components/permissions"; import { OrgPermissionCan } from "@app/components/permissions";
import { import {
Button, Button,
DeleteActionModal, DeleteActionModal,
@@ -19,21 +19,21 @@ import {
UpgradePlanModal UpgradePlanModal
} from "@app/components/v2"; } from "@app/components/v2";
import { import {
ProjectPermissionActions, OrgPermissionActions,
ProjectPermissionSub, OrgPermissionSubjects,
useSubscription, useOrganization,
useWorkspace useSubscription
} from "@app/context"; } from "@app/context";
import { withProjectPermission } from "@app/hoc"; import { withPermission } from "@app/hoc";
import { usePopUp } from "@app/hooks"; import { usePopUp } from "@app/hooks";
import { useDeleteAuditLogStream, useGetAuditLogStreams } from "@app/hooks/api"; import { useDeleteAuditLogStream, useGetAuditLogStreams } from "@app/hooks/api";
import { AuditLogStreamForm } from "./AuditLogStreamForm"; import { AuditLogStreamForm } from "./AuditLogStreamForm";
export const AuditLogStreamsTab = withProjectPermission( export const AuditLogStreamsTab = withPermission(
() => { () => {
const { currentWorkspace } = useWorkspace(); const { currentOrg } = useOrganization();
const projectSlug = currentWorkspace?.slug || ""; const orgId = currentOrg?.id || "";
const { popUp, handlePopUpOpen, handlePopUpToggle, handlePopUpClose } = usePopUp([ const { popUp, handlePopUpOpen, handlePopUpToggle, handlePopUpClose } = usePopUp([
"auditLogStreamForm", "auditLogStreamForm",
"deleteAuditLogStream", "deleteAuditLogStream",
@@ -42,7 +42,7 @@ export const AuditLogStreamsTab = withProjectPermission(
const { subscription } = useSubscription(); const { subscription } = useSubscription();
const { data: auditLogStreams, isLoading: isAuditLogStreamsLoading } = const { data: auditLogStreams, isLoading: isAuditLogStreamsLoading } =
useGetAuditLogStreams(projectSlug); useGetAuditLogStreams(orgId);
// mutation // mutation
const { mutateAsync: deleteAuditLogStream } = useDeleteAuditLogStream(); const { mutateAsync: deleteAuditLogStream } = useDeleteAuditLogStream();
@@ -52,7 +52,7 @@ export const AuditLogStreamsTab = withProjectPermission(
const auditLogStreamId = popUp?.deleteAuditLogStream?.data as string; const auditLogStreamId = popUp?.deleteAuditLogStream?.data as string;
await deleteAuditLogStream({ await deleteAuditLogStream({
id: auditLogStreamId, id: auditLogStreamId,
projectSlug orgId
}); });
handlePopUpClose("deleteAuditLogStream"); handlePopUpClose("deleteAuditLogStream");
createNotification({ createNotification({
@@ -72,10 +72,7 @@ export const AuditLogStreamsTab = withProjectPermission(
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4"> <div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
<div className="flex justify-between"> <div className="flex justify-between">
<p className="text-xl font-semibold text-mineshaft-100">Audit Log Streams</p> <p className="text-xl font-semibold text-mineshaft-100">Audit Log Streams</p>
<ProjectPermissionCan <OrgPermissionCan I={OrgPermissionActions.Create} a={OrgPermissionSubjects.Settings}>
I={ProjectPermissionActions.Create}
a={ProjectPermissionSub.Settings}
>
{(isAllowed) => ( {(isAllowed) => (
<Button <Button
onClick={() => { onClick={() => {
@@ -91,7 +88,7 @@ export const AuditLogStreamsTab = withProjectPermission(
Create Create
</Button> </Button>
)} )}
</ProjectPermissionCan> </OrgPermissionCan>
</div> </div>
<p className="mb-8 text-gray-400"> <p className="mb-8 text-gray-400">
Manage audit log streams to send audit log to any logging providers with syslog support. Manage audit log streams to send audit log to any logging providers with syslog support.
@@ -124,9 +121,9 @@ export const AuditLogStreamsTab = withProjectPermission(
</Td> </Td>
<Td> <Td>
<div className="flex items-center justify-end space-x-2"> <div className="flex items-center justify-end space-x-2">
<ProjectPermissionCan <OrgPermissionCan
I={ProjectPermissionActions.Edit} I={OrgPermissionActions.Edit}
a={ProjectPermissionSub.Settings} a={OrgPermissionSubjects.Settings}
> >
{(isAllowed) => ( {(isAllowed) => (
<Button <Button
@@ -138,10 +135,10 @@ export const AuditLogStreamsTab = withProjectPermission(
Edit Edit
</Button> </Button>
)} )}
</ProjectPermissionCan> </OrgPermissionCan>
<ProjectPermissionCan <OrgPermissionCan
I={ProjectPermissionActions.Delete} I={OrgPermissionActions.Delete}
a={ProjectPermissionSub.Settings} a={OrgPermissionSubjects.Settings}
> >
{(isAllowed) => ( {(isAllowed) => (
<Button <Button
@@ -155,7 +152,7 @@ export const AuditLogStreamsTab = withProjectPermission(
Delete Delete
</Button> </Button>
)} )}
</ProjectPermissionCan> </OrgPermissionCan>
</div> </div>
</Td> </Td>
</Tr> </Tr>
@@ -196,5 +193,5 @@ export const AuditLogStreamsTab = withProjectPermission(
</div> </div>
); );
}, },
{ action: ProjectPermissionActions.Read, subject: ProjectPermissionSub.Settings } { action: OrgPermissionActions.Read, subject: OrgPermissionSubjects.Settings }
); );
@@ -1,12 +1,14 @@
import { Fragment } from "react"; import { Fragment } from "react";
import { Tab } from "@headlessui/react"; import { Tab } from "@headlessui/react";
import { AuditLogStreamsTab } from "../AuditLogStreamTab";
import { OrgAuthTab } from "../OrgAuthTab"; import { OrgAuthTab } from "../OrgAuthTab";
import { OrgGeneralTab } from "../OrgGeneralTab"; import { OrgGeneralTab } from "../OrgGeneralTab";
const tabs = [ const tabs = [
{ name: "General", key: "tab-org-general" }, { name: "General", key: "tab-org-general" },
{ name: "Security", key: "tab-org-security" } { name: "Security", key: "tab-org-security" },
{ name: "Audit Log Streams", key: "tag-audit-log-streams" }
]; ];
export const OrgTabGroup = () => { export const OrgTabGroup = () => {
return ( return (
@@ -17,9 +19,8 @@ export const OrgTabGroup = () => {
{({ selected }) => ( {({ selected }) => (
<button <button
type="button" type="button"
className={`w-30 mx-2 mr-4 py-2 text-sm font-medium outline-none ${ className={`w-30 mx-2 mr-4 py-2 text-sm font-medium outline-none ${selected ? "border-b border-white text-white" : "text-mineshaft-400"
selected ? "border-b border-white text-white" : "text-mineshaft-400" }`}
}`}
> >
{tab.name} {tab.name}
</button> </button>
@@ -34,6 +35,9 @@ export const OrgTabGroup = () => {
<Tab.Panel> <Tab.Panel>
<OrgAuthTab /> <OrgAuthTab />
</Tab.Panel> </Tab.Panel>
<Tab.Panel>
<AuditLogStreamsTab />
</Tab.Panel>
</Tab.Panels> </Tab.Panels>
</Tab.Group> </Tab.Group>
); );
@@ -4,12 +4,10 @@ import { Tab } from "@headlessui/react";
import { ProjectGeneralTab } from "./components/ProjectGeneralTab"; import { ProjectGeneralTab } from "./components/ProjectGeneralTab";
import { WebhooksTab } from "./components/WebhooksTab"; import { WebhooksTab } from "./components/WebhooksTab";
import { AuditLogStreamsTab } from "./components";
const tabs = [ const tabs = [
{ name: "General", key: "tab-project-general" }, { name: "General", key: "tab-project-general" },
{ name: "Webhooks", key: "tab-project-webhooks" }, { name: "Webhooks", key: "tab-project-webhooks" },
{ name: "Audit Log Streams", key: "tab-project-audit-log-stream" }
]; ];
export const ProjectSettingsPage = () => { export const ProjectSettingsPage = () => {
@@ -43,9 +41,6 @@ export const ProjectSettingsPage = () => {
<Tab.Panel> <Tab.Panel>
<WebhooksTab /> <WebhooksTab />
</Tab.Panel> </Tab.Panel>
<Tab.Panel>
<AuditLogStreamsTab />
</Tab.Panel>
</Tab.Panels> </Tab.Panels>
</Tab.Group> </Tab.Group>
</div> </div>
@@ -1,4 +1,3 @@
export { AuditLogStreamsTab } from "./AuditLogStreamTab";
export { AutoCapitalizationSection } from "./AutoCapitalizationSection"; export { AutoCapitalizationSection } from "./AutoCapitalizationSection";
export { DeleteProjectSection } from "./DeleteProjectSection"; export { DeleteProjectSection } from "./DeleteProjectSection";
export { E2EESection } from "./E2EESection"; export { E2EESection } from "./E2EESection";