mirror of
https://github.com/fosrl/pangolin.git
synced 2026-01-28 22:00:51 +00:00
Working on settings
This commit is contained in:
@@ -26,7 +26,16 @@ export const orgs = pgTable("orgs", {
|
||||
orgId: varchar("orgId").primaryKey(),
|
||||
name: varchar("name").notNull(),
|
||||
subnet: varchar("subnet"),
|
||||
createdAt: text("createdAt")
|
||||
createdAt: text("createdAt"),
|
||||
settingsLogRetentionDaysRequest: integer("settingsLogRetentionDaysRequest") // where 0 = dont keep logs and -1 = keep forever
|
||||
.notNull()
|
||||
.default(15),
|
||||
settingsLogRetentionDaysAccess: integer("settingsLogRetentionDaysAccess")
|
||||
.notNull()
|
||||
.default(15),
|
||||
settingsLogRetentionDaysAction: integer("settingsLogRetentionDaysAction")
|
||||
.notNull()
|
||||
.default(15),
|
||||
});
|
||||
|
||||
export const orgDomains = pgTable("orgDomains", {
|
||||
@@ -676,8 +685,9 @@ export const requestAuditLog = pgTable(
|
||||
{
|
||||
id: serial("id").primaryKey(),
|
||||
timestamp: integer("timestamp").notNull(), // this is EPOCH time in seconds
|
||||
orgId: text("orgId")
|
||||
.references(() => orgs.orgId, { onDelete: "cascade" }),
|
||||
orgId: text("orgId").references(() => orgs.orgId, {
|
||||
onDelete: "cascade"
|
||||
}),
|
||||
action: boolean("action").notNull(),
|
||||
reason: integer("reason").notNull(),
|
||||
actorType: text("actorType"),
|
||||
|
||||
@@ -19,7 +19,16 @@ export const orgs = sqliteTable("orgs", {
|
||||
orgId: text("orgId").primaryKey(),
|
||||
name: text("name").notNull(),
|
||||
subnet: text("subnet"),
|
||||
createdAt: text("createdAt")
|
||||
createdAt: text("createdAt"),
|
||||
settingsLogRetentionDaysRequest: integer("settingsLogRetentionDaysRequest") // where 0 = dont keep logs and -1 = keep forever
|
||||
.notNull()
|
||||
.default(15),
|
||||
settingsLogRetentionDaysAccess: integer("settingsLogRetentionDaysAccess")
|
||||
.notNull()
|
||||
.default(15),
|
||||
settingsLogRetentionDaysAction: integer("settingsLogRetentionDaysAction")
|
||||
.notNull()
|
||||
.default(15)
|
||||
});
|
||||
|
||||
export const userDomains = sqliteTable("userDomains", {
|
||||
@@ -721,8 +730,9 @@ export const requestAuditLog = sqliteTable(
|
||||
{
|
||||
id: integer("id").primaryKey({ autoIncrement: true }),
|
||||
timestamp: integer("timestamp").notNull(), // this is EPOCH time in seconds
|
||||
orgId: text("orgId")
|
||||
.references(() => orgs.orgId, { onDelete: "cascade" }),
|
||||
orgId: text("orgId").references(() => orgs.orgId, {
|
||||
onDelete: "cascade"
|
||||
}),
|
||||
action: integer("action", { mode: "boolean" }).notNull(),
|
||||
reason: integer("reason").notNull(),
|
||||
actorType: text("actorType"),
|
||||
|
||||
@@ -1,11 +1,32 @@
|
||||
import { accessAuditLog, db } from "@server/db";
|
||||
import { accessAuditLog, db, orgs } from "@server/db";
|
||||
import { getCountryCodeForIp } from "@server/lib/geoip";
|
||||
import logger from "@server/logger";
|
||||
import NodeCache from "node-cache";
|
||||
import { eq } from "drizzle-orm";
|
||||
|
||||
const cache = new NodeCache({
|
||||
stdTTL: 5 // seconds
|
||||
});
|
||||
async function getAccessDays(orgId: string): Promise<number> {
|
||||
// check cache first
|
||||
const cached = cache.get<number>(`org_${orgId}_accessDays`);
|
||||
if (cached !== undefined) {
|
||||
return cached;
|
||||
}
|
||||
|
||||
const [org] = await db
|
||||
.select({
|
||||
settingsLogRetentionDaysAction: orgs.settingsLogRetentionDaysAction
|
||||
})
|
||||
.from(orgs)
|
||||
.where(eq(orgs.orgId, orgId))
|
||||
.limit(1);
|
||||
|
||||
if (!org) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// store the result in cache
|
||||
cache.set(`org_${orgId}_accessDays`, org.settingsLogRetentionDaysAction);
|
||||
|
||||
return org.settingsLogRetentionDaysAction;
|
||||
}
|
||||
|
||||
export async function logAccessAudit(data: {
|
||||
action: boolean;
|
||||
|
||||
@@ -12,11 +12,39 @@
|
||||
*/
|
||||
|
||||
import { ActionsEnum } from "@server/auth/actions";
|
||||
import { actionAuditLog, db } from "@server/db";
|
||||
import { actionAuditLog, db, orgs } from "@server/db";
|
||||
import logger from "@server/logger";
|
||||
import HttpCode from "@server/types/HttpCode";
|
||||
import { Request, Response, NextFunction } from "express";
|
||||
import createHttpError from "http-errors";
|
||||
import NodeCache from "node-cache";
|
||||
import { eq } from "drizzle-orm";
|
||||
|
||||
const cache = new NodeCache({ stdTTL: 300 }); // cache for 5 minutes
|
||||
async function getActionDays(orgId: string): Promise<number> {
|
||||
// check cache first
|
||||
const cached = cache.get<number>(`org_${orgId}_actionDays`);
|
||||
if (cached !== undefined) {
|
||||
return cached;
|
||||
}
|
||||
|
||||
const [org] = await db
|
||||
.select({
|
||||
settingsLogRetentionDaysAction: orgs.settingsLogRetentionDaysAction
|
||||
})
|
||||
.from(orgs)
|
||||
.where(eq(orgs.orgId, orgId))
|
||||
.limit(1);
|
||||
|
||||
if (!org) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// store the result in cache
|
||||
cache.set(`org_${orgId}_actionDays`, org.settingsLogRetentionDaysAction);
|
||||
|
||||
return org.settingsLogRetentionDaysAction;
|
||||
}
|
||||
|
||||
export function logActionAudit(action: ActionsEnum) {
|
||||
return async function (
|
||||
@@ -57,6 +85,12 @@ export function logActionAudit(action: ActionsEnum) {
|
||||
return next();
|
||||
}
|
||||
|
||||
const retentionDays = await getActionDays(orgId);
|
||||
if (retentionDays === 0) {
|
||||
// do not log
|
||||
return next();
|
||||
}
|
||||
|
||||
const timestamp = Math.floor(Date.now() / 1000);
|
||||
|
||||
let metadata = null;
|
||||
@@ -86,3 +120,4 @@ export function logActionAudit(action: ActionsEnum) {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { db, requestAuditLog } from "@server/db";
|
||||
import { db, orgs, requestAuditLog } from "@server/db";
|
||||
import logger from "@server/logger";
|
||||
import { eq } from "drizzle-orm";
|
||||
import NodeCache from "node-cache";
|
||||
|
||||
/**
|
||||
|
||||
@@ -22,6 +24,32 @@ Reasons:
|
||||
|
||||
*/
|
||||
|
||||
const cache = new NodeCache({ stdTTL: 300 }); // cache for 5 minutes
|
||||
async function getRetentionDays(orgId: string): Promise<number> {
|
||||
// check cache first
|
||||
const cached = cache.get<number>(`org_${orgId}_retentionDays`);
|
||||
if (cached !== undefined) {
|
||||
return cached;
|
||||
}
|
||||
|
||||
const [org] = await db
|
||||
.select({
|
||||
settingsLogRetentionDaysRequest: orgs.settingsLogRetentionDaysRequest
|
||||
})
|
||||
.from(orgs)
|
||||
.where(eq(orgs.orgId, orgId))
|
||||
.limit(1);
|
||||
|
||||
if (!org) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// store the result in cache
|
||||
cache.set(`org_${orgId}_retentionDays`, org.settingsLogRetentionDaysRequest);
|
||||
|
||||
return org.settingsLogRetentionDaysRequest;
|
||||
}
|
||||
|
||||
export async function logRequestAudit(
|
||||
data: {
|
||||
action: boolean;
|
||||
@@ -29,8 +57,8 @@ export async function logRequestAudit(
|
||||
resourceId?: number;
|
||||
orgId?: string;
|
||||
location?: string;
|
||||
user?: { username: string; userId: string; };
|
||||
apiKey?: { name: string | null; apiKeyId: string; };
|
||||
user?: { username: string; userId: string };
|
||||
apiKey?: { name: string | null; apiKeyId: string };
|
||||
metadata?: any;
|
||||
// userAgent?: string;
|
||||
},
|
||||
@@ -43,11 +71,20 @@ export async function logRequestAudit(
|
||||
tls: boolean;
|
||||
sessions?: Record<string, string>;
|
||||
headers?: Record<string, string>;
|
||||
query?: Record<string, string>;
|
||||
query?: Record<string, string>;
|
||||
requestIp?: string;
|
||||
}
|
||||
) {
|
||||
try {
|
||||
|
||||
if (data.orgId) {
|
||||
const retentionDays = await getRetentionDays(data.orgId);
|
||||
if (retentionDays === 0) {
|
||||
// do not log
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let actorType: string | undefined;
|
||||
let actor: string | undefined;
|
||||
let actorId: string | undefined;
|
||||
@@ -79,7 +116,10 @@ export async function logRequestAudit(
|
||||
|
||||
const clientIp = body.requestIp
|
||||
? (() => {
|
||||
if (body.requestIp.startsWith("[") && body.requestIp.includes("]")) {
|
||||
if (
|
||||
body.requestIp.startsWith("[") &&
|
||||
body.requestIp.includes("]")
|
||||
) {
|
||||
// if brackets are found, extract the IPv6 address from between the brackets
|
||||
const ipv6Match = body.requestIp.match(/\[(.*?)\]/);
|
||||
if (ipv6Match) {
|
||||
|
||||
Reference in New Issue
Block a user