mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-07 17:27:40 +00:00
Merge pull request #1186 from akhilmhdh/feat/audit-log-export
feat(audit-log): improvement in loading time
This commit is contained in:
+181
-62
@@ -306,12 +306,77 @@
|
|||||||
},
|
},
|
||||||
"/api/v1/workspace/{workspaceId}/audit-logs": {
|
"/api/v1/workspace/{workspaceId}/audit-logs": {
|
||||||
"get": {
|
"get": {
|
||||||
"description": "",
|
"summary": "Return audit logs",
|
||||||
|
"description": "Return audit logs",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"name": "workspaceId",
|
"name": "workspaceId",
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"required": true,
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"description": "ID of the workspace where to get folders from"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "offset",
|
||||||
|
"description": "Number of logs to skip before starting to return logs for pagination",
|
||||||
|
"required": false,
|
||||||
|
"in": "query",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "limit",
|
||||||
|
"description": "Maximum number of logs to return for pagination",
|
||||||
|
"required": false,
|
||||||
|
"in": "query",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "startDate",
|
||||||
|
"description": "Filter logs from this date in ISO-8601 format",
|
||||||
|
"required": false,
|
||||||
|
"in": "query",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "endDate",
|
||||||
|
"description": "Filter logs till this date in ISO-8601 format",
|
||||||
|
"required": false,
|
||||||
|
"in": "query",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "eventType",
|
||||||
|
"description": "Filter by type of event such as get-secrets, get-secret, create-secret, update-secret, delete-secret, etc.",
|
||||||
|
"required": false,
|
||||||
|
"in": "query",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "userAgentType",
|
||||||
|
"description": "Filter by type of user agent such as web, cli, k8-operator, or other",
|
||||||
|
"required": false,
|
||||||
|
"in": "query",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "actor",
|
||||||
|
"description": "Filter by actor such as user or service",
|
||||||
|
"required": false,
|
||||||
|
"in": "query",
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
@@ -319,9 +384,30 @@
|
|||||||
],
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "OK"
|
"description": "OK",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"auditLogs": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/AuditLog"
|
||||||
|
},
|
||||||
|
"description": "List of audit log"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"apiKeyAuth": []
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/api/v1/workspace/{workspaceId}/audit-logs/filters/actors": {
|
"/api/v1/workspace/{workspaceId}/audit-logs/filters/actors": {
|
||||||
@@ -1132,6 +1218,43 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/api/v1/admin/config": {
|
||||||
|
"get": {
|
||||||
|
"description": "",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"patch": {
|
||||||
|
"description": "",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/api/v1/admin/signup": {
|
||||||
|
"post": {
|
||||||
|
"description": "",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "user-agent",
|
||||||
|
"in": "header",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/api/v1/bot/{workspaceId}": {
|
"/api/v1/bot/{workspaceId}": {
|
||||||
"get": {
|
"get": {
|
||||||
"description": "",
|
"description": "",
|
||||||
@@ -4560,65 +4683,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"get": {
|
|
||||||
"summary": "Get all accessible environments of a workspace",
|
|
||||||
"description": "Fetch all environments that the user has access to in a specified workspace",
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"name": "workspaceId",
|
|
||||||
"in": "path",
|
|
||||||
"required": true,
|
|
||||||
"schema": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"description": "ID of the workspace"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "OK",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"accessibleEnvironments": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"name": {
|
|
||||||
"type": "string",
|
|
||||||
"example": "Development"
|
|
||||||
},
|
|
||||||
"slug": {
|
|
||||||
"type": "string",
|
|
||||||
"example": "development"
|
|
||||||
},
|
|
||||||
"isWriteDenied": {
|
|
||||||
"type": "boolean",
|
|
||||||
"example": false
|
|
||||||
},
|
|
||||||
"isReadDenied": {
|
|
||||||
"type": "boolean",
|
|
||||||
"example": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"description": "List of environments the user has access to in the specified workspace"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"security": [
|
|
||||||
{
|
|
||||||
"apiKeyAuth": []
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/api/v2/workspace/{workspaceId}/tags": {
|
"/api/v2/workspace/{workspaceId}/tags": {
|
||||||
@@ -6864,6 +6928,61 @@
|
|||||||
"example": "2023-01-13T14:16:12.210Z"
|
"example": "2023-01-13T14:16:12.210Z"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"AuditLog": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"actor": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"example": ""
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"organization": {
|
||||||
|
"type": "string",
|
||||||
|
"example": ""
|
||||||
|
},
|
||||||
|
"workspace": {
|
||||||
|
"type": "string",
|
||||||
|
"example": ""
|
||||||
|
},
|
||||||
|
"ipAddress": {
|
||||||
|
"type": "string",
|
||||||
|
"example": ""
|
||||||
|
},
|
||||||
|
"event": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"example": ""
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"userAgent": {
|
||||||
|
"type": "string",
|
||||||
|
"example": ""
|
||||||
|
},
|
||||||
|
"userAgentType": {
|
||||||
|
"type": "string",
|
||||||
|
"example": ""
|
||||||
|
},
|
||||||
|
"expiresAt": {
|
||||||
|
"type": "string",
|
||||||
|
"example": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes": {
|
"securitySchemes": {
|
||||||
|
|||||||
@@ -578,6 +578,82 @@ export const rollbackWorkspaceSecretSnapshot = async (req: Request, res: Respons
|
|||||||
* @param res
|
* @param res
|
||||||
*/
|
*/
|
||||||
export const getWorkspaceAuditLogs = async (req: Request, res: Response) => {
|
export const getWorkspaceAuditLogs = async (req: Request, res: Response) => {
|
||||||
|
/*
|
||||||
|
#swagger.summary = 'Return audit logs'
|
||||||
|
#swagger.description = 'Return audit logs'
|
||||||
|
|
||||||
|
#swagger.security = [{
|
||||||
|
"apiKeyAuth": []
|
||||||
|
}]
|
||||||
|
|
||||||
|
#swagger.parameters['workspaceId'] = {
|
||||||
|
"description": "ID of the workspace where to get folders from",
|
||||||
|
"required": true,
|
||||||
|
"type": "string",
|
||||||
|
"in": "path"
|
||||||
|
}
|
||||||
|
|
||||||
|
#swagger.parameters['offset'] = {
|
||||||
|
"description": "Number of logs to skip before starting to return logs for pagination",
|
||||||
|
"required": false,
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
|
||||||
|
#swagger.parameters['limit'] = {
|
||||||
|
"description": "Maximum number of logs to return for pagination",
|
||||||
|
"required": false,
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
|
||||||
|
#swagger.parameters['startDate'] = {
|
||||||
|
"description": "Filter logs from this date in ISO-8601 format",
|
||||||
|
"required": false,
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
|
||||||
|
#swagger.parameters['endDate'] = {
|
||||||
|
"description": "Filter logs till this date in ISO-8601 format",
|
||||||
|
"required": false,
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
|
||||||
|
#swagger.parameters['eventType'] = {
|
||||||
|
"description": "Filter by type of event such as get-secrets, get-secret, create-secret, update-secret, delete-secret, etc.",
|
||||||
|
"required": false,
|
||||||
|
"type": "string",
|
||||||
|
}
|
||||||
|
|
||||||
|
#swagger.parameters['userAgentType'] = {
|
||||||
|
"description": "Filter by type of user agent such as web, cli, k8-operator, or other",
|
||||||
|
"required": false,
|
||||||
|
"type": "string",
|
||||||
|
}
|
||||||
|
|
||||||
|
#swagger.parameters['actor'] = {
|
||||||
|
"description": "Filter by actor such as user or service",
|
||||||
|
"required": false,
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
|
||||||
|
#swagger.responses[200] = {
|
||||||
|
content: {
|
||||||
|
"application/json": {
|
||||||
|
schema: {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"auditLogs": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
$ref: "#/components/schemas/AuditLog",
|
||||||
|
},
|
||||||
|
"description": "List of audit log"
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
const {
|
const {
|
||||||
query: { limit, offset, endDate, eventType, startDate, userAgentType, actor },
|
query: { limit, offset, endDate, eventType, startDate, userAgentType, actor },
|
||||||
params: { workspaceId }
|
params: { workspaceId }
|
||||||
@@ -626,14 +702,9 @@ export const getWorkspaceAuditLogs = async (req: Request, res: Response) => {
|
|||||||
}
|
}
|
||||||
: {})
|
: {})
|
||||||
};
|
};
|
||||||
|
|
||||||
const auditLogs = await AuditLog.find(query).sort({ createdAt: -1 }).skip(offset).limit(limit);
|
const auditLogs = await AuditLog.find(query).sort({ createdAt: -1 }).skip(offset).limit(limit);
|
||||||
|
|
||||||
const totalCount = await AuditLog.countDocuments(query);
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
auditLogs,
|
auditLogs
|
||||||
totalCount
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -698,11 +769,7 @@ export const getWorkspaceAuditLogActorFilterOpts = async (req: Request, res: Res
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const actors = [
|
const actors = [...userActors, ...serviceActors, ...serviceV3Actors];
|
||||||
...userActors,
|
|
||||||
...serviceActors,
|
|
||||||
...serviceV3Actors
|
|
||||||
];
|
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
actors
|
actors
|
||||||
|
|||||||
@@ -1,76 +1,70 @@
|
|||||||
import { Schema, Types, model } from "mongoose";
|
import { Schema, Types, model } from "mongoose";
|
||||||
import {
|
import { ActorType, EventType, UserAgentType } from "./enums";
|
||||||
ActorType,
|
import { Actor, Event } from "./types";
|
||||||
EventType,
|
|
||||||
UserAgentType
|
|
||||||
} from "./enums";
|
|
||||||
import {
|
|
||||||
Actor,
|
|
||||||
Event
|
|
||||||
} from "./types";
|
|
||||||
|
|
||||||
export interface IAuditLog {
|
export interface IAuditLog {
|
||||||
actor: Actor;
|
actor: Actor;
|
||||||
organization: Types.ObjectId;
|
organization: Types.ObjectId;
|
||||||
workspace: Types.ObjectId;
|
workspace: Types.ObjectId;
|
||||||
ipAddress: string;
|
ipAddress: string;
|
||||||
event: Event;
|
event: Event;
|
||||||
userAgent: string;
|
userAgent: string;
|
||||||
userAgentType: UserAgentType;
|
userAgentType: UserAgentType;
|
||||||
expiresAt: Date;
|
expiresAt: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auditLogSchema = new Schema<IAuditLog>(
|
const auditLogSchema = new Schema<IAuditLog>(
|
||||||
{
|
{
|
||||||
actor: {
|
actor: {
|
||||||
type: {
|
type: {
|
||||||
type: String,
|
type: String,
|
||||||
enum: ActorType,
|
enum: ActorType,
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
metadata: {
|
metadata: {
|
||||||
type: Schema.Types.Mixed
|
type: Schema.Types.Mixed
|
||||||
}
|
}
|
||||||
},
|
|
||||||
organization: {
|
|
||||||
type: Schema.Types.ObjectId,
|
|
||||||
required: false
|
|
||||||
},
|
|
||||||
workspace: {
|
|
||||||
type: Schema.Types.ObjectId,
|
|
||||||
required: false
|
|
||||||
},
|
|
||||||
ipAddress: {
|
|
||||||
type: String,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
event: {
|
|
||||||
type: {
|
|
||||||
type: String,
|
|
||||||
enum: EventType,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
metadata: {
|
|
||||||
type: Schema.Types.Mixed
|
|
||||||
}
|
|
||||||
},
|
|
||||||
userAgent: {
|
|
||||||
type: String,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
userAgentType: {
|
|
||||||
type: String,
|
|
||||||
enum: UserAgentType,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
expiresAt: {
|
|
||||||
type: Date,
|
|
||||||
expires: 0
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
organization: {
|
||||||
timestamps: true
|
type: Schema.Types.ObjectId,
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
workspace: {
|
||||||
|
type: Schema.Types.ObjectId,
|
||||||
|
required: false,
|
||||||
|
index: true
|
||||||
|
},
|
||||||
|
ipAddress: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
event: {
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
enum: EventType,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
metadata: {
|
||||||
|
type: Schema.Types.Mixed
|
||||||
|
}
|
||||||
|
},
|
||||||
|
userAgent: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
userAgentType: {
|
||||||
|
type: String,
|
||||||
|
enum: UserAgentType,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
expiresAt: {
|
||||||
|
type: Date,
|
||||||
|
expires: 0
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
timestamps: true
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
export const AuditLog = model<IAuditLog>("AuditLog", auditLogSchema);
|
export const AuditLog = model<IAuditLog>("AuditLog", auditLogSchema);
|
||||||
|
|||||||
@@ -5,12 +5,12 @@ export let logger: Logger;
|
|||||||
|
|
||||||
// https://github.com/pinojs/pino/blob/master/lib/levels.js#L13-L20
|
// https://github.com/pinojs/pino/blob/master/lib/levels.js#L13-L20
|
||||||
const logLevelToSeverityLookup: Record<string, string> = {
|
const logLevelToSeverityLookup: Record<string, string> = {
|
||||||
'10': 'TRACE',
|
"10": "TRACE",
|
||||||
'20': 'DEBUG',
|
"20": "DEBUG",
|
||||||
'30': 'INFO',
|
"30": "INFO",
|
||||||
'40': 'WARNING',
|
"40": "WARNING",
|
||||||
'50': 'ERROR',
|
"50": "ERROR",
|
||||||
'60': 'CRITICAL'
|
"60": "CRITICAL"
|
||||||
}
|
}
|
||||||
|
|
||||||
export const initLogger = async () => {
|
export const initLogger = async () => {
|
||||||
@@ -51,7 +51,7 @@ export const initLogger = async () => {
|
|||||||
logger = pino(
|
logger = pino(
|
||||||
{
|
{
|
||||||
mixin(_context, level) {
|
mixin(_context, level) {
|
||||||
return { 'severity': logLevelToSeverityLookup[level] || logLevelToSeverityLookup['30'] }
|
return { "severity": logLevelToSeverityLookup[level] || logLevelToSeverityLookup["30"] }
|
||||||
},
|
},
|
||||||
level: process.env.PINO_LOG_LEVEL || "info",
|
level: process.env.PINO_LOG_LEVEL || "info",
|
||||||
formatters: {
|
formatters: {
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ export const validateClientForWorkspace = async ({
|
|||||||
environment,
|
environment,
|
||||||
requiredPermissions
|
requiredPermissions
|
||||||
});
|
});
|
||||||
return { membership, workspace};
|
return { membership, workspace };
|
||||||
case ActorType.SERVICE_V3:
|
case ActorType.SERVICE_V3:
|
||||||
throw UnauthorizedRequestError({
|
throw UnauthorizedRequestError({
|
||||||
message: "Failed service token authorization for organization"
|
message: "Failed service token authorization for organization"
|
||||||
@@ -121,8 +121,8 @@ export const GetWorkspaceAuditLogsV1 = z.object({
|
|||||||
userAgentType: z.nativeEnum(UserAgentType).nullable().optional(),
|
userAgentType: z.nativeEnum(UserAgentType).nullable().optional(),
|
||||||
startDate: z.string().datetime().nullable().optional(),
|
startDate: z.string().datetime().nullable().optional(),
|
||||||
endDate: z.string().datetime().nullable().optional(),
|
endDate: z.string().datetime().nullable().optional(),
|
||||||
offset: z.coerce.number(),
|
offset: z.coerce.number().default(0),
|
||||||
limit: z.coerce.number(),
|
limit: z.coerce.number().default(20),
|
||||||
actor: z.string().nullish().optional()
|
actor: z.string().nullish().optional()
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|||||||
+56
-40
@@ -12,32 +12,32 @@ const generateOpenAPISpec = async () => {
|
|||||||
const doc = {
|
const doc = {
|
||||||
info: {
|
info: {
|
||||||
title: "Infisical API",
|
title: "Infisical API",
|
||||||
description: "List of all available APIs that can be consumed",
|
description: "List of all available APIs that can be consumed"
|
||||||
},
|
},
|
||||||
host: ["https://infisical.com"],
|
host: ["https://infisical.com"],
|
||||||
servers: [
|
servers: [
|
||||||
{
|
{
|
||||||
url: "https://app.infisical.com",
|
url: "https://app.infisical.com",
|
||||||
description: "Production server",
|
description: "Production server"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
url: "http://localhost:8080",
|
url: "http://localhost:8080",
|
||||||
description: "Local server",
|
description: "Local server"
|
||||||
},
|
}
|
||||||
],
|
],
|
||||||
securityDefinitions: {
|
securityDefinitions: {
|
||||||
bearerAuth: {
|
bearerAuth: {
|
||||||
type: "http",
|
type: "http",
|
||||||
scheme: "bearer",
|
scheme: "bearer",
|
||||||
bearerFormat: "JWT",
|
bearerFormat: "JWT",
|
||||||
description: "A service token in Infisical",
|
description: "A service token in Infisical"
|
||||||
},
|
},
|
||||||
apiKeyAuth: {
|
apiKeyAuth: {
|
||||||
type: "apiKey",
|
type: "apiKey",
|
||||||
in: "header",
|
in: "header",
|
||||||
name: "X-API-Key",
|
name: "X-API-Key",
|
||||||
description: "An API Key in Infisical",
|
description: "An API Key in Infisical"
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
definitions: {
|
definitions: {
|
||||||
CurrentUser: {
|
CurrentUser: {
|
||||||
@@ -50,7 +50,7 @@ const generateOpenAPISpec = async () => {
|
|||||||
iv: "iv_of_enc_nacl_private_key",
|
iv: "iv_of_enc_nacl_private_key",
|
||||||
tag: "tag_of_enc_nacl_private_key",
|
tag: "tag_of_enc_nacl_private_key",
|
||||||
updatedAt: "2023-01-13T14:16:12.210Z",
|
updatedAt: "2023-01-13T14:16:12.210Z",
|
||||||
createdAt: "2023-01-13T14:16:12.210Z",
|
createdAt: "2023-01-13T14:16:12.210Z"
|
||||||
},
|
},
|
||||||
Membership: {
|
Membership: {
|
||||||
user: {
|
user: {
|
||||||
@@ -60,10 +60,10 @@ const generateOpenAPISpec = async () => {
|
|||||||
lastName: "Doe",
|
lastName: "Doe",
|
||||||
publicKey: "johns_nacl_public_key",
|
publicKey: "johns_nacl_public_key",
|
||||||
updatedAt: "2023-01-13T14:16:12.210Z",
|
updatedAt: "2023-01-13T14:16:12.210Z",
|
||||||
createdAt: "2023-01-13T14:16:12.210Z",
|
createdAt: "2023-01-13T14:16:12.210Z"
|
||||||
},
|
},
|
||||||
workspace: "",
|
workspace: "",
|
||||||
role: "admin",
|
role: "admin"
|
||||||
},
|
},
|
||||||
MembershipOrg: {
|
MembershipOrg: {
|
||||||
user: {
|
user: {
|
||||||
@@ -73,33 +73,35 @@ const generateOpenAPISpec = async () => {
|
|||||||
lastName: "Doe",
|
lastName: "Doe",
|
||||||
publicKey: "johns_nacl_public_key",
|
publicKey: "johns_nacl_public_key",
|
||||||
updatedAt: "2023-01-13T14:16:12.210Z",
|
updatedAt: "2023-01-13T14:16:12.210Z",
|
||||||
createdAt: "2023-01-13T14:16:12.210Z",
|
createdAt: "2023-01-13T14:16:12.210Z"
|
||||||
},
|
},
|
||||||
organization: "",
|
organization: "",
|
||||||
role: "owner",
|
role: "owner",
|
||||||
status: "accepted",
|
status: "accepted"
|
||||||
},
|
},
|
||||||
Organization: {
|
Organization: {
|
||||||
_id: "",
|
_id: "",
|
||||||
name: "Acme Corp.",
|
name: "Acme Corp.",
|
||||||
customerId: "",
|
customerId: ""
|
||||||
},
|
},
|
||||||
Project: {
|
Project: {
|
||||||
name: "My Project",
|
name: "My Project",
|
||||||
organization: "",
|
organization: "",
|
||||||
environments: [{
|
environments: [
|
||||||
name: "development",
|
{
|
||||||
slug: "dev",
|
name: "development",
|
||||||
}],
|
slug: "dev"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
ProjectKey: {
|
ProjectKey: {
|
||||||
encryptedkey: "",
|
encryptedkey: "",
|
||||||
nonce: "",
|
nonce: "",
|
||||||
sender: {
|
sender: {
|
||||||
publicKey: "senders_nacl_public_key",
|
publicKey: "senders_nacl_public_key"
|
||||||
},
|
},
|
||||||
receiver: "",
|
receiver: "",
|
||||||
workspace: "",
|
workspace: ""
|
||||||
},
|
},
|
||||||
CreateSecret: {
|
CreateSecret: {
|
||||||
type: "shared",
|
type: "shared",
|
||||||
@@ -111,7 +113,7 @@ const generateOpenAPISpec = async () => {
|
|||||||
secretValueTag: "",
|
secretValueTag: "",
|
||||||
secretCommentCiphertext: "",
|
secretCommentCiphertext: "",
|
||||||
secretCommentIV: "",
|
secretCommentIV: "",
|
||||||
secretCommentTag: "",
|
secretCommentTag: ""
|
||||||
},
|
},
|
||||||
UpdateSecret: {
|
UpdateSecret: {
|
||||||
id: "",
|
id: "",
|
||||||
@@ -123,12 +125,12 @@ const generateOpenAPISpec = async () => {
|
|||||||
secretValueTag: "",
|
secretValueTag: "",
|
||||||
secretCommentCiphertext: "",
|
secretCommentCiphertext: "",
|
||||||
secretCommentIV: "",
|
secretCommentIV: "",
|
||||||
secretCommentTag: "",
|
secretCommentTag: ""
|
||||||
},
|
},
|
||||||
Secret: {
|
Secret: {
|
||||||
_id: "",
|
_id: "",
|
||||||
version: 1,
|
version: 1,
|
||||||
workspace : "",
|
workspace: "",
|
||||||
type: "shared",
|
type: "shared",
|
||||||
user: null,
|
user: null,
|
||||||
secretKeyCiphertext: "",
|
secretKeyCiphertext: "",
|
||||||
@@ -141,7 +143,7 @@ const generateOpenAPISpec = async () => {
|
|||||||
secretCommentIV: "",
|
secretCommentIV: "",
|
||||||
secretCommentTag: "",
|
secretCommentTag: "",
|
||||||
updatedAt: "2023-01-13T14:16:12.210Z",
|
updatedAt: "2023-01-13T14:16:12.210Z",
|
||||||
createdAt: "2023-01-13T14:16:12.210Z",
|
createdAt: "2023-01-13T14:16:12.210Z"
|
||||||
},
|
},
|
||||||
RawSecret: {
|
RawSecret: {
|
||||||
_id: "abc123",
|
_id: "abc123",
|
||||||
@@ -167,12 +169,10 @@ const generateOpenAPISpec = async () => {
|
|||||||
_id: "",
|
_id: "",
|
||||||
email: "[email protected]",
|
email: "[email protected]",
|
||||||
firstName: "John",
|
firstName: "John",
|
||||||
lastName: "Doe",
|
lastName: "Doe"
|
||||||
},
|
},
|
||||||
workspace: "",
|
workspace: "",
|
||||||
actionNames: [
|
actionNames: ["addSecrets"],
|
||||||
"addSecrets",
|
|
||||||
],
|
|
||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
name: "addSecrets",
|
name: "addSecrets",
|
||||||
@@ -181,24 +181,24 @@ const generateOpenAPISpec = async () => {
|
|||||||
payload: [
|
payload: [
|
||||||
{
|
{
|
||||||
oldSecretVersion: "",
|
oldSecretVersion: "",
|
||||||
newSecretVersion: "",
|
newSecretVersion: ""
|
||||||
},
|
}
|
||||||
],
|
]
|
||||||
},
|
}
|
||||||
],
|
],
|
||||||
channel: "cli",
|
channel: "cli",
|
||||||
ipAddress: "192.168.0.1",
|
ipAddress: "192.168.0.1",
|
||||||
updatedAt: "2023-01-13T14:16:12.210Z",
|
updatedAt: "2023-01-13T14:16:12.210Z",
|
||||||
createdAt: "2023-01-13T14:16:12.210Z",
|
createdAt: "2023-01-13T14:16:12.210Z"
|
||||||
},
|
},
|
||||||
SecretSnapshot: {
|
SecretSnapshot: {
|
||||||
workspace: "",
|
workspace: "",
|
||||||
version: 1,
|
version: 1,
|
||||||
secretVersions: [
|
secretVersions: [
|
||||||
{
|
{
|
||||||
_id: "",
|
_id: ""
|
||||||
},
|
}
|
||||||
],
|
]
|
||||||
},
|
},
|
||||||
SecretVersion: {
|
SecretVersion: {
|
||||||
_id: "",
|
_id: "",
|
||||||
@@ -214,7 +214,7 @@ const generateOpenAPISpec = async () => {
|
|||||||
secretKeyTag: "",
|
secretKeyTag: "",
|
||||||
secretValueCiphertext: "",
|
secretValueCiphertext: "",
|
||||||
secretValueIV: "",
|
secretValueIV: "",
|
||||||
secretValueTag: "",
|
secretValueTag: ""
|
||||||
},
|
},
|
||||||
ServiceTokenData: {
|
ServiceTokenData: {
|
||||||
_id: "",
|
_id: "",
|
||||||
@@ -224,16 +224,32 @@ const generateOpenAPISpec = async () => {
|
|||||||
user: {
|
user: {
|
||||||
_id: "",
|
_id: "",
|
||||||
firstName: "",
|
firstName: "",
|
||||||
lastName: "",
|
lastName: ""
|
||||||
},
|
},
|
||||||
expiresAt: "2023-01-13T14:16:12.210Z",
|
expiresAt: "2023-01-13T14:16:12.210Z",
|
||||||
encryptedKey: "",
|
encryptedKey: "",
|
||||||
iv: "",
|
iv: "",
|
||||||
tag: "",
|
tag: "",
|
||||||
updatedAt: "2023-01-13T14:16:12.210Z",
|
updatedAt: "2023-01-13T14:16:12.210Z",
|
||||||
createdAt: "2023-01-13T14:16:12.210Z",
|
createdAt: "2023-01-13T14:16:12.210Z"
|
||||||
},
|
},
|
||||||
},
|
AuditLog: {
|
||||||
|
actor: {
|
||||||
|
type: "",
|
||||||
|
metadata: {}
|
||||||
|
},
|
||||||
|
organization: "",
|
||||||
|
workspace: "",
|
||||||
|
ipAddress: "",
|
||||||
|
event: {
|
||||||
|
type: "",
|
||||||
|
metadata: {}
|
||||||
|
},
|
||||||
|
userAgent: "",
|
||||||
|
userAgentType: "",
|
||||||
|
expiresAt: ""
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const outputJSONFile = "../spec.json";
|
const outputJSONFile = "../spec.json";
|
||||||
@@ -243,6 +259,6 @@ const generateOpenAPISpec = async () => {
|
|||||||
const spec = await swaggerAutogen(outputJSONFile, endpointsFiles, doc);
|
const spec = await swaggerAutogen(outputJSONFile, endpointsFiles, doc);
|
||||||
|
|
||||||
await fs.writeFile(outputYAMLFile, yaml.dump(spec.data));
|
await fs.writeFile(outputYAMLFile, yaml.dump(spec.data));
|
||||||
}
|
};
|
||||||
|
|
||||||
generateOpenAPISpec();
|
generateOpenAPISpec();
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
title: "Export"
|
||||||
|
openapi: "GET /api/v1/workspace/{workspaceId}/audit-logs"
|
||||||
|
---
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
---
|
---
|
||||||
title: "Create"
|
title: "Create"
|
||||||
openapi: "POST /api/v2/workspace/{workspaceId}/environments"
|
openapi: "POST /api/v1/workspace/{workspaceId}/environments"
|
||||||
---
|
---
|
||||||
@@ -380,6 +380,10 @@
|
|||||||
{
|
{
|
||||||
"group": "Service Tokens",
|
"group": "Service Tokens",
|
||||||
"pages": ["api-reference/endpoints/service-tokens/get"]
|
"pages": ["api-reference/endpoints/service-tokens/get"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "Audit Logs",
|
||||||
|
"pages": ["api-reference/endpoints/audit-logs/export-audit-log"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
+120
-43
@@ -192,16 +192,74 @@ paths:
|
|||||||
description: Version of secret snapshot to roll back to
|
description: Version of secret snapshot to roll back to
|
||||||
/api/v1/workspace/{workspaceId}/audit-logs:
|
/api/v1/workspace/{workspaceId}/audit-logs:
|
||||||
get:
|
get:
|
||||||
description: ''
|
summary: Return audit logs
|
||||||
|
description: Return audit logs
|
||||||
parameters:
|
parameters:
|
||||||
- name: workspaceId
|
- name: workspaceId
|
||||||
in: path
|
in: path
|
||||||
required: true
|
required: true
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
|
description: ID of the workspace where to get folders from
|
||||||
|
- name: offset
|
||||||
|
description: Number of logs to skip before starting to return logs for pagination
|
||||||
|
required: false
|
||||||
|
in: query
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
- name: limit
|
||||||
|
description: Maximum number of logs to return for pagination
|
||||||
|
required: false
|
||||||
|
in: query
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
- name: startDate
|
||||||
|
description: Filter logs from this date in ISO-8601 format
|
||||||
|
required: false
|
||||||
|
in: query
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
- name: endDate
|
||||||
|
description: Filter logs till this date in ISO-8601 format
|
||||||
|
required: false
|
||||||
|
in: query
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
- name: eventType
|
||||||
|
description: >-
|
||||||
|
Filter by type of event such as get-secrets, get-secret,
|
||||||
|
create-secret, update-secret, delete-secret, etc.
|
||||||
|
required: false
|
||||||
|
in: query
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
- name: userAgentType
|
||||||
|
description: Filter by type of user agent such as web, cli, k8-operator, or other
|
||||||
|
required: false
|
||||||
|
in: query
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
- name: actor
|
||||||
|
description: Filter by actor such as user or service
|
||||||
|
required: false
|
||||||
|
in: query
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
description: OK
|
description: OK
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
auditLogs:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/AuditLog'
|
||||||
|
description: List of audit log
|
||||||
|
security:
|
||||||
|
- apiKeyAuth: []
|
||||||
/api/v1/workspace/{workspaceId}/audit-logs/filters/actors:
|
/api/v1/workspace/{workspaceId}/audit-logs/filters/actors:
|
||||||
get:
|
get:
|
||||||
description: ''
|
description: ''
|
||||||
@@ -691,6 +749,28 @@ paths:
|
|||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
description: OK
|
description: OK
|
||||||
|
/api/v1/admin/config:
|
||||||
|
get:
|
||||||
|
description: ''
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: OK
|
||||||
|
patch:
|
||||||
|
description: ''
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: OK
|
||||||
|
/api/v1/admin/signup:
|
||||||
|
post:
|
||||||
|
description: ''
|
||||||
|
parameters:
|
||||||
|
- name: user-agent
|
||||||
|
in: header
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: OK
|
||||||
/api/v1/bot/{workspaceId}:
|
/api/v1/bot/{workspaceId}:
|
||||||
get:
|
get:
|
||||||
description: ''
|
description: ''
|
||||||
@@ -2834,48 +2914,6 @@ paths:
|
|||||||
example: dev
|
example: dev
|
||||||
required:
|
required:
|
||||||
- environmentSlug
|
- environmentSlug
|
||||||
get:
|
|
||||||
summary: Get all accessible environments of a workspace
|
|
||||||
description: >-
|
|
||||||
Fetch all environments that the user has access to in a specified
|
|
||||||
workspace
|
|
||||||
parameters:
|
|
||||||
- name: workspaceId
|
|
||||||
in: path
|
|
||||||
required: true
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
description: ID of the workspace
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: OK
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
accessibleEnvironments:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
name:
|
|
||||||
type: string
|
|
||||||
example: Development
|
|
||||||
slug:
|
|
||||||
type: string
|
|
||||||
example: development
|
|
||||||
isWriteDenied:
|
|
||||||
type: boolean
|
|
||||||
example: false
|
|
||||||
isReadDenied:
|
|
||||||
type: boolean
|
|
||||||
example: false
|
|
||||||
description: >-
|
|
||||||
List of environments the user has access to in the specified
|
|
||||||
workspace
|
|
||||||
security:
|
|
||||||
- apiKeyAuth: []
|
|
||||||
/api/v2/workspace/{workspaceId}/tags:
|
/api/v2/workspace/{workspaceId}/tags:
|
||||||
get:
|
get:
|
||||||
description: ''
|
description: ''
|
||||||
@@ -4342,6 +4380,45 @@ components:
|
|||||||
createdAt:
|
createdAt:
|
||||||
type: string
|
type: string
|
||||||
example: '2023-01-13T14:16:12.210Z'
|
example: '2023-01-13T14:16:12.210Z'
|
||||||
|
AuditLog:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
actor:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
type:
|
||||||
|
type: string
|
||||||
|
example: ''
|
||||||
|
metadata:
|
||||||
|
type: object
|
||||||
|
properties: {}
|
||||||
|
organization:
|
||||||
|
type: string
|
||||||
|
example: ''
|
||||||
|
workspace:
|
||||||
|
type: string
|
||||||
|
example: ''
|
||||||
|
ipAddress:
|
||||||
|
type: string
|
||||||
|
example: ''
|
||||||
|
event:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
type:
|
||||||
|
type: string
|
||||||
|
example: ''
|
||||||
|
metadata:
|
||||||
|
type: object
|
||||||
|
properties: {}
|
||||||
|
userAgent:
|
||||||
|
type: string
|
||||||
|
example: ''
|
||||||
|
userAgentType:
|
||||||
|
type: string
|
||||||
|
example: ''
|
||||||
|
expiresAt:
|
||||||
|
type: string
|
||||||
|
example: ''
|
||||||
securitySchemes:
|
securitySchemes:
|
||||||
bearerAuth:
|
bearerAuth:
|
||||||
type: http
|
type: http
|
||||||
|
|||||||
@@ -1,59 +1,46 @@
|
|||||||
import { useQuery } from "@tanstack/react-query";
|
import { useInfiniteQuery, useQuery } from "@tanstack/react-query";
|
||||||
|
|
||||||
import { apiRequest } from "@app/config/request";
|
import { apiRequest } from "@app/config/request";
|
||||||
|
|
||||||
import {
|
import { Actor, AuditLog, AuditLogFilters } from "./types";
|
||||||
Actor,
|
|
||||||
AuditLog,
|
|
||||||
AuditLogFilters
|
|
||||||
} from "./types";
|
|
||||||
|
|
||||||
export const workspaceKeys = {
|
export const workspaceKeys = {
|
||||||
getAuditLogs: (workspaceId: string, filters: AuditLogFilters) => [{ workspaceId, filters }, "audit-logs"] as const,
|
getAuditLogs: (workspaceId: string, filters: AuditLogFilters) =>
|
||||||
getAuditLogActorFilterOpts: (workspaceId: string) => [{ workspaceId }, "audit-log-actor-filters"] as const
|
[{ workspaceId, filters }, "audit-logs"] as const,
|
||||||
}
|
getAuditLogActorFilterOpts: (workspaceId: string) =>
|
||||||
|
[{ workspaceId }, "audit-log-actor-filters"] as const
|
||||||
|
};
|
||||||
|
|
||||||
export const useGetAuditLogs = (workspaceId: string, filters: AuditLogFilters) => {
|
export const useGetAuditLogs = (workspaceId: string, filters: AuditLogFilters) => {
|
||||||
return useQuery({
|
return useInfiniteQuery({
|
||||||
queryKey: workspaceKeys.getAuditLogs(workspaceId, filters),
|
queryKey: workspaceKeys.getAuditLogs(workspaceId, filters),
|
||||||
queryFn: async () => {
|
queryFn: async ({ pageParam }) => {
|
||||||
|
const { data } = await apiRequest.get<{ auditLogs: AuditLog[] }>(
|
||||||
const params = new URLSearchParams();
|
`/api/v1/workspace/${workspaceId}/audit-logs`,
|
||||||
if (filters.eventType) {
|
{
|
||||||
params.append("eventType", filters.eventType);
|
params: {
|
||||||
}
|
...filters,
|
||||||
|
offset: pageParam,
|
||||||
if (filters.userAgentType) {
|
startDate: filters?.startDate?.toISOString(),
|
||||||
params.append("userAgentType", filters.userAgentType);
|
endDate: filters?.endDate?.toISOString()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filters.actor) {
|
|
||||||
params.append("actor", filters.actor);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filters.startDate) {
|
|
||||||
params.append("startDate", filters.startDate.toISOString());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filters.endDate) {
|
|
||||||
params.append("endDate", filters.endDate.toISOString());
|
|
||||||
}
|
|
||||||
|
|
||||||
params.append("offset", String(filters.offset));
|
|
||||||
params.append("limit", String(filters.limit));
|
|
||||||
|
|
||||||
const { data } = await apiRequest.get<{ auditLogs: AuditLog[], totalCount: number }>(`/api/v1/workspace/${workspaceId}/audit-logs`, { params });
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
});
|
);
|
||||||
}
|
return data.auditLogs;
|
||||||
|
},
|
||||||
|
getNextPageParam: (lastPage, pages) =>
|
||||||
|
lastPage.length !== 0 ? pages.length * filters.limit : undefined
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
export const useGetAuditLogActorFilterOpts = (workspaceId: string) => {
|
export const useGetAuditLogActorFilterOpts = (workspaceId: string) => {
|
||||||
return useQuery({
|
return useQuery({
|
||||||
queryKey: workspaceKeys.getAuditLogActorFilterOpts(workspaceId),
|
queryKey: workspaceKeys.getAuditLogActorFilterOpts(workspaceId),
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
const { data } = await apiRequest.get<{ actors: Actor[] }>(`/api/v1/workspace/${workspaceId}/audit-logs/filters/actors`);
|
const { data } = await apiRequest.get<{ actors: Actor[] }>(
|
||||||
return data.actors;
|
`/api/v1/workspace/${workspaceId}/audit-logs/filters/actors`
|
||||||
}
|
);
|
||||||
});
|
return data.actors;
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,8 +1,4 @@
|
|||||||
import {
|
import { ActorType, EventType, UserAgentType } from "./enums";
|
||||||
ActorType,
|
|
||||||
EventType,
|
|
||||||
UserAgentType
|
|
||||||
} from "./enums";
|
|
||||||
|
|
||||||
interface UserActorMetadata {
|
interface UserActorMetadata {
|
||||||
userId: string;
|
userId: string;
|
||||||
@@ -25,174 +21,171 @@ export interface ServiceActor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface ServiceActorV3 {
|
export interface ServiceActorV3 {
|
||||||
type: ActorType.SERVICE_V3;
|
type: ActorType.SERVICE_V3;
|
||||||
metadata: ServiceActorMetadata;
|
metadata: ServiceActorMetadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Actor =
|
export type Actor = UserActor | ServiceActor | ServiceActorV3;
|
||||||
| UserActor
|
|
||||||
| ServiceActor
|
|
||||||
| ServiceActorV3;
|
|
||||||
|
|
||||||
interface GetSecretsEvent {
|
interface GetSecretsEvent {
|
||||||
type: EventType.GET_SECRETS;
|
type: EventType.GET_SECRETS;
|
||||||
metadata: {
|
metadata: {
|
||||||
environment: string;
|
environment: string;
|
||||||
secretPath: string;
|
secretPath: string;
|
||||||
numberOfSecrets: number;
|
numberOfSecrets: number;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface GetSecretEvent {
|
interface GetSecretEvent {
|
||||||
type: EventType.GET_SECRET;
|
type: EventType.GET_SECRET;
|
||||||
metadata: {
|
metadata: {
|
||||||
environment: string;
|
environment: string;
|
||||||
secretPath: string;
|
secretPath: string;
|
||||||
secretId: string;
|
secretId: string;
|
||||||
secretKey: string;
|
secretKey: string;
|
||||||
secretVersion: number;
|
secretVersion: number;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface CreateSecretEvent {
|
interface CreateSecretEvent {
|
||||||
type: EventType.CREATE_SECRET;
|
type: EventType.CREATE_SECRET;
|
||||||
metadata: {
|
metadata: {
|
||||||
environment: string;
|
environment: string;
|
||||||
secretPath: string;
|
secretPath: string;
|
||||||
secretId: string;
|
secretId: string;
|
||||||
secretKey: string;
|
secretKey: string;
|
||||||
secretVersion: number;
|
secretVersion: number;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface UpdateSecretEvent {
|
interface UpdateSecretEvent {
|
||||||
type: EventType.UPDATE_SECRET;
|
type: EventType.UPDATE_SECRET;
|
||||||
metadata: {
|
metadata: {
|
||||||
environment: string;
|
environment: string;
|
||||||
secretPath: string;
|
secretPath: string;
|
||||||
secretId: string;
|
secretId: string;
|
||||||
secretKey: string;
|
secretKey: string;
|
||||||
secretVersion: number;
|
secretVersion: number;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DeleteSecretEvent {
|
interface DeleteSecretEvent {
|
||||||
type: EventType.DELETE_SECRET;
|
type: EventType.DELETE_SECRET;
|
||||||
metadata: {
|
metadata: {
|
||||||
environment: string;
|
environment: string;
|
||||||
secretPath: string;
|
secretPath: string;
|
||||||
secretId: string;
|
secretId: string;
|
||||||
secretKey: string;
|
secretKey: string;
|
||||||
secretVersion: number;
|
secretVersion: number;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface GetWorkspaceKeyEvent {
|
interface GetWorkspaceKeyEvent {
|
||||||
type: EventType.GET_WORKSPACE_KEY,
|
type: EventType.GET_WORKSPACE_KEY;
|
||||||
metadata: {
|
metadata: {
|
||||||
keyId: string;
|
keyId: string;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface AuthorizeIntegrationEvent {
|
interface AuthorizeIntegrationEvent {
|
||||||
type: EventType.AUTHORIZE_INTEGRATION;
|
type: EventType.AUTHORIZE_INTEGRATION;
|
||||||
metadata: {
|
metadata: {
|
||||||
integration: string;
|
integration: string;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface UnauthorizeIntegrationEvent {
|
interface UnauthorizeIntegrationEvent {
|
||||||
type: EventType.UNAUTHORIZE_INTEGRATION;
|
type: EventType.UNAUTHORIZE_INTEGRATION;
|
||||||
metadata: {
|
metadata: {
|
||||||
integration: string;
|
integration: string;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface CreateIntegrationEvent {
|
interface CreateIntegrationEvent {
|
||||||
type: EventType.CREATE_INTEGRATION;
|
type: EventType.CREATE_INTEGRATION;
|
||||||
metadata: {
|
metadata: {
|
||||||
integrationId: string;
|
integrationId: string;
|
||||||
integration: string;
|
integration: string;
|
||||||
environment: string;
|
environment: string;
|
||||||
secretPath: string;
|
secretPath: string;
|
||||||
url?: string;
|
url?: string;
|
||||||
app?: string;
|
app?: string;
|
||||||
appId?: string;
|
appId?: string;
|
||||||
targetEnvironment?: string;
|
targetEnvironment?: string;
|
||||||
targetEnvironmentId?: string;
|
targetEnvironmentId?: string;
|
||||||
targetService?: string;
|
targetService?: string;
|
||||||
targetServiceId?: string;
|
targetServiceId?: string;
|
||||||
path?: string;
|
path?: string;
|
||||||
region?: string;
|
region?: string;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DeleteIntegrationEvent {
|
interface DeleteIntegrationEvent {
|
||||||
type: EventType.DELETE_INTEGRATION;
|
type: EventType.DELETE_INTEGRATION;
|
||||||
metadata: {
|
metadata: {
|
||||||
integrationId: string;
|
integrationId: string;
|
||||||
integration: string;
|
integration: string;
|
||||||
environment: string;
|
environment: string;
|
||||||
secretPath: string;
|
secretPath: string;
|
||||||
url?: string;
|
url?: string;
|
||||||
app?: string;
|
app?: string;
|
||||||
appId?: string;
|
appId?: string;
|
||||||
targetEnvironment?: string;
|
targetEnvironment?: string;
|
||||||
targetEnvironmentId?: string;
|
targetEnvironmentId?: string;
|
||||||
targetService?: string;
|
targetService?: string;
|
||||||
targetServiceId?: string;
|
targetServiceId?: string;
|
||||||
path?: string;
|
path?: string;
|
||||||
region?: string;
|
region?: string;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface AddTrustedIPEvent {
|
interface AddTrustedIPEvent {
|
||||||
type: EventType.ADD_TRUSTED_IP;
|
type: EventType.ADD_TRUSTED_IP;
|
||||||
metadata: {
|
metadata: {
|
||||||
trustedIpId: string;
|
trustedIpId: string;
|
||||||
ipAddress: string;
|
ipAddress: string;
|
||||||
prefix?: number;
|
prefix?: number;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface UpdateTrustedIPEvent {
|
interface UpdateTrustedIPEvent {
|
||||||
type: EventType.UPDATE_TRUSTED_IP;
|
type: EventType.UPDATE_TRUSTED_IP;
|
||||||
metadata: {
|
metadata: {
|
||||||
trustedIpId: string;
|
trustedIpId: string;
|
||||||
ipAddress: string;
|
ipAddress: string;
|
||||||
prefix?: number;
|
prefix?: number;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DeleteTrustedIPEvent {
|
interface DeleteTrustedIPEvent {
|
||||||
type: EventType.DELETE_TRUSTED_IP;
|
type: EventType.DELETE_TRUSTED_IP;
|
||||||
metadata: {
|
metadata: {
|
||||||
trustedIpId: string;
|
trustedIpId: string;
|
||||||
ipAddress: string;
|
ipAddress: string;
|
||||||
prefix?: number;
|
prefix?: number;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface CreateServiceTokenEvent {
|
interface CreateServiceTokenEvent {
|
||||||
type: EventType.CREATE_SERVICE_TOKEN;
|
type: EventType.CREATE_SERVICE_TOKEN;
|
||||||
metadata: {
|
metadata: {
|
||||||
name: string;
|
name: string;
|
||||||
scopes: Array<{
|
scopes: Array<{
|
||||||
environment: string;
|
environment: string;
|
||||||
secretPath: string;
|
secretPath: string;
|
||||||
}>;
|
}>;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DeleteServiceTokenEvent {
|
interface DeleteServiceTokenEvent {
|
||||||
type: EventType.DELETE_SERVICE_TOKEN;
|
type: EventType.DELETE_SERVICE_TOKEN;
|
||||||
metadata: {
|
metadata: {
|
||||||
name: string;
|
name: string;
|
||||||
scopes: Array<{
|
scopes: Array<{
|
||||||
environment: string;
|
environment: string;
|
||||||
secretPath: string;
|
secretPath: string;
|
||||||
}>;
|
}>;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface CreateServiceTokenV3Event {
|
interface CreateServiceTokenV3Event {
|
||||||
@@ -226,222 +219,221 @@ interface DeleteServiceTokenV3Event {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface CreateEnvironmentEvent {
|
interface CreateEnvironmentEvent {
|
||||||
type: EventType.CREATE_ENVIRONMENT;
|
type: EventType.CREATE_ENVIRONMENT;
|
||||||
metadata: {
|
metadata: {
|
||||||
name: string;
|
name: string;
|
||||||
slug: string;
|
slug: string;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface UpdateEnvironmentEvent {
|
interface UpdateEnvironmentEvent {
|
||||||
type: EventType.UPDATE_ENVIRONMENT;
|
type: EventType.UPDATE_ENVIRONMENT;
|
||||||
metadata: {
|
metadata: {
|
||||||
oldName: string;
|
oldName: string;
|
||||||
newName: string;
|
newName: string;
|
||||||
oldSlug: string;
|
oldSlug: string;
|
||||||
newSlug: string;
|
newSlug: string;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DeleteEnvironmentEvent {
|
interface DeleteEnvironmentEvent {
|
||||||
type: EventType.DELETE_ENVIRONMENT;
|
type: EventType.DELETE_ENVIRONMENT;
|
||||||
metadata: {
|
metadata: {
|
||||||
name: string;
|
name: string;
|
||||||
slug: string;
|
slug: string;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface AddWorkspaceMemberEvent {
|
interface AddWorkspaceMemberEvent {
|
||||||
type: EventType.ADD_WORKSPACE_MEMBER;
|
type: EventType.ADD_WORKSPACE_MEMBER;
|
||||||
metadata: {
|
metadata: {
|
||||||
userId: string;
|
userId: string;
|
||||||
email: string;
|
email: string;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface RemoveWorkspaceMemberEvent {
|
interface RemoveWorkspaceMemberEvent {
|
||||||
type: EventType.REMOVE_WORKSPACE_MEMBER;
|
type: EventType.REMOVE_WORKSPACE_MEMBER;
|
||||||
metadata: {
|
metadata: {
|
||||||
userId: string;
|
userId: string;
|
||||||
email: string;
|
email: string;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface CreateFolderEvent {
|
interface CreateFolderEvent {
|
||||||
type: EventType.CREATE_FOLDER;
|
type: EventType.CREATE_FOLDER;
|
||||||
metadata: {
|
metadata: {
|
||||||
environment: string;
|
environment: string;
|
||||||
folderId: string;
|
folderId: string;
|
||||||
folderName: string;
|
folderName: string;
|
||||||
folderPath: string;
|
folderPath: string;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface UpdateFolderEvent {
|
interface UpdateFolderEvent {
|
||||||
type: EventType.UPDATE_FOLDER;
|
type: EventType.UPDATE_FOLDER;
|
||||||
metadata: {
|
metadata: {
|
||||||
environment: string;
|
environment: string;
|
||||||
folderId: string;
|
folderId: string;
|
||||||
oldFolderName: string;
|
oldFolderName: string;
|
||||||
newFolderName: string;
|
newFolderName: string;
|
||||||
folderPath: string;
|
folderPath: string;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DeleteFolderEvent {
|
interface DeleteFolderEvent {
|
||||||
type: EventType.DELETE_FOLDER;
|
type: EventType.DELETE_FOLDER;
|
||||||
metadata: {
|
metadata: {
|
||||||
environment: string;
|
environment: string;
|
||||||
folderId: string;
|
folderId: string;
|
||||||
folderName: string;
|
folderName: string;
|
||||||
folderPath: string;
|
folderPath: string;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface CreateWebhookEvent {
|
interface CreateWebhookEvent {
|
||||||
type: EventType.CREATE_WEBHOOK,
|
type: EventType.CREATE_WEBHOOK;
|
||||||
metadata: {
|
metadata: {
|
||||||
webhookId: string;
|
webhookId: string;
|
||||||
environment: string;
|
environment: string;
|
||||||
secretPath: string;
|
secretPath: string;
|
||||||
webhookUrl: string;
|
webhookUrl: string;
|
||||||
isDisabled: boolean;
|
isDisabled: boolean;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface UpdateWebhookStatusEvent {
|
interface UpdateWebhookStatusEvent {
|
||||||
type: EventType.UPDATE_WEBHOOK_STATUS,
|
type: EventType.UPDATE_WEBHOOK_STATUS;
|
||||||
metadata: {
|
metadata: {
|
||||||
webhookId: string;
|
webhookId: string;
|
||||||
environment: string;
|
environment: string;
|
||||||
secretPath: string;
|
secretPath: string;
|
||||||
webhookUrl: string;
|
webhookUrl: string;
|
||||||
isDisabled: boolean;
|
isDisabled: boolean;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DeleteWebhookEvent {
|
interface DeleteWebhookEvent {
|
||||||
type: EventType.DELETE_WEBHOOK,
|
type: EventType.DELETE_WEBHOOK;
|
||||||
metadata: {
|
metadata: {
|
||||||
webhookId: string;
|
webhookId: string;
|
||||||
environment: string;
|
environment: string;
|
||||||
secretPath: string;
|
secretPath: string;
|
||||||
webhookUrl: string;
|
webhookUrl: string;
|
||||||
isDisabled: boolean;
|
isDisabled: boolean;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface GetSecretImportsEvent {
|
interface GetSecretImportsEvent {
|
||||||
type: EventType.GET_SECRET_IMPORTS,
|
type: EventType.GET_SECRET_IMPORTS;
|
||||||
metadata: {
|
metadata: {
|
||||||
environment: string;
|
environment: string;
|
||||||
secretImportId: string;
|
secretImportId: string;
|
||||||
folderId: string;
|
folderId: string;
|
||||||
numberOfImports: number;
|
numberOfImports: number;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface CreateSecretImportEvent {
|
interface CreateSecretImportEvent {
|
||||||
type: EventType.CREATE_SECRET_IMPORT,
|
type: EventType.CREATE_SECRET_IMPORT;
|
||||||
metadata: {
|
metadata: {
|
||||||
secretImportId: string;
|
secretImportId: string;
|
||||||
folderId: string;
|
folderId: string;
|
||||||
importFromEnvironment: string;
|
importFromEnvironment: string;
|
||||||
importFromSecretPath: string;
|
importFromSecretPath: string;
|
||||||
importToEnvironment: string;
|
importToEnvironment: string;
|
||||||
importToSecretPath: string;
|
importToSecretPath: string;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface UpdateSecretImportEvent {
|
interface UpdateSecretImportEvent {
|
||||||
type: EventType.UPDATE_SECRET_IMPORT,
|
type: EventType.UPDATE_SECRET_IMPORT;
|
||||||
metadata: {
|
metadata: {
|
||||||
secretImportId: string;
|
secretImportId: string;
|
||||||
folderId: string;
|
folderId: string;
|
||||||
importToEnvironment: string;
|
importToEnvironment: string;
|
||||||
importToSecretPath: string;
|
importToSecretPath: string;
|
||||||
orderBefore: {
|
orderBefore: {
|
||||||
environment: string;
|
environment: string;
|
||||||
secretPath: string;
|
secretPath: string;
|
||||||
}[],
|
}[];
|
||||||
orderAfter: {
|
orderAfter: {
|
||||||
environment: string;
|
environment: string;
|
||||||
secretPath: string;
|
secretPath: string;
|
||||||
}[]
|
}[];
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DeleteSecretImportEvent {
|
interface DeleteSecretImportEvent {
|
||||||
type: EventType.DELETE_SECRET_IMPORT,
|
type: EventType.DELETE_SECRET_IMPORT;
|
||||||
metadata: {
|
metadata: {
|
||||||
secretImportId: string;
|
secretImportId: string;
|
||||||
folderId: string;
|
folderId: string;
|
||||||
importFromEnvironment: string;
|
importFromEnvironment: string;
|
||||||
importFromSecretPath: string;
|
importFromSecretPath: string;
|
||||||
importToEnvironment: string;
|
importToEnvironment: string;
|
||||||
importToSecretPath: string;
|
importToSecretPath: string;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface UpdateUserRole {
|
interface UpdateUserRole {
|
||||||
type: EventType.UPDATE_USER_WORKSPACE_ROLE,
|
type: EventType.UPDATE_USER_WORKSPACE_ROLE;
|
||||||
metadata: {
|
metadata: {
|
||||||
userId: string;
|
userId: string;
|
||||||
email: string;
|
email: string;
|
||||||
oldRole: string;
|
oldRole: string;
|
||||||
newRole: string;
|
newRole: string;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface UpdateUserDeniedPermissions {
|
interface UpdateUserDeniedPermissions {
|
||||||
type: EventType.UPDATE_USER_WORKSPACE_DENIED_PERMISSIONS,
|
type: EventType.UPDATE_USER_WORKSPACE_DENIED_PERMISSIONS;
|
||||||
metadata: {
|
metadata: {
|
||||||
userId: string;
|
userId: string;
|
||||||
email: string;
|
email: string;
|
||||||
deniedPermissions: {
|
deniedPermissions: {
|
||||||
environmentSlug: string;
|
environmentSlug: string;
|
||||||
ability: string;
|
ability: string;
|
||||||
}[]
|
}[];
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export type Event =
|
export type Event =
|
||||||
| GetSecretsEvent
|
| GetSecretsEvent
|
||||||
| GetSecretEvent
|
| GetSecretEvent
|
||||||
| CreateSecretEvent
|
| CreateSecretEvent
|
||||||
| UpdateSecretEvent
|
| UpdateSecretEvent
|
||||||
| DeleteSecretEvent
|
| DeleteSecretEvent
|
||||||
| GetWorkspaceKeyEvent
|
| GetWorkspaceKeyEvent
|
||||||
| AuthorizeIntegrationEvent
|
| AuthorizeIntegrationEvent
|
||||||
| UnauthorizeIntegrationEvent
|
| UnauthorizeIntegrationEvent
|
||||||
| CreateIntegrationEvent
|
| CreateIntegrationEvent
|
||||||
| DeleteIntegrationEvent
|
| DeleteIntegrationEvent
|
||||||
| AddTrustedIPEvent
|
| AddTrustedIPEvent
|
||||||
| UpdateTrustedIPEvent
|
| UpdateTrustedIPEvent
|
||||||
| DeleteTrustedIPEvent
|
| DeleteTrustedIPEvent
|
||||||
| CreateServiceTokenEvent
|
| CreateServiceTokenEvent
|
||||||
| DeleteServiceTokenEvent
|
| DeleteServiceTokenEvent
|
||||||
| CreateServiceTokenV3Event
|
| CreateServiceTokenV3Event
|
||||||
| UpdateServiceTokenV3Event
|
| UpdateServiceTokenV3Event
|
||||||
| DeleteServiceTokenV3Event
|
| DeleteServiceTokenV3Event
|
||||||
| CreateEnvironmentEvent
|
| CreateEnvironmentEvent
|
||||||
| UpdateEnvironmentEvent
|
| UpdateEnvironmentEvent
|
||||||
| DeleteEnvironmentEvent
|
| DeleteEnvironmentEvent
|
||||||
| AddWorkspaceMemberEvent
|
| AddWorkspaceMemberEvent
|
||||||
| RemoveWorkspaceMemberEvent
|
| RemoveWorkspaceMemberEvent
|
||||||
| CreateFolderEvent
|
| CreateFolderEvent
|
||||||
| UpdateFolderEvent
|
| UpdateFolderEvent
|
||||||
| DeleteFolderEvent
|
| DeleteFolderEvent
|
||||||
| CreateWebhookEvent
|
| CreateWebhookEvent
|
||||||
| UpdateWebhookStatusEvent
|
| UpdateWebhookStatusEvent
|
||||||
| DeleteWebhookEvent
|
| DeleteWebhookEvent
|
||||||
| GetSecretImportsEvent
|
| GetSecretImportsEvent
|
||||||
| CreateSecretImportEvent
|
| CreateSecretImportEvent
|
||||||
| UpdateSecretImportEvent
|
| UpdateSecretImportEvent
|
||||||
| DeleteSecretImportEvent
|
| DeleteSecretImportEvent
|
||||||
| UpdateUserRole
|
| UpdateUserRole
|
||||||
| UpdateUserDeniedPermissions;
|
| UpdateUserDeniedPermissions;
|
||||||
|
|
||||||
export type AuditLog = {
|
export type AuditLog = {
|
||||||
_id: string;
|
_id: string;
|
||||||
@@ -454,14 +446,13 @@ export type AuditLog = {
|
|||||||
userAgentType: UserAgentType;
|
userAgentType: UserAgentType;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
export type AuditLogFilters = {
|
export type AuditLogFilters = {
|
||||||
eventType?: EventType;
|
eventType?: EventType;
|
||||||
userAgentType?: UserAgentType;
|
userAgentType?: UserAgentType;
|
||||||
actor?: string;
|
actor?: string;
|
||||||
offset: number;
|
limit: number;
|
||||||
limit: number;
|
startDate?: Date;
|
||||||
startDate?: Date;
|
endDate?: Date;
|
||||||
endDate?: Date;
|
};
|
||||||
}
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export const AuditLogsPage = withProjectPermission(
|
|||||||
return (
|
return (
|
||||||
<div className="flex justify-center bg-bunker-800 text-white w-full h-full">
|
<div className="flex justify-center bg-bunker-800 text-white w-full h-full">
|
||||||
<div className="max-w-7xl px-6 w-full">
|
<div className="max-w-7xl px-6 w-full">
|
||||||
<div className="my-6">
|
<div className="py-6 sticky top-0 z-10 bg-bunker-800">
|
||||||
<p className="text-3xl font-semibold text-gray-200">Audit Logs</p>
|
<p className="text-3xl font-semibold text-gray-200">Audit Logs</p>
|
||||||
<div />
|
<div />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,13 +3,7 @@ import { Control, Controller, UseFormReset } from "react-hook-form";
|
|||||||
import { faFilterCircleXmark } from "@fortawesome/free-solid-svg-icons";
|
import { faFilterCircleXmark } from "@fortawesome/free-solid-svg-icons";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
|
||||||
import {
|
import { Button, DatePicker, FormControl, Select, SelectItem } from "@app/components/v2";
|
||||||
Button,
|
|
||||||
DatePicker,
|
|
||||||
FormControl,
|
|
||||||
Select,
|
|
||||||
SelectItem
|
|
||||||
} from "@app/components/v2";
|
|
||||||
import { useWorkspace } from "@app/context";
|
import { useWorkspace } from "@app/context";
|
||||||
import { useGetAuditLogActorFilterOpts } from "@app/hooks/api";
|
import { useGetAuditLogActorFilterOpts } from "@app/hooks/api";
|
||||||
import { eventToNameMap, userAgentTTypeoNameMap } from "@app/hooks/api/auditLogs/constants";
|
import { eventToNameMap, userAgentTTypeoNameMap } from "@app/hooks/api/auditLogs/constants";
|
||||||
@@ -19,201 +13,207 @@ import { Actor } from "@app/hooks/api/auditLogs/types";
|
|||||||
import { AuditLogFilterFormData } from "./types";
|
import { AuditLogFilterFormData } from "./types";
|
||||||
|
|
||||||
const eventTypes = Object.entries(eventToNameMap).map(([value, label]) => ({ label, value }));
|
const eventTypes = Object.entries(eventToNameMap).map(([value, label]) => ({ label, value }));
|
||||||
const userAgentTypes = Object.entries(userAgentTTypeoNameMap).map(([value, label]) => ({ label, value }));
|
const userAgentTypes = Object.entries(userAgentTTypeoNameMap).map(([value, label]) => ({
|
||||||
|
label,
|
||||||
|
value
|
||||||
|
}));
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
control: Control<AuditLogFilterFormData>;
|
control: Control<AuditLogFilterFormData>;
|
||||||
reset: UseFormReset<AuditLogFilterFormData>;
|
reset: UseFormReset<AuditLogFilterFormData>;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const LogsFilter = ({
|
export const LogsFilter = ({ control, reset }: Props) => {
|
||||||
control,
|
const [isStartDatePickerOpen, setIsStartDatePickerOpen] = useState(false);
|
||||||
reset
|
const [isEndDatePickerOpen, setIsEndDatePickerOpen] = useState(false);
|
||||||
}: Props) => {
|
|
||||||
const [isStartDatePickerOpen, setIsStartDatePickerOpen] = useState(false);
|
|
||||||
const [isEndDatePickerOpen, setIsEndDatePickerOpen] = useState(false);
|
|
||||||
|
|
||||||
const { currentWorkspace } = useWorkspace();
|
const { currentWorkspace } = useWorkspace();
|
||||||
const { data, isLoading } = useGetAuditLogActorFilterOpts(currentWorkspace?._id ?? "");
|
const { data, isLoading } = useGetAuditLogActorFilterOpts(currentWorkspace?._id ?? "");
|
||||||
|
|
||||||
const renderActorSelectItem = (actor: Actor) => {
|
|
||||||
switch (actor.type) {
|
|
||||||
case ActorType.USER:
|
|
||||||
return (
|
|
||||||
<SelectItem value={`${actor.type}-${actor.metadata.userId}`} key={`user-actor-filter-${actor.metadata.userId}`}>
|
|
||||||
{actor.metadata.email}
|
|
||||||
</SelectItem>
|
|
||||||
);
|
|
||||||
case ActorType.SERVICE:
|
|
||||||
return (
|
|
||||||
<SelectItem value={`${actor.type}-${actor.metadata.serviceId}`} key={`service-actor-filter-${actor.metadata.serviceId}`}>
|
|
||||||
{actor.metadata.name}
|
|
||||||
</SelectItem>
|
|
||||||
);
|
|
||||||
case ActorType.SERVICE_V3:
|
|
||||||
return (
|
|
||||||
<SelectItem value={`${actor.type}-${actor.metadata.serviceId}`} key={`service-actor-v3-filter-${actor.metadata.serviceId}`}>
|
|
||||||
{actor.metadata.name}
|
|
||||||
</SelectItem>
|
|
||||||
);
|
|
||||||
default:
|
|
||||||
return (
|
|
||||||
<SelectItem value="actor-none" key="actor-none">
|
|
||||||
N/A
|
|
||||||
</SelectItem>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
const renderActorSelectItem = (actor: Actor) => {
|
||||||
|
switch (actor.type) {
|
||||||
|
case ActorType.USER:
|
||||||
|
return (
|
||||||
|
<SelectItem
|
||||||
|
value={`${actor.type}-${actor.metadata.userId}`}
|
||||||
|
key={`user-actor-filter-${actor.metadata.userId}`}
|
||||||
|
>
|
||||||
|
{actor.metadata.email}
|
||||||
|
</SelectItem>
|
||||||
|
);
|
||||||
|
case ActorType.SERVICE:
|
||||||
|
return (
|
||||||
|
<SelectItem
|
||||||
|
value={`${actor.type}-${actor.metadata.serviceId}`}
|
||||||
|
key={`service-actor-filter-${actor.metadata.serviceId}`}
|
||||||
|
>
|
||||||
|
{actor.metadata.name}
|
||||||
|
</SelectItem>
|
||||||
|
);
|
||||||
|
case ActorType.SERVICE_V3:
|
||||||
|
return (
|
||||||
|
<SelectItem
|
||||||
|
value={`${actor.type}-${actor.metadata.serviceId}`}
|
||||||
|
key={`service-actor-v3-filter-${actor.metadata.serviceId}`}
|
||||||
|
>
|
||||||
|
{actor.metadata.name}
|
||||||
|
</SelectItem>
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
return (
|
||||||
|
<SelectItem value="actor-none" key="actor-none">
|
||||||
|
N/A
|
||||||
|
</SelectItem>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center sticky top-20 z-10 bg-bunker-800">
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
name="eventType"
|
name="eventType"
|
||||||
render={({ field: { onChange, ...field }, fieldState: { error } }) => (
|
render={({ field: { onChange, ...field }, fieldState: { error } }) => (
|
||||||
<FormControl
|
<FormControl
|
||||||
label="Event"
|
label="Event"
|
||||||
errorText={error?.message}
|
errorText={error?.message}
|
||||||
isError={Boolean(error)}
|
isError={Boolean(error)}
|
||||||
className="w-40 mr-4"
|
className="w-40 mr-4"
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
{...(field.value ? { value: field.value } : { placeholder: "Select" })}
|
{...(field.value ? { value: field.value } : { placeholder: "Select" })}
|
||||||
{...field}
|
{...field}
|
||||||
onValueChange={(e) => onChange(e)}
|
onValueChange={(e) => onChange(e)}
|
||||||
className="w-full bg-mineshaft-700 border border-mineshaft-500 text-mineshaft-100"
|
className="w-full bg-mineshaft-700 border border-mineshaft-500 text-mineshaft-100"
|
||||||
>
|
>
|
||||||
{eventTypes.map(({ label, value }) => (
|
{eventTypes.map(({ label, value }) => (
|
||||||
<SelectItem value={String(value || "")} key={label}>
|
<SelectItem value={String(value || "")} key={label}>
|
||||||
{label}
|
{label}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
))}
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
{!isLoading && data && data.length > 0 && (
|
{!isLoading && data && data.length > 0 && (
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
name="actor"
|
name="actor"
|
||||||
render={({ field: { onChange, ...field }, fieldState: { error } }) => (
|
render={({ field: { onChange, ...field }, fieldState: { error } }) => (
|
||||||
<FormControl
|
<FormControl
|
||||||
label="Actor"
|
label="Actor"
|
||||||
errorText={error?.message}
|
errorText={error?.message}
|
||||||
isError={Boolean(error)}
|
isError={Boolean(error)}
|
||||||
className="w-40 mr-4"
|
className="w-40 mr-4"
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
{...(field.value ? { value: field.value } : { placeholder: "Select" })}
|
{...(field.value ? { value: field.value } : { placeholder: "Select" })}
|
||||||
{...field}
|
{...field}
|
||||||
onValueChange={(e) => onChange(e)}
|
onValueChange={(e) => onChange(e)}
|
||||||
className="w-full bg-mineshaft-700 border border-mineshaft-500 text-mineshaft-100"
|
className="w-full bg-mineshaft-700 border border-mineshaft-500 text-mineshaft-100"
|
||||||
>
|
|
||||||
{data.map((actor) => renderActorSelectItem(actor))}
|
|
||||||
</Select>
|
|
||||||
</FormControl>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<Controller
|
|
||||||
control={control}
|
|
||||||
name="userAgentType"
|
|
||||||
render={({ field: { onChange, ...field }, fieldState: { error } }) => (
|
|
||||||
<FormControl
|
|
||||||
label="Source"
|
|
||||||
errorText={error?.message}
|
|
||||||
isError={Boolean(error)}
|
|
||||||
className="w-40 mr-4"
|
|
||||||
>
|
|
||||||
<Select
|
|
||||||
{...(field.value ? { value: field.value } : { placeholder: "Select" })}
|
|
||||||
{...field}
|
|
||||||
onValueChange={(e) => onChange(e)}
|
|
||||||
className="w-full bg-mineshaft-700 border border-mineshaft-500 text-mineshaft-100"
|
|
||||||
>
|
|
||||||
{userAgentTypes.map(({ label, value }) => (
|
|
||||||
<SelectItem value={String(value || "")} key={label}>
|
|
||||||
{label}
|
|
||||||
</SelectItem>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
</FormControl>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<Controller
|
|
||||||
name="startDate"
|
|
||||||
control={control}
|
|
||||||
render={({ field: { onChange, ...field }, fieldState: { error } }) => {
|
|
||||||
return (
|
|
||||||
<FormControl
|
|
||||||
label="Start date"
|
|
||||||
errorText={error?.message}
|
|
||||||
isError={Boolean(error)}
|
|
||||||
className="mr-4"
|
|
||||||
>
|
|
||||||
<DatePicker
|
|
||||||
value={field.value || undefined}
|
|
||||||
onChange={date => {
|
|
||||||
onChange(date);
|
|
||||||
setIsStartDatePickerOpen(false);
|
|
||||||
}}
|
|
||||||
popUpProps={{
|
|
||||||
open: isStartDatePickerOpen,
|
|
||||||
onOpenChange: setIsStartDatePickerOpen
|
|
||||||
}}
|
|
||||||
popUpContentProps={{}}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Controller
|
|
||||||
name="endDate"
|
|
||||||
control={control}
|
|
||||||
render={({ field: { onChange, ...field }, fieldState: { error } }) => {
|
|
||||||
return (
|
|
||||||
<FormControl
|
|
||||||
label="End date"
|
|
||||||
errorText={error?.message}
|
|
||||||
isError={Boolean(error)}
|
|
||||||
>
|
|
||||||
<DatePicker
|
|
||||||
value={field.value || undefined}
|
|
||||||
onChange={date => {
|
|
||||||
onChange(date);
|
|
||||||
setIsEndDatePickerOpen(false);
|
|
||||||
}}
|
|
||||||
popUpProps={{
|
|
||||||
open: isEndDatePickerOpen,
|
|
||||||
onOpenChange: setIsEndDatePickerOpen
|
|
||||||
}}
|
|
||||||
popUpContentProps={{}}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<Button
|
|
||||||
isLoading={false}
|
|
||||||
colorSchema="primary"
|
|
||||||
variant="outline_bg"
|
|
||||||
type="submit"
|
|
||||||
leftIcon={<FontAwesomeIcon icon={faFilterCircleXmark} className="mr-2" />}
|
|
||||||
onClick={() => reset({
|
|
||||||
eventType: undefined,
|
|
||||||
actor: undefined,
|
|
||||||
userAgentType: undefined,
|
|
||||||
startDate: undefined,
|
|
||||||
endDate: undefined
|
|
||||||
})}
|
|
||||||
>
|
>
|
||||||
Clear filters
|
{data.map((actor) => renderActorSelectItem(actor))}
|
||||||
</Button>
|
</Select>
|
||||||
</div>
|
</FormControl>
|
||||||
</div>
|
)}
|
||||||
);
|
/>
|
||||||
}
|
)}
|
||||||
|
<Controller
|
||||||
|
control={control}
|
||||||
|
name="userAgentType"
|
||||||
|
render={({ field: { onChange, ...field }, fieldState: { error } }) => (
|
||||||
|
<FormControl
|
||||||
|
label="Source"
|
||||||
|
errorText={error?.message}
|
||||||
|
isError={Boolean(error)}
|
||||||
|
className="w-40 mr-4"
|
||||||
|
>
|
||||||
|
<Select
|
||||||
|
{...(field.value ? { value: field.value } : { placeholder: "Select" })}
|
||||||
|
{...field}
|
||||||
|
onValueChange={(e) => onChange(e)}
|
||||||
|
className="w-full bg-mineshaft-700 border border-mineshaft-500 text-mineshaft-100"
|
||||||
|
>
|
||||||
|
{userAgentTypes.map(({ label, value }) => (
|
||||||
|
<SelectItem value={String(value || "")} key={label}>
|
||||||
|
{label}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
</FormControl>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<Controller
|
||||||
|
name="startDate"
|
||||||
|
control={control}
|
||||||
|
render={({ field: { onChange, ...field }, fieldState: { error } }) => {
|
||||||
|
return (
|
||||||
|
<FormControl
|
||||||
|
label="Start date"
|
||||||
|
errorText={error?.message}
|
||||||
|
isError={Boolean(error)}
|
||||||
|
className="mr-4"
|
||||||
|
>
|
||||||
|
<DatePicker
|
||||||
|
value={field.value || undefined}
|
||||||
|
onChange={(date) => {
|
||||||
|
onChange(date);
|
||||||
|
setIsStartDatePickerOpen(false);
|
||||||
|
}}
|
||||||
|
popUpProps={{
|
||||||
|
open: isStartDatePickerOpen,
|
||||||
|
onOpenChange: setIsStartDatePickerOpen
|
||||||
|
}}
|
||||||
|
popUpContentProps={{}}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Controller
|
||||||
|
name="endDate"
|
||||||
|
control={control}
|
||||||
|
render={({ field: { onChange, ...field }, fieldState: { error } }) => {
|
||||||
|
return (
|
||||||
|
<FormControl label="End date" errorText={error?.message} isError={Boolean(error)}>
|
||||||
|
<DatePicker
|
||||||
|
value={field.value || undefined}
|
||||||
|
onChange={(date) => {
|
||||||
|
onChange(date);
|
||||||
|
setIsEndDatePickerOpen(false);
|
||||||
|
}}
|
||||||
|
popUpProps={{
|
||||||
|
open: isEndDatePickerOpen,
|
||||||
|
onOpenChange: setIsEndDatePickerOpen
|
||||||
|
}}
|
||||||
|
popUpContentProps={{}}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Button
|
||||||
|
isLoading={false}
|
||||||
|
colorSchema="primary"
|
||||||
|
variant="outline_bg"
|
||||||
|
type="submit"
|
||||||
|
leftIcon={<FontAwesomeIcon icon={faFilterCircleXmark} className="mr-2" />}
|
||||||
|
onClick={() =>
|
||||||
|
reset({
|
||||||
|
eventType: undefined,
|
||||||
|
actor: undefined,
|
||||||
|
userAgentType: undefined,
|
||||||
|
startDate: undefined,
|
||||||
|
endDate: undefined
|
||||||
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Clear filters
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|||||||
@@ -13,78 +13,54 @@ import { LogsTable } from "./LogsTable";
|
|||||||
import { AuditLogFilterFormData, auditLogFilterFormSchema } from "./types";
|
import { AuditLogFilterFormData, auditLogFilterFormSchema } from "./types";
|
||||||
|
|
||||||
export const LogsSection = () => {
|
export const LogsSection = () => {
|
||||||
const { subscription } = useSubscription();
|
const { subscription } = useSubscription();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const { popUp, handlePopUpOpen, handlePopUpToggle } = usePopUp([
|
const { popUp, handlePopUpOpen, handlePopUpToggle } = usePopUp(["upgradePlan"] as const);
|
||||||
"upgradePlan"
|
|
||||||
] as const);
|
|
||||||
|
|
||||||
const {
|
const { control, reset, watch } = useForm<AuditLogFilterFormData>({
|
||||||
control,
|
resolver: yupResolver(auditLogFilterFormSchema),
|
||||||
reset,
|
defaultValues: {
|
||||||
watch,
|
page: 1,
|
||||||
setValue,
|
perPage: 10
|
||||||
} = useForm<AuditLogFilterFormData>({
|
}
|
||||||
resolver: yupResolver(auditLogFilterFormSchema),
|
});
|
||||||
defaultValues: {
|
|
||||||
page: 1,
|
|
||||||
perPage: 10
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (subscription && !subscription.auditLogs) {
|
if (subscription && !subscription.auditLogs) {
|
||||||
handlePopUpOpen("upgradePlan");
|
handlePopUpOpen("upgradePlan");
|
||||||
}
|
}
|
||||||
}, [subscription]);
|
}, [subscription]);
|
||||||
|
|
||||||
const eventType = watch("eventType") as EventType | undefined;
|
const eventType = watch("eventType") as EventType | undefined;
|
||||||
const userAgentType = watch("userAgentType") as UserAgentType | undefined;
|
const userAgentType = watch("userAgentType") as UserAgentType | undefined;
|
||||||
const actor = watch("actor");
|
const actor = watch("actor");
|
||||||
|
|
||||||
const startDate = watch("startDate");
|
const startDate = watch("startDate");
|
||||||
const endDate = watch("endDate");
|
const endDate = watch("endDate");
|
||||||
|
|
||||||
const page = watch("page") as number;
|
return (
|
||||||
const perPage = watch("perPage") as number;
|
<div>
|
||||||
|
<LogsFilter control={control} reset={reset} />
|
||||||
|
<LogsTable
|
||||||
|
eventType={eventType}
|
||||||
|
userAgentType={userAgentType}
|
||||||
|
actor={actor}
|
||||||
|
startDate={startDate}
|
||||||
|
endDate={endDate}
|
||||||
|
/>
|
||||||
|
<UpgradePlanModal
|
||||||
|
isOpen={popUp.upgradePlan.isOpen}
|
||||||
|
onOpenChange={(isOpen) => {
|
||||||
|
if (!isOpen) {
|
||||||
|
router.back();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
handlePopUpToggle("upgradePlan", isOpen);
|
||||||
<div
|
}}
|
||||||
// className="p-4 bg-mineshaft-900 mb-6 rounded-lg border border-mineshaft-600"
|
text="You can use audit logs if you switch to a paid Infisical plan."
|
||||||
>
|
/>
|
||||||
{/* <div className="flex items-center mb-8">
|
</div>
|
||||||
<h2 className="text-xl font-semibold flex-1 text-white">
|
);
|
||||||
Audit Logs
|
};
|
||||||
</h2>
|
|
||||||
</div> */}
|
|
||||||
<LogsFilter
|
|
||||||
control={control}
|
|
||||||
reset={reset}
|
|
||||||
/>
|
|
||||||
<LogsTable
|
|
||||||
eventType={eventType}
|
|
||||||
userAgentType={userAgentType}
|
|
||||||
actor={actor}
|
|
||||||
startDate={startDate}
|
|
||||||
endDate={endDate}
|
|
||||||
page={page}
|
|
||||||
perPage={perPage}
|
|
||||||
setValue={setValue}
|
|
||||||
/>
|
|
||||||
<UpgradePlanModal
|
|
||||||
isOpen={popUp.upgradePlan.isOpen}
|
|
||||||
onOpenChange={(isOpen) => {
|
|
||||||
|
|
||||||
if (!isOpen) {
|
|
||||||
router.back();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
handlePopUpToggle("upgradePlan", isOpen)
|
|
||||||
}}
|
|
||||||
text="You can use audit logs if you switch to a paid Infisical plan."
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,96 +1,95 @@
|
|||||||
|
import { Fragment } from "react";
|
||||||
import { faFile } from "@fortawesome/free-solid-svg-icons";
|
import { faFile } from "@fortawesome/free-solid-svg-icons";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
EmptyState,
|
Button,
|
||||||
Pagination,
|
EmptyState,
|
||||||
Table,
|
Table,
|
||||||
TableContainer,
|
TableContainer,
|
||||||
TableSkeleton,
|
TableSkeleton,
|
||||||
TBody,
|
TBody,
|
||||||
Td,
|
Td,
|
||||||
Th,
|
Th,
|
||||||
THead,
|
THead,
|
||||||
Tr} from "@app/components/v2";
|
Tr
|
||||||
|
} from "@app/components/v2";
|
||||||
import { useWorkspace } from "@app/context";
|
import { useWorkspace } from "@app/context";
|
||||||
import { useGetAuditLogs } from "@app/hooks/api";
|
import { useGetAuditLogs } from "@app/hooks/api";
|
||||||
import { EventType, UserAgentType } from "@app/hooks/api/auditLogs/enums";
|
import { EventType, UserAgentType } from "@app/hooks/api/auditLogs/enums";
|
||||||
|
|
||||||
import { LogsTableRow } from "./LogsTableRow";
|
import { LogsTableRow } from "./LogsTableRow";
|
||||||
import { SetValueType } from "./types";
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
eventType?: EventType;
|
eventType?: EventType;
|
||||||
userAgentType?: UserAgentType;
|
userAgentType?: UserAgentType;
|
||||||
actor?: string;
|
actor?: string;
|
||||||
startDate?: Date;
|
startDate?: Date;
|
||||||
endDate?: Date;
|
endDate?: Date;
|
||||||
page: number;
|
};
|
||||||
perPage: number;
|
|
||||||
setValue: SetValueType;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const LogsTable = ({
|
const AUDIT_LOG_LIMIT = 15;
|
||||||
eventType,
|
|
||||||
userAgentType,
|
|
||||||
actor,
|
|
||||||
startDate,
|
|
||||||
endDate,
|
|
||||||
page,
|
|
||||||
perPage,
|
|
||||||
setValue
|
|
||||||
}: Props) => {
|
|
||||||
const { currentWorkspace } = useWorkspace();
|
|
||||||
const { data, isLoading } = useGetAuditLogs(currentWorkspace?._id ?? "", {
|
|
||||||
eventType,
|
|
||||||
userAgentType,
|
|
||||||
actor,
|
|
||||||
startDate,
|
|
||||||
endDate,
|
|
||||||
offset: (page - 1) * perPage,
|
|
||||||
limit: perPage
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
export const LogsTable = ({ eventType, userAgentType, actor, startDate, endDate }: Props) => {
|
||||||
<TableContainer>
|
const { currentWorkspace } = useWorkspace();
|
||||||
<Table>
|
const { data, isLoading, isFetchingNextPage, hasNextPage, fetchNextPage } = useGetAuditLogs(
|
||||||
<THead>
|
currentWorkspace?._id ?? "",
|
||||||
<Tr>
|
{
|
||||||
<Th>Timestamp</Th>
|
eventType,
|
||||||
<Th>Event</Th>
|
userAgentType,
|
||||||
<Th>Actor</Th>
|
actor,
|
||||||
<Th>Source</Th>
|
startDate,
|
||||||
<Th>Metadata</Th>
|
endDate,
|
||||||
</Tr>
|
limit: AUDIT_LOG_LIMIT
|
||||||
</THead>
|
}
|
||||||
<TBody>
|
);
|
||||||
{!isLoading && data?.auditLogs && data?.auditLogs.map((auditLog) => (
|
|
||||||
<LogsTableRow
|
const isEmpty = !isLoading && !data?.pages?.[0].length;
|
||||||
auditLog={auditLog}
|
|
||||||
key={`audit-log-${auditLog._id}`}
|
return (
|
||||||
/>
|
<div>
|
||||||
))}
|
<TableContainer>
|
||||||
{isLoading && <TableSkeleton innerKey="logs-table" columns={5} key="logs" />}
|
<Table>
|
||||||
{!isLoading && data?.auditLogs && data?.auditLogs.length === 0 && (
|
<THead>
|
||||||
<Tr>
|
<Tr>
|
||||||
<Td colSpan={5}>
|
<Th>Timestamp</Th>
|
||||||
<EmptyState
|
<Th>Event</Th>
|
||||||
title="No audit logs on file"
|
<Th>Actor</Th>
|
||||||
icon={faFile}
|
<Th>Source</Th>
|
||||||
/>
|
<Th>Metadata</Th>
|
||||||
</Td>
|
</Tr>
|
||||||
</Tr>
|
</THead>
|
||||||
)}
|
<TBody>
|
||||||
</TBody>
|
{!isLoading &&
|
||||||
</Table>
|
data?.pages?.map((group, i) => (
|
||||||
{!isLoading && data?.totalCount !== undefined && (
|
<Fragment key={`auditlog-item-${i + 1}`}>
|
||||||
<Pagination
|
{group.map((auditLog) => (
|
||||||
count={data?.totalCount}
|
<LogsTableRow auditLog={auditLog} key={`audit-log-${auditLog._id}`} />
|
||||||
page={page}
|
))}
|
||||||
perPage={perPage}
|
</Fragment>
|
||||||
onChangePage={(newPage) => setValue("page", newPage)}
|
))}
|
||||||
onChangePerPage={(newPerPage) => setValue("perPage", newPerPage)}
|
{isLoading && <TableSkeleton innerKey="logs-table" columns={5} key="logs" />}
|
||||||
/>
|
{isEmpty && (
|
||||||
|
<Tr>
|
||||||
|
<Td colSpan={5}>
|
||||||
|
<EmptyState title="No audit logs on file" icon={faFile} />
|
||||||
|
</Td>
|
||||||
|
</Tr>
|
||||||
)}
|
)}
|
||||||
</TableContainer>
|
</TBody>
|
||||||
);
|
</Table>
|
||||||
}
|
</TableContainer>
|
||||||
|
{!isEmpty && (
|
||||||
|
<Button
|
||||||
|
className="mt-4 mb-20 py-3 px-4 text-sm"
|
||||||
|
isFullWidth
|
||||||
|
variant="star"
|
||||||
|
isLoading={isFetchingNextPage}
|
||||||
|
isDisabled={isFetchingNextPage || !hasNextPage}
|
||||||
|
onClick={() => fetchNextPage()}
|
||||||
|
>
|
||||||
|
{hasNextPage ? "Load More" : "End of logs"}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user