fix: speed up otp login

This commit is contained in:
Codex 2026-04-16 16:30:36 +03:00
parent a5113a2ed5
commit ffc7f3a97d
2 changed files with 43 additions and 29 deletions

View File

@ -1,13 +1,11 @@
import React, { createContext, useContext, useEffect, useState } from "react";
import { demoUsers } from "../data/mockAppData";
import { supabase, hasSupabaseConfig } from "../supabaseClient";
import { safeSupabaseCall } from "../services/safeSupabaseCall";
const AuthContext = createContext(null);
const STORAGE_KEY = "construction-auth-local-user";
export const DEMO_LOGIN_EMAIL = "local@local";
export const ROLE_SWITCH_ENTRY_EMAIL = "roles@local";
export const MISSING_PROFILE_ERROR = "Профиль пользователя не найден. Обратитесь к администратору.";
export const PROFILE_LOAD_ERROR = "Не удалось загрузить профиль пользователя.";
export const UNKNOWN_EMAIL_ERROR = "Email не найден в системе. Обратитесь к администратору.";
@ -66,6 +64,23 @@ export const mapProfileToAuthUser = (profile) => {
};
};
export const mapSessionUserToAuthUser = (sessionUser) => {
if (!sessionUser) {
return null;
}
const userMetadata = sessionUser.user_metadata || {};
const appMetadata = sessionUser.app_metadata || {};
return {
id: sessionUser.id,
email: sessionUser.email,
name: userMetadata.name || sessionUser.email || "Пользователь",
role: userMetadata.role || appMetadata.role || "manager",
lastLogin: sessionUser.last_sign_in_at || sessionUser.updated_at || null,
};
};
export const AuthProvider = ({ children }) => {
const [user, setUser] = useState(() => {
const stored = localStorage.getItem(STORAGE_KEY);
@ -83,39 +98,15 @@ export const AuthProvider = ({ children }) => {
const {
data: { subscription },
} = supabase.auth.onAuthStateChange(async (_event, session) => {
} = supabase.auth.onAuthStateChange((_event, session) => {
if (!session?.user) {
setUser(null);
setAuthError("");
return;
}
const { data, error } = await safeSupabaseCall(async () => {
const { data: profile, error } = await supabase
.from("users")
.select("id, email, name, last_login, role_info:roles(name)")
.eq("id", session.user.id)
.maybeSingle();
if (error) {
throw error;
}
return profile;
}, "Ошибка загрузки профиля");
if (error) {
setUser(null);
setAuthError(error?.message || PROFILE_LOAD_ERROR);
return;
}
if (!data) {
setUser(null);
setAuthError(MISSING_PROFILE_ERROR);
return;
}
setUser(mapProfileToAuthUser(data));
const nextUser = mapSessionUserToAuthUser(session.user);
setUser(nextUser);
setAuthError("");
});
@ -171,6 +162,8 @@ export const AuthProvider = ({ children }) => {
throw normalizeOtpError(error);
}
setUser(mapSessionUserToAuthUser(data.session?.user));
setAuthError("");
return { success: Boolean(data.session) };
}

View File

@ -6,6 +6,7 @@ import {
buildOtpRequestPayload,
isRoleSwitchEntryEmail,
mapProfileToAuthUser,
mapSessionUserToAuthUser,
normalizeOtpError,
resolveDemoUser,
resolveLoginEmail,
@ -75,6 +76,26 @@ describe("mapProfileToAuthUser", () => {
});
});
describe("mapSessionUserToAuthUser", () => {
it("maps session metadata to an immediate app user", () => {
expect(
mapSessionUserToAuthUser({
id: "session-id",
email: "driver@company.ru",
user_metadata: { name: "Иван Соколов", role: "driver" },
app_metadata: { role: "logistician" },
last_sign_in_at: "2026-04-15T08:00:00Z",
}),
).toEqual({
id: "session-id",
email: "driver@company.ru",
name: "Иван Соколов",
role: "driver",
lastLogin: "2026-04-15T08:00:00Z",
});
});
});
describe("normalizeOtpError", () => {
it("maps unknown email errors to the admin hint", () => {