mirror of
https://github.com/fosrl/pangolin.git
synced 2026-06-05 15:26:35 +00:00
Merge branch 'main' into dev
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { logsDb, requestAuditLog, driver, primaryLogsDb } from "@server/db";
|
||||
import { logsDb, requestAuditLog, driver } from "@server/db";
|
||||
import { registry } from "@server/openApi";
|
||||
import { NextFunction } from "express";
|
||||
import { Request, Response } from "express";
|
||||
@@ -74,12 +74,12 @@ async function query(query: Q) {
|
||||
);
|
||||
}
|
||||
|
||||
const [all] = await primaryLogsDb
|
||||
const [all] = await logsDb
|
||||
.select({ total: count() })
|
||||
.from(requestAuditLog)
|
||||
.where(baseConditions);
|
||||
|
||||
const [blocked] = await primaryLogsDb
|
||||
const [blocked] = await logsDb
|
||||
.select({ total: count() })
|
||||
.from(requestAuditLog)
|
||||
.where(and(baseConditions, eq(requestAuditLog.action, false)));
|
||||
@@ -90,7 +90,7 @@ async function query(query: Q) {
|
||||
|
||||
const DISTINCT_LIMIT = 500;
|
||||
|
||||
const requestsPerCountry = await primaryLogsDb
|
||||
const requestsPerCountry = await logsDb
|
||||
.selectDistinct({
|
||||
code: requestAuditLog.location,
|
||||
count: totalQ
|
||||
@@ -118,7 +118,7 @@ async function query(query: Q) {
|
||||
const booleanTrue = driver === "pg" ? sql`true` : sql`1`;
|
||||
const booleanFalse = driver === "pg" ? sql`false` : sql`0`;
|
||||
|
||||
const requestsPerDay = await primaryLogsDb
|
||||
const requestsPerDay = await logsDb
|
||||
.select({
|
||||
day: groupByDayFunction.as("day"),
|
||||
allowedCount:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { logsDb, primaryLogsDb, requestAuditLog, resources, siteResources, db, primaryDb } from "@server/db";
|
||||
import { logsDb, requestAuditLog, resources, siteResources, db, primaryDb } from "@server/db";
|
||||
import { registry } from "@server/openApi";
|
||||
import { NextFunction } from "express";
|
||||
import { Request, Response } from "express";
|
||||
@@ -110,7 +110,7 @@ function getWhere(data: Q) {
|
||||
}
|
||||
|
||||
export function queryRequest(data: Q) {
|
||||
return primaryLogsDb
|
||||
return logsDb
|
||||
.select({
|
||||
id: requestAuditLog.id,
|
||||
timestamp: requestAuditLog.timestamp,
|
||||
@@ -211,7 +211,7 @@ async function enrichWithResourceDetails(logs: Awaited<ReturnType<typeof queryRe
|
||||
}
|
||||
|
||||
export function countRequestQuery(data: Q) {
|
||||
const countQuery = primaryLogsDb
|
||||
const countQuery = logsDb
|
||||
.select({ count: count() })
|
||||
.from(requestAuditLog)
|
||||
.where(getWhere(data));
|
||||
@@ -254,34 +254,34 @@ async function queryUniqueFilterAttributes(
|
||||
uniqueResources,
|
||||
uniqueSiteResources
|
||||
] = await Promise.all([
|
||||
primaryLogsDb
|
||||
logsDb
|
||||
.selectDistinct({ actor: requestAuditLog.actor })
|
||||
.from(requestAuditLog)
|
||||
.where(baseConditions)
|
||||
.limit(DISTINCT_LIMIT + 1),
|
||||
primaryLogsDb
|
||||
logsDb
|
||||
.selectDistinct({ locations: requestAuditLog.location })
|
||||
.from(requestAuditLog)
|
||||
.where(baseConditions)
|
||||
.limit(DISTINCT_LIMIT + 1),
|
||||
primaryLogsDb
|
||||
logsDb
|
||||
.selectDistinct({ hosts: requestAuditLog.host })
|
||||
.from(requestAuditLog)
|
||||
.where(baseConditions)
|
||||
.limit(DISTINCT_LIMIT + 1),
|
||||
primaryLogsDb
|
||||
logsDb
|
||||
.selectDistinct({ paths: requestAuditLog.path })
|
||||
.from(requestAuditLog)
|
||||
.where(baseConditions)
|
||||
.limit(DISTINCT_LIMIT + 1),
|
||||
primaryLogsDb
|
||||
logsDb
|
||||
.selectDistinct({
|
||||
id: requestAuditLog.resourceId
|
||||
})
|
||||
.from(requestAuditLog)
|
||||
.where(baseConditions)
|
||||
.limit(DISTINCT_LIMIT + 1),
|
||||
primaryLogsDb
|
||||
logsDb
|
||||
.selectDistinct({
|
||||
id: requestAuditLog.siteResourceId
|
||||
})
|
||||
|
||||
@@ -1156,7 +1156,7 @@ export const authRouter = Router();
|
||||
unauthenticated.use("/auth", authRouter);
|
||||
authRouter.use(
|
||||
rateLimit({
|
||||
windowMs: config.getRawConfig().rate_limits.auth.window_minutes,
|
||||
windowMs: config.getRawConfig().rate_limits.auth.window_minutes * 60 * 1000,
|
||||
max: config.getRawConfig().rate_limits.auth.max_requests,
|
||||
keyGenerator: (req) =>
|
||||
`authRouterGlobal:${ipKeyGenerator(req.ip || "")}:${req.path}`,
|
||||
@@ -1252,7 +1252,7 @@ authRouter.post(
|
||||
windowMs: 15 * 60 * 1000,
|
||||
max: 900,
|
||||
keyGenerator: (req) =>
|
||||
`olmGetToken:${req.body.newtId || ipKeyGenerator(req.ip || "")}`,
|
||||
`olmGetToken:${req.body.olmId || ipKeyGenerator(req.ip || "")}`,
|
||||
handler: (req, res, next) => {
|
||||
const message = `You can only request an Olm token ${900} times every ${15} minutes. Please try again later.`;
|
||||
return next(createHttpError(HttpCode.TOO_MANY_REQUESTS, message));
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Request, Response, NextFunction } from "express";
|
||||
import { z } from "zod";
|
||||
import { db, Site, siteNetworks, siteResources } from "@server/db";
|
||||
import { newts, newtSessions, sites } from "@server/db";
|
||||
import { eq, inArray } from "drizzle-orm";
|
||||
import { db } from "@server/db";
|
||||
import { newts, sites } from "@server/db";
|
||||
import { eq } from "drizzle-orm";
|
||||
import response from "@server/lib/response";
|
||||
import HttpCode from "@server/types/HttpCode";
|
||||
import createHttpError from "http-errors";
|
||||
@@ -11,7 +11,7 @@ import { deletePeer } from "../gerbil/peers";
|
||||
import { fromError } from "zod-validation-error";
|
||||
import { sendToClient } from "#dynamic/routers/ws";
|
||||
import { OpenAPITags, registry } from "@server/openApi";
|
||||
import { rebuildClientAssociationsFromSiteResource } from "@server/lib/rebuildClientAssociations";
|
||||
import { cleanupSiteAssociations } from "@server/lib/rebuildClientAssociations";
|
||||
import { usageService } from "@server/lib/billing/usageService";
|
||||
import { FeatureId } from "@server/lib/billing";
|
||||
|
||||
@@ -63,7 +63,11 @@ export async function deleteSite(
|
||||
);
|
||||
}
|
||||
|
||||
let deletedNewtId: string | null = null;
|
||||
const [deletedNewt] = await db
|
||||
.select()
|
||||
.from(newts)
|
||||
.where(eq(newts.siteId, siteId))
|
||||
.limit(1);
|
||||
|
||||
await db.transaction(async (trx) => {
|
||||
if (site.type == "wireguard") {
|
||||
@@ -71,56 +75,24 @@ export async function deleteSite(
|
||||
await deletePeer(site.exitNodeId!, site.pubKey);
|
||||
}
|
||||
} else if (site.type == "newt") {
|
||||
const networks = await trx
|
||||
.select({ networkId: siteNetworks.networkId })
|
||||
.from(siteNetworks)
|
||||
.where(eq(siteNetworks.siteId, siteId));
|
||||
// Clean up all client associations and send peer/proxy removal
|
||||
// messages in a single efficient pass before deleting the row.
|
||||
await cleanupSiteAssociations(site, trx);
|
||||
|
||||
// loop through them
|
||||
const updatedSiteResources = await trx
|
||||
.select()
|
||||
.from(siteResources)
|
||||
.where(
|
||||
inArray(
|
||||
siteResources.networkId,
|
||||
networks.map((n) => n.networkId)
|
||||
)
|
||||
);
|
||||
for (const siteResource of updatedSiteResources) {
|
||||
await rebuildClientAssociationsFromSiteResource(
|
||||
siteResource,
|
||||
trx
|
||||
);
|
||||
}
|
||||
|
||||
// get the newt on the site by querying the newt table for siteId
|
||||
const [deletedNewt] = await trx
|
||||
.delete(newts)
|
||||
.where(eq(newts.siteId, siteId))
|
||||
.returning();
|
||||
if (deletedNewt) {
|
||||
deletedNewtId = deletedNewt.newtId;
|
||||
|
||||
// delete all of the sessions for the newt
|
||||
await trx
|
||||
.delete(newtSessions)
|
||||
.where(eq(newtSessions.newtId, deletedNewt.newtId));
|
||||
}
|
||||
await trx.delete(sites).where(eq(sites.siteId, siteId));
|
||||
}
|
||||
|
||||
await trx.delete(sites).where(eq(sites.siteId, siteId));
|
||||
|
||||
await usageService.add(site.orgId, FeatureId.SITES, -1, trx);
|
||||
});
|
||||
|
||||
// Send termination message outside of transaction to prevent blocking
|
||||
if (deletedNewtId) {
|
||||
if (deletedNewt) {
|
||||
const payload = {
|
||||
type: `newt/wg/terminate`,
|
||||
data: {}
|
||||
};
|
||||
// Don't await this to prevent blocking the response
|
||||
sendToClient(deletedNewtId, payload).catch((error) => {
|
||||
sendToClient(deletedNewt.newtId, payload).catch((error) => {
|
||||
logger.error(
|
||||
"Failed to send termination message to newt:",
|
||||
error
|
||||
|
||||
@@ -15,10 +15,7 @@ import logger from "@server/logger";
|
||||
import { fromError } from "zod-validation-error";
|
||||
import { eq, and, inArray } from "drizzle-orm";
|
||||
import { OpenAPITags, registry } from "@server/openApi";
|
||||
import {
|
||||
rebuildClientAssociationsFromClient,
|
||||
rebuildClientAssociationsFromSiteResource
|
||||
} from "@server/lib/rebuildClientAssociations";
|
||||
import { rebuildClientAssociationsFromClient } from "@server/lib/rebuildClientAssociations";
|
||||
|
||||
const batchAddClientToSiteResourcesParamsSchema = z
|
||||
.object({
|
||||
|
||||
Reference in New Issue
Block a user