@paroicms/server 1.106.0 → 1.107.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,3 @@
1
+ import type { GqlResolvers } from "../../graphql/generated-graphql-types.d.ts";
2
+ import { type GraphqlContext } from "../../graphql/graphql.types.js";
3
+ export declare const loggingResolvers: GqlResolvers<GraphqlContext>;
@@ -0,0 +1,40 @@
1
+ import { siteReadyGuard } from "../../graphql/graphql.types.js";
2
+ import { authGuard } from "../auth/auth.helper.js";
3
+ import { checkRateLimit } from "./naive-rate-limiter.js";
4
+ const validLogLevels = new Set(["error", "warn", "info", "trace", "debug"]);
5
+ export const loggingResolvers = {
6
+ Mutation: {
7
+ saveLog: async (_parent, { lines }, { siteContext, httpContext }) => {
8
+ const payload = authGuard(httpContext);
9
+ siteReadyGuard(siteContext);
10
+ const sessionId = payload.id;
11
+ checkRateLimit(sessionId);
12
+ for (const line of lines) {
13
+ if (!validLogLevels.has(line.level)) {
14
+ siteContext.logger.warn(`[Admin-UI] Invalid log level: ${line.level}`);
15
+ continue;
16
+ }
17
+ const prefixedMessage = `[Admin-UI] ${line.message}`;
18
+ switch (line.level) {
19
+ case "error":
20
+ siteContext.logger.error(prefixedMessage);
21
+ break;
22
+ case "warn":
23
+ siteContext.logger.warn(prefixedMessage);
24
+ break;
25
+ case "info":
26
+ siteContext.logger.info(prefixedMessage);
27
+ break;
28
+ case "trace":
29
+ siteContext.logger.trace(prefixedMessage);
30
+ break;
31
+ case "debug":
32
+ siteContext.logger.debug(prefixedMessage);
33
+ break;
34
+ }
35
+ }
36
+ return true;
37
+ },
38
+ },
39
+ };
40
+ //# sourceMappingURL=logging.resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logging.resolver.js","sourceRoot":"","sources":["../../../src/admin-backend/logging/logging.resolver.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAuB,MAAM,gCAAgC,CAAC;AACrF,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAEzD,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;AAE5E,MAAM,CAAC,MAAM,gBAAgB,GAAiC;IAC5D,QAAQ,EAAE;QACR,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,WAAW,EAAE,WAAW,EAAE,EAAE,EAAE;YAClE,MAAM,OAAO,GAAG,SAAS,CAAC,WAAW,CAAC,CAAC;YACvC,cAAc,CAAC,WAAW,CAAC,CAAC;YAE5B,MAAM,SAAS,GAAG,OAAO,CAAC,EAAE,CAAC;YAC7B,cAAc,CAAC,SAAS,CAAC,CAAC;YAE1B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;oBACpC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,iCAAiC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;oBACvE,SAAS;gBACX,CAAC;gBAED,MAAM,eAAe,GAAG,cAAc,IAAI,CAAC,OAAO,EAAE,CAAC;gBAErD,QAAQ,IAAI,CAAC,KAAK,EAAE,CAAC;oBACnB,KAAK,OAAO;wBACV,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;wBAC1C,MAAM;oBACR,KAAK,MAAM;wBACT,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;wBACzC,MAAM;oBACR,KAAK,MAAM;wBACT,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;wBACzC,MAAM;oBACR,KAAK,OAAO;wBACV,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;wBAC1C,MAAM;oBACR,KAAK,OAAO;wBACV,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;wBAC1C,MAAM;gBACV,CAAC;YACH,CAAC;YAED,OAAO,IAAI,CAAC;QACd,CAAC;KACF;CACF,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function checkRateLimit(sessionId: string): void;
@@ -0,0 +1,37 @@
1
+ import { ApiError } from "@paroicms/public-server-lib";
2
+ const rateLimitMap = new Map();
3
+ const INITIAL_LIMIT = 50;
4
+ const WINDOW_LIMIT = 10;
5
+ const WINDOW_DURATION = 30000;
6
+ setInterval(() => {
7
+ const now = Date.now();
8
+ const expiredThreshold = now - WINDOW_DURATION * 2;
9
+ for (const [sessionId, entry] of rateLimitMap.entries()) {
10
+ if (entry.windowStart < expiredThreshold) {
11
+ rateLimitMap.delete(sessionId);
12
+ }
13
+ }
14
+ }, WINDOW_DURATION * 3).unref();
15
+ export function checkRateLimit(sessionId) {
16
+ const now = Date.now();
17
+ const entry = rateLimitMap.get(sessionId);
18
+ if (!entry) {
19
+ rateLimitMap.set(sessionId, { count: 1, windowStart: now });
20
+ return;
21
+ }
22
+ if (entry.count < INITIAL_LIMIT) {
23
+ ++entry.count;
24
+ return;
25
+ }
26
+ const timeSinceWindowStart = now - entry.windowStart;
27
+ if (timeSinceWindowStart >= WINDOW_DURATION) {
28
+ entry.count = 1;
29
+ entry.windowStart = now;
30
+ return;
31
+ }
32
+ if (entry.count >= WINDOW_LIMIT) {
33
+ throw new ApiError("Rate limit exceeded", 400);
34
+ }
35
+ ++entry.count;
36
+ }
37
+ //# sourceMappingURL=naive-rate-limiter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"naive-rate-limiter.js","sourceRoot":"","sources":["../../../src/admin-backend/logging/naive-rate-limiter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAQvD,MAAM,YAAY,GAAG,IAAI,GAAG,EAA0B,CAAC;AACvD,MAAM,aAAa,GAAG,EAAE,CAAC;AACzB,MAAM,YAAY,GAAG,EAAE,CAAC;AACxB,MAAM,eAAe,GAAG,KAAK,CAAC;AAG9B,WAAW,CAAC,GAAG,EAAE;IACf,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,MAAM,gBAAgB,GAAG,GAAG,GAAG,eAAe,GAAG,CAAC,CAAC;IAEnD,KAAK,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,YAAY,CAAC,OAAO,EAAE,EAAE,CAAC;QACxD,IAAI,KAAK,CAAC,WAAW,GAAG,gBAAgB,EAAE,CAAC;YACzC,YAAY,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;AACH,CAAC,EAAE,eAAe,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;AAEhC,MAAM,UAAU,cAAc,CAAC,SAAiB;IAC9C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,MAAM,KAAK,GAAG,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAE1C,IAAI,CAAC,KAAK,EAAE,CAAC;QAEX,YAAY,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC,CAAC;QAC5D,OAAO;IACT,CAAC;IAED,IAAI,KAAK,CAAC,KAAK,GAAG,aAAa,EAAE,CAAC;QAEhC,EAAE,KAAK,CAAC,KAAK,CAAC;QACd,OAAO;IACT,CAAC;IAGD,MAAM,oBAAoB,GAAG,GAAG,GAAG,KAAK,CAAC,WAAW,CAAC;IAErD,IAAI,oBAAoB,IAAI,eAAe,EAAE,CAAC;QAE5C,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC;QAChB,KAAK,CAAC,WAAW,GAAG,GAAG,CAAC;QACxB,OAAO;IACT,CAAC;IAED,IAAI,KAAK,CAAC,KAAK,IAAI,YAAY,EAAE,CAAC;QAChC,MAAM,IAAI,QAAQ,CAAC,qBAAqB,EAAE,GAAG,CAAC,CAAC;IACjD,CAAC;IAED,EAAE,KAAK,CAAC,KAAK,CAAC;AAChB,CAAC"}
@@ -6,6 +6,7 @@ import { extendWithDocumentResolver } from "../admin-backend/document/document.r
6
6
  import { documentResolvers } from "../admin-backend/document/document.resolver.js";
7
7
  import { extendLNodeWrapWithFieldValuesResolvers, extendPartWithFieldValuesResolver, fieldResolvers, } from "../admin-backend/fields/fields.resolver.js";
8
8
  import { lNodeWrapResolvers } from "../admin-backend/lnode/lnode-wrap.resolver.js";
9
+ import { loggingResolvers } from "../admin-backend/logging/logging.resolver.js";
9
10
  import { extendDocumentWithMediaResolver } from "../admin-backend/media/media.resolver.extend.js";
10
11
  import { mediaResolvers } from "../admin-backend/media/media.resolver.js";
11
12
  import { migrationResolvers } from "../admin-backend/migration/migration.resolver.js";
@@ -40,6 +41,7 @@ export function federateResolvers() {
40
41
  unprotectedResolvers,
41
42
  scalarTypeResolvers,
42
43
  extendDocumentWithMediaResolver,
44
+ loggingResolvers,
43
45
  ];
44
46
  }
45
47
  //# sourceMappingURL=apollo-server-init.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"apollo-server-init.js","sourceRoot":"","sources":["../../src/graphql/apollo-server-init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,gBAAgB,EAAE,MAAM,8CAA8C,CAAC;AAChF,OAAO,EAAE,eAAe,EAAE,MAAM,4CAA4C,CAAC;AAC7E,OAAO,EAAE,0BAA0B,EAAE,MAAM,uDAAuD,CAAC;AACnG,OAAO,EAAE,iBAAiB,EAAE,MAAM,gDAAgD,CAAC;AACnF,OAAO,EACL,uCAAuC,EACvC,iCAAiC,EACjC,cAAc,GACf,MAAM,4CAA4C,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,+CAA+C,CAAC;AACnF,OAAO,EAAE,+BAA+B,EAAE,MAAM,iDAAiD,CAAC;AAClG,OAAO,EAAE,cAAc,EAAE,MAAM,0CAA0C,CAAC;AAC1E,OAAO,EAAE,kBAAkB,EAAE,MAAM,kDAAkD,CAAC;AACtF,OAAO,EAAE,+BAA+B,EAAE,MAAM,+CAA+C,CAAC;AAChG,OAAO,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAC;AACvE,OAAO,EAAE,gCAAgC,EAAE,MAAM,+CAA+C,CAAC;AACjG,OAAO,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAC;AACvE,OAAO,EAAE,uBAAuB,EAAE,MAAM,8DAA8D,CAAC;AACvG,OAAO,EAAE,sBAAsB,EAAE,MAAM,4DAA4D,CAAC;AACpG,OAAO,EAAE,oBAAoB,EAAE,MAAM,sDAAsD,CAAC;AAC5F,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,MAAM,2CAA2C,CAAC;AAIhF,MAAM,CAAC,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,UAAU,EAAE,gBAAgB,CAAC,EAAE,MAAM,CAAC,CAAC;AAEjF,MAAM,UAAU,iBAAiB;IAC/B,OAAO;QACL,gBAAgB;QAChB,eAAe;QACf,kBAAkB;QAClB,iBAAiB;QACjB,0BAA0B;QAC1B,cAAc;QACd,uCAAuC;QACvC,iCAAiC;QACjC,aAAa;QACb,+BAA+B;QAC/B,cAAc;QACd,aAAa;QACb,gCAAgC;QAChC,kBAAkB;QAClB,uBAAuB;QACvB,sBAAsB;QACtB,oBAAoB;QACpB,mBAAmB;QACnB,+BAA+B;KAChC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"apollo-server-init.js","sourceRoot":"","sources":["../../src/graphql/apollo-server-init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,gBAAgB,EAAE,MAAM,8CAA8C,CAAC;AAChF,OAAO,EAAE,eAAe,EAAE,MAAM,4CAA4C,CAAC;AAC7E,OAAO,EAAE,0BAA0B,EAAE,MAAM,uDAAuD,CAAC;AACnG,OAAO,EAAE,iBAAiB,EAAE,MAAM,gDAAgD,CAAC;AACnF,OAAO,EACL,uCAAuC,EACvC,iCAAiC,EACjC,cAAc,GACf,MAAM,4CAA4C,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,+CAA+C,CAAC;AACnF,OAAO,EAAE,gBAAgB,EAAE,MAAM,8CAA8C,CAAC;AAChF,OAAO,EAAE,+BAA+B,EAAE,MAAM,iDAAiD,CAAC;AAClG,OAAO,EAAE,cAAc,EAAE,MAAM,0CAA0C,CAAC;AAC1E,OAAO,EAAE,kBAAkB,EAAE,MAAM,kDAAkD,CAAC;AACtF,OAAO,EAAE,+BAA+B,EAAE,MAAM,+CAA+C,CAAC;AAChG,OAAO,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAC;AACvE,OAAO,EAAE,gCAAgC,EAAE,MAAM,+CAA+C,CAAC;AACjG,OAAO,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAC;AACvE,OAAO,EAAE,uBAAuB,EAAE,MAAM,8DAA8D,CAAC;AACvG,OAAO,EAAE,sBAAsB,EAAE,MAAM,4DAA4D,CAAC;AACpG,OAAO,EAAE,oBAAoB,EAAE,MAAM,sDAAsD,CAAC;AAC5F,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,MAAM,2CAA2C,CAAC;AAIhF,MAAM,CAAC,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,UAAU,EAAE,gBAAgB,CAAC,EAAE,MAAM,CAAC,CAAC;AAEjF,MAAM,UAAU,iBAAiB;IAC/B,OAAO;QACL,gBAAgB;QAChB,eAAe;QACf,kBAAkB;QAClB,iBAAiB;QACjB,0BAA0B;QAC1B,cAAc;QACd,uCAAuC;QACvC,iCAAiC;QACjC,aAAa;QACb,+BAA+B;QAC/B,cAAc;QACd,aAAa;QACb,gCAAgC;QAChC,kBAAkB;QAClB,uBAAuB;QACvB,sBAAsB;QACtB,oBAAoB;QACpB,mBAAmB;QACnB,+BAA+B;QAC/B,gBAAgB;KACjB,CAAC;AACJ,CAAC"}