fix: narrow PR to verified bug fixes
This commit is contained in:
1 parent
3f9941f9c7
commit
268c864801
8 files changed
+50
-123
No files matched your search
+9
-16
@@ -32,22 +32,15 @@ export const createSignInEventHandler = (db: Database): Exclude<NextAuthConfig["
|
||||
|
||||
const groupsKey = env.AUTH_OIDC_GROUPS_ATTRIBUTE;
|
||||
// Groups from oidc provider are provided from the profile, it's not typed.
|
||||
// Some providers send a single group as a string instead of an array — normalize it.
|
||||
// Only accept string or string[] claims; reject null, numbers, objects, etc.
|
||||
const oidcGroups = profile && groupsKey in profile ? profile[groupsKey] : undefined;
|
||||
const normalizedOidcGroups: string[] | undefined = (() => {
|
||||
if (typeof oidcGroups === "string") return [oidcGroups];
|
||||
if (Array.isArray(oidcGroups) && oidcGroups.every((group): group is string => typeof group === "string")) {
|
||||
return oidcGroups;
|
||||
}
|
||||
if (oidcGroups !== undefined) {
|
||||
logger.warn(`Invalid OIDC groups claim "${groupsKey}"`);
|
||||
}
|
||||
return undefined;
|
||||
})();
|
||||
if (!env.AUTH_OIDC_GROUPS_LOCAL_MANAGEMENT && dbUser.provider === "oidc" && normalizedOidcGroups !== undefined) {
|
||||
logger.debug(`Using profile groups (${groupsKey}): ${JSON.stringify(normalizedOidcGroups)}`);
|
||||
await synchronizeGroupsWithExternalForUserAsync(db, user.id, normalizedOidcGroups);
|
||||
if (
|
||||
!env.AUTH_OIDC_GROUPS_LOCAL_MANAGEMENT &&
|
||||
dbUser.provider === "oidc" &&
|
||||
profile &&
|
||||
groupsKey in profile &&
|
||||
Array.isArray(profile[groupsKey])
|
||||
) {
|
||||
logger.debug(`Using profile groups (${groupsKey}): ${JSON.stringify(profile[groupsKey])}`);
|
||||
await synchronizeGroupsWithExternalForUserAsync(db, user.id, profile[groupsKey] as string[]);
|
||||
}
|
||||
|
||||
// In ldap-authroization we return the groups from ldap, it's not typed.
|
||||
|
||||
@@ -152,48 +152,6 @@ describe("createSignInEventHandler should create signInEventHandler", () => {
|
||||
});
|
||||
expect(dbGroupMembers?.groupId).toBe("1");
|
||||
});
|
||||
test("should add membership when the groups claim is a single string", async () => {
|
||||
// Arrange
|
||||
const db = createDb();
|
||||
await createUserAsync(db, "oidc");
|
||||
await createGroupAsync(db);
|
||||
const eventHandler = createSignInEventHandler(db);
|
||||
|
||||
// Act
|
||||
await eventHandler?.({
|
||||
user: { id: "1", name: "test" },
|
||||
profile: { preferred_username: "test", someRandomGroupsKey: "test" },
|
||||
account: null,
|
||||
});
|
||||
|
||||
// Assert
|
||||
const dbGroupMembers = await db.query.groupMembers.findFirst({
|
||||
where: eq(groupMembers.userId, "1"),
|
||||
});
|
||||
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.findMany({
|
||||
where: eq(groupMembers.userId, "1"),
|
||||
columns: { groupId: true },
|
||||
});
|
||||
expect(dbGroupMembers).toEqual([{ groupId: "1" }]);
|
||||
});
|
||||
test("should remove group membership", async () => {
|
||||
// Arrange
|
||||
const db = createDb();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ParseError, ResponseError } from "@homarr/common/server";
|
||||
import { ResponseError } from "@homarr/common/server";
|
||||
import { createLogger } from "@homarr/core/infrastructure/logs";
|
||||
import { ErrorWithMetadata } from "@homarr/core/infrastructure/logs/error";
|
||||
import { createCertificateAgentAsync, fetchWithTrustedCertificatesAsync } from "@homarr/core/infrastructure/http";
|
||||
@@ -163,20 +163,7 @@ export class BeszelIntegration extends Integration {
|
||||
throw new ResponseError(response);
|
||||
}
|
||||
|
||||
let data: BeszelAuthResponse;
|
||||
try {
|
||||
data = (await response.json()) as BeszelAuthResponse;
|
||||
} catch (error) {
|
||||
logger.warn("Failed to parse Beszel auth response JSON", {
|
||||
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 },
|
||||
{ cause: error instanceof Error ? error : new Error(String(error)) },
|
||||
);
|
||||
}
|
||||
const data = (await response.json()) as BeszelAuthResponse;
|
||||
const expiresAt = parseTokenExpiration(data.token) ?? undefined;
|
||||
|
||||
// A token that has already lapsed by the time it reaches us means our clock and Beszel's
|
||||
@@ -621,19 +608,7 @@ export class BeszelIntegration extends Integration {
|
||||
return TestConnectionError.StatusResult({ status: response.status, url: response.url });
|
||||
}
|
||||
|
||||
let data: BeszelAuthResponse;
|
||||
try {
|
||||
data = (await response.json()) as BeszelAuthResponse;
|
||||
} catch (error) {
|
||||
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", {
|
||||
cause: error instanceof Error ? error : new Error(String(error)),
|
||||
}),
|
||||
);
|
||||
}
|
||||
const data = (await response.json()) as BeszelAuthResponse;
|
||||
if (!data.token) {
|
||||
return TestConnectionError.UnauthorizedResult(401);
|
||||
}
|
||||
|
||||
@@ -42,7 +42,10 @@ export class UnraidIntegration extends Integration implements ISystemHealthMonit
|
||||
// Each entry in cpus[] is one logical CPU (thread). Dividing the summed per-thread
|
||||
// utilization by the thread count (not physical cores) gives the correct average and
|
||||
// avoids over-reporting on SMT systems. Guard against zero to avoid Infinity/NaN.
|
||||
const cpuUtilizationNormalized = cpuCount > 0 ? cpuUtilization / cpuCount : 0;
|
||||
let cpuUtilizationNormalized = 0;
|
||||
if (cpuCount > 0) {
|
||||
cpuUtilizationNormalized = cpuUtilization / cpuCount;
|
||||
}
|
||||
|
||||
const totalMemory = systemInfo.info.memory.layout.reduce((acc, layout) => layout.size + acc, 0);
|
||||
const usedMemory = totalMemory * (systemInfo.metrics.memory.percentTotal / 100);
|
||||
|
||||
Reference in new issue
Block a user