Checkpoint: Implémentation de la cohabitation des deux systèmes d'authentification (OAuth Manus et authentification locale). Les utilisateurs peuvent maintenant choisir entre :

- Authentification locale avec email/mot de passe
- OAuth Manus pour les utilisateurs de la plateforme

Le contexte tRPC gère automatiquement les deux types de tokens (JWT local et JWT OAuth).
This commit is contained in:
Manus Sandbox
2025-11-19 07:03:34 -05:00
parent a1d67c7451
commit 42826fc7dd
9 changed files with 940 additions and 10 deletions

View File

@@ -95,6 +95,86 @@ export async function getUserById(id: number) {
return result.length > 0 ? result[0] : undefined;
}
/**
* Récupère un utilisateur par son openId (OAuth)
*/
export async function getUserByOpenId(openId: string) {
const db = await getDb();
if (!db) {
console.warn("[Database] Cannot get user: database not available");
return undefined;
}
const result = await db.select().from(users).where(eq(users.openId, openId)).limit(1);
return result.length > 0 ? result[0] : undefined;
}
/**
* Crée ou met à jour un utilisateur OAuth
*/
export async function upsertUser(user: InsertUser): Promise<void> {
if (!user.openId && !user.email) {
throw new Error("User openId or email is required for upsert");
}
const db = await getDb();
if (!db) {
console.warn("[Database] Cannot upsert user: database not available");
return;
}
try {
const values: InsertUser = {
openId: user.openId,
email: user.email || '',
};
const updateSet: Record<string, unknown> = {};
const textFields = ["name", "email"] as const;
type TextField = (typeof textFields)[number];
const assignNullable = (field: TextField) => {
const value = user[field];
if (value === undefined) return;
const normalized = value ?? null;
values[field] = normalized;
updateSet[field] = normalized;
};
textFields.forEach(assignNullable);
if (user.lastSignedIn !== undefined) {
values.lastSignedIn = user.lastSignedIn;
updateSet.lastSignedIn = user.lastSignedIn;
}
if (user.role !== undefined) {
values.role = user.role;
updateSet.role = user.role;
} else if (user.openId === ENV.ownerOpenId) {
values.role = 'admin';
updateSet.role = 'admin';
}
if (!values.lastSignedIn) {
values.lastSignedIn = new Date();
}
if (Object.keys(updateSet).length === 0) {
updateSet.lastSignedIn = new Date();
}
// Utiliser openId comme clé unique pour OAuth
if (user.openId) {
await db.insert(users).values(values).onDuplicateKeyUpdate({
set: updateSet,
});
}
} catch (error) {
console.error("[Database] Failed to upsert user:", error);
throw error;
}
}
/**
* Met à jour le dernier login d'un utilisateur
*/