diff --git a/apps/nextjs/src/components/board/sections/gridstack/use-gridstack.ts b/apps/nextjs/src/components/board/sections/gridstack/use-gridstack.ts index 18a5a1dc0..74a891d07 100644 --- a/apps/nextjs/src/components/board/sections/gridstack/use-gridstack.ts +++ b/apps/nextjs/src/components/board/sections/gridstack/use-gridstack.ts @@ -319,23 +319,29 @@ const useCssVariableConfiguration = ({ columnCount, isDynamic, }: UseCssVariableConfiguration) => { - const prevWidthRef = useRef(null); + const prevSizeRef = useRef<{ width: number; height: number } | null>(null); const onResize = useCallback(() => { if (!wrapperRef.current) return; if (!gridRef.current) return; const currentWidth = wrapperRef.current.clientWidth; - const prevWidth = prevWidthRef.current; + const currentHeight = wrapperRef.current.clientHeight; + const prevSize = prevSizeRef.current; - // Only recalculate if the width change is significant enough (> 20px) - // This prevents infinite feedback loops when the vertical scrollbar - // appears/disappears, causing clientWidth to oscillate by ~15px - if (prevWidth !== null && Math.abs(currentWidth - prevWidth) < 20) { + // Only skip recalculation when the width change is insignificant (< 20px) + // and, for dynamic sections, the height is unchanged. This prevents infinite + // feedback loops when the vertical scrollbar appears/disappears, causing + // clientWidth to oscillate by ~15px, while still reacting to height changes. + if ( + prevSize !== null && + Math.abs(currentWidth - prevSize.width) < 20 && + (!isDynamic || currentHeight === prevSize.height) + ) { return; } - prevWidthRef.current = currentWidth; + prevSizeRef.current = { width: currentWidth, height: currentHeight }; handleResizeChange( wrapperRef.current, diff --git a/packages/auth/test/events.spec.ts b/packages/auth/test/events.spec.ts index 73c7b43f4..994bdcb5c 100644 --- a/packages/auth/test/events.spec.ts +++ b/packages/auth/test/events.spec.ts @@ -172,6 +172,27 @@ describe("createSignInEventHandler should create signInEventHandler", () => { }); expect(dbGroupMembers?.groupId).toBe("1"); }); + test("should not change memberships for an invalid groups claim", async () => { + // Arrange + const db = createDb(); + await createUserAsync(db, "oidc"); + await createGroupAsync(db); + await db.insert(groupMembers).values({ userId: "1", groupId: "1" }); + const eventHandler = createSignInEventHandler(db); + + // Act + await eventHandler?.({ + user: { id: "1", name: "test" }, + profile: { preferred_username: "test", someRandomGroupsKey: 42 }, + account: null, + }); + + // Assert + const dbGroupMembers = await db.query.groupMembers.findFirst({ + where: eq(groupMembers.userId, "1"), + }); + expect(dbGroupMembers?.groupId).toBe("1"); + }); test("should remove group membership", async () => { // Arrange const db = createDb(); diff --git a/packages/integrations/src/beszel/beszel-integration.ts b/packages/integrations/src/beszel/beszel-integration.ts index 34b087107..d3edb6c5e 100644 --- a/packages/integrations/src/beszel/beszel-integration.ts +++ b/packages/integrations/src/beszel/beszel-integration.ts @@ -171,9 +171,11 @@ export class BeszelIntegration extends Integration { integrationId: this.integration.id, error: error instanceof Error ? error.message : String(error), }); - throw new ErrorWithMetadata("Beszel authentication response was not valid JSON", { - integrationId: this.integration.id, - }); + throw new ErrorWithMetadata( + "Beszel authentication response was not valid JSON", + { integrationId: this.integration.id }, + { cause: error instanceof Error ? error : new Error(String(error)) }, + ); } const expiresAt = parseTokenExpiration(data.token) ?? undefined; @@ -626,7 +628,11 @@ export class BeszelIntegration extends Integration { logger.warn("Failed to parse Beszel testing response JSON", { error: error instanceof Error ? error.message : String(error), }); - return TestConnectionError.ParseResult(new ParseError("Beszel testing response was not valid JSON")); + return TestConnectionError.ParseResult( + new ParseError("Beszel testing response was not valid JSON", { + cause: error instanceof Error ? error : new Error(String(error)), + }), + ); } if (!data.token) { return TestConnectionError.UnauthorizedResult(401);