Checkpoint: Correction complémentaire : normalisation stricte des valeurs OAuth de loginMethod avant insertion DB, afin d’éviter les erreurs de troncature causées par les identifiants de plateforme externes. Ajout de tests associés et validation build complète.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { COOKIE_NAME, ONE_YEAR_MS } from "@shared/const";
|
||||
import type { Express, Request, Response } from "express";
|
||||
import * as db from "../db";
|
||||
import { normalizeLoginMethod } from "../authMethod";
|
||||
import { getSessionCookieOptions } from "./cookies";
|
||||
import { sdk } from "./sdk";
|
||||
|
||||
@@ -32,7 +33,7 @@ export function registerOAuthRoutes(app: Express) {
|
||||
openId: userInfo.openId,
|
||||
name: userInfo.name || null,
|
||||
email: userInfo.email ?? "unknown@example.com",
|
||||
loginMethod: (userInfo.loginMethod ?? userInfo.platform ?? "manus") as "manus" | "local" | "azure-ad",
|
||||
loginMethod: normalizeLoginMethod(userInfo.loginMethod ?? userInfo.platform),
|
||||
lastSignedIn: new Date(),
|
||||
});
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import { AXIOS_TIMEOUT_MS, COOKIE_NAME, ONE_YEAR_MS } from "@shared/const";
|
||||
import { ForbiddenError } from "@shared/_core/errors";
|
||||
import axios, { type AxiosInstance } from "axios";
|
||||
import { parse as parseCookieHeader } from "cookie";
|
||||
import { normalizeLoginMethod } from "../authMethod";
|
||||
import type { Request } from "express";
|
||||
import { SignJWT, jwtVerify } from "jose";
|
||||
import type { User } from "../../drizzle/schema";
|
||||
@@ -296,7 +297,7 @@ class SDKServer {
|
||||
openId: userInfo.openId,
|
||||
name: userInfo.name || null,
|
||||
email: userInfo.email ?? "unknown@example.com",
|
||||
loginMethod: (userInfo.loginMethod ?? userInfo.platform ?? "manus") as "manus" | "local" | "azure-ad",
|
||||
loginMethod: normalizeLoginMethod(userInfo.loginMethod ?? userInfo.platform),
|
||||
lastSignedIn: signedInAt,
|
||||
});
|
||||
user = await db.getUserByOpenId(userInfo.openId);
|
||||
|
||||
19
server/authMethod.test.ts
Normal file
19
server/authMethod.test.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { normalizeLoginMethod } from "./authMethod";
|
||||
|
||||
describe("normalizeLoginMethod", () => {
|
||||
it("conserve les valeurs de l’enum DB", () => {
|
||||
expect(normalizeLoginMethod("local")).toBe("local");
|
||||
expect(normalizeLoginMethod("azure-ad")).toBe("azure-ad");
|
||||
});
|
||||
|
||||
it("convertit les identifiants de fournisseur Microsoft", () => {
|
||||
expect(normalizeLoginMethod("Microsoft OAuth")).toBe("azure-ad");
|
||||
expect(normalizeLoginMethod("AZURE_ENTRA")).toBe("azure-ad");
|
||||
});
|
||||
|
||||
it("utilise Manus pour toute valeur inconnue au lieu d’échouer en base", () => {
|
||||
expect(normalizeLoginMethod("platform-v2")).toBe("manus");
|
||||
expect(normalizeLoginMethod(undefined)).toBe("manus");
|
||||
});
|
||||
});
|
||||
23
server/authMethod.ts
Normal file
23
server/authMethod.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
/** Values accepted by the `users.loginMethod` database enum. */
|
||||
export type LoginMethod = "manus" | "local" | "azure-ad";
|
||||
|
||||
const LOGIN_METHODS = new Set<LoginMethod>(["manus", "local", "azure-ad"]);
|
||||
|
||||
/**
|
||||
* Maps provider-specific identifiers to the limited database enum.
|
||||
* OAuth identity payloads are external input and must never be persisted verbatim.
|
||||
*/
|
||||
export function normalizeLoginMethod(value: unknown): LoginMethod {
|
||||
if (typeof value !== "string") return "manus";
|
||||
|
||||
const normalized = value.trim().toLowerCase();
|
||||
if (LOGIN_METHODS.has(normalized as LoginMethod)) {
|
||||
return normalized as LoginMethod;
|
||||
}
|
||||
|
||||
if (normalized.includes("azure") || normalized.includes("microsoft")) {
|
||||
return "azure-ad";
|
||||
}
|
||||
|
||||
return "manus";
|
||||
}
|
||||
Reference in New Issue
Block a user