From 5c4de03588c79c7cb214f16d69896dd8b623de01 Mon Sep 17 00:00:00 2001 From: Jacky Fong Date: Thu, 26 Feb 2026 03:46:35 +0800 Subject: [PATCH] add reset bandwidth api for site Change endpoint update to reset all site in the organization move the logic to organization move the permission to organization --- messages/en-US.json | 1 + server/auth/actions.ts | 1 + server/routers/integration.ts | 7 +++ server/routers/org/index.ts | 1 + server/routers/org/resetOrgBandwidth.ts | 83 +++++++++++++++++++++++++ src/components/PermissionsSelectBox.tsx | 1 + 6 files changed, 94 insertions(+) create mode 100644 server/routers/org/resetOrgBandwidth.ts diff --git a/messages/en-US.json b/messages/en-US.json index 68f9640b2..aa66e9ac1 100644 --- a/messages/en-US.json +++ b/messages/en-US.json @@ -1096,6 +1096,7 @@ "setupTokenDescription": "Enter the setup token from the server console.", "setupTokenRequired": "Setup token is required", "actionUpdateSite": "Update Site", + "actionResetSiteBandwidth": "Reset Organization Bandwidth", "actionListSiteRoles": "List Allowed Site Roles", "actionCreateResource": "Create Resource", "actionDeleteResource": "Delete Resource", diff --git a/server/auth/actions.ts b/server/auth/actions.ts index 094437f43..c3c543a43 100644 --- a/server/auth/actions.ts +++ b/server/auth/actions.ts @@ -19,6 +19,7 @@ export enum ActionsEnum { getSite = "getSite", listSites = "listSites", updateSite = "updateSite", + resetSiteBandwidth = "resetSiteBandwidth", reGenerateSecret = "reGenerateSecret", createResource = "createResource", deleteResource = "deleteResource", diff --git a/server/routers/integration.ts b/server/routers/integration.ts index 9ece5ddd0..c035a3506 100644 --- a/server/routers/integration.ts +++ b/server/routers/integration.ts @@ -134,6 +134,13 @@ authenticated.post( logActionAudit(ActionsEnum.updateSite), site.updateSite ); +authenticated.post( + "/org/:orgId/reset-bandwidth", + verifyApiKeyOrgAccess, + verifyApiKeyHasAction(ActionsEnum.resetSiteBandwidth), + logActionAudit(ActionsEnum.resetSiteBandwidth), + org.resetOrgBandwidth +); authenticated.delete( "/site/:siteId", diff --git a/server/routers/org/index.ts b/server/routers/org/index.ts index b0db28d14..c1aee7b33 100644 --- a/server/routers/org/index.ts +++ b/server/routers/org/index.ts @@ -8,3 +8,4 @@ export * from "./getOrgOverview"; export * from "./listOrgs"; export * from "./pickOrgDefaults"; export * from "./checkOrgUserAccess"; +export * from "./resetOrgBandwidth"; diff --git a/server/routers/org/resetOrgBandwidth.ts b/server/routers/org/resetOrgBandwidth.ts new file mode 100644 index 000000000..b98e2e406 --- /dev/null +++ b/server/routers/org/resetOrgBandwidth.ts @@ -0,0 +1,83 @@ +import { NextFunction, Request, Response } from "express"; +import { z } from "zod"; +import { db, 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"; +import logger from "@server/logger"; +import { fromError } from "zod-validation-error"; +import { OpenAPITags, registry } from "@server/openApi"; + +const resetOrgBandwidthParamsSchema = z.strictObject({ + orgId: z.string() +}); + +registry.registerPath({ + method: "post", + path: "/org/{orgId}/reset-bandwidth", + description: "Reset all sites in selected organization bandwidth counters.", + tags: [OpenAPITags.Org, OpenAPITags.Site], + request: { + params: resetOrgBandwidthParamsSchema + }, + responses: {} +}); + +export async function resetOrgBandwidth( + req: Request, + res: Response, + next: NextFunction +): Promise { + try { + const parsedParams = resetOrgBandwidthParamsSchema.safeParse( + req.params + ); + if (!parsedParams.success) { + return next( + createHttpError( + HttpCode.BAD_REQUEST, + fromError(parsedParams.error).toString() + ) + ); + } + + const { orgId } = parsedParams.data; + + const [site] = await db + .select({ siteId: sites.siteId }) + .from(sites) + .where(eq(sites.orgId, orgId)) + .limit(1); + + if (!site) { + return next( + createHttpError( + HttpCode.NOT_FOUND, + `No sites found in org ${orgId}` + ) + ); + } + + await db + .update(sites) + .set({ + megabytesIn: 0, + megabytesOut: 0 + }) + .where(eq(sites.orgId, orgId)); + + return response(res, { + data: {}, + success: true, + error: false, + message: "Sites bandwidth reset successfully", + status: HttpCode.OK + }); + } catch (error) { + logger.error(error); + return next( + createHttpError(HttpCode.INTERNAL_SERVER_ERROR, "An error occurred") + ); + } +} diff --git a/src/components/PermissionsSelectBox.tsx b/src/components/PermissionsSelectBox.tsx index b11c635a6..4e3b61ab0 100644 --- a/src/components/PermissionsSelectBox.tsx +++ b/src/components/PermissionsSelectBox.tsx @@ -26,6 +26,7 @@ function getActionsCategories(root: boolean) { [t("actionGetOrg")]: "getOrg", [t("actionUpdateOrg")]: "updateOrg", [t("actionGetOrgUser")]: "getOrgUser", + [t("actionResetSiteBandwidth")]: "resetSiteBandwidth", [t("actionInviteUser")]: "inviteUser", [t("actionRemoveInvitation")]: "removeInvitation", [t("actionListInvitations")]: "listInvitations",