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:
Manus
2026-08-17 20:25:16 +00:00
parent 54164b1b33
commit d8b2a8fe6f
5 changed files with 47 additions and 2 deletions

View File

@@ -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(),
});

View File

@@ -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
View File

@@ -0,0 +1,19 @@
import { describe, expect, it } from "vitest";
import { normalizeLoginMethod } from "./authMethod";
describe("normalizeLoginMethod", () => {
it("conserve les valeurs de lenum 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
View 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";
}