more fix and update
This commit is contained in:
@@ -39,7 +39,10 @@ interface AuthContextValue {
|
||||
verifyLoginOtp: (recipient: string, code: string) => Promise<PasswordlessAuthResponse>;
|
||||
loginWithPassword: (login: string, password: string) => Promise<AuthTokens>;
|
||||
loginWithLdap: (username: string, password: string) => Promise<AuthTokens>;
|
||||
beginTotpLogin: (recipient: string) => Promise<string>;
|
||||
verifyTotpLogin: (totpChallengeToken: string, code: string) => Promise<AuthTokens>;
|
||||
completePin: (sessionId: string, pin: string) => Promise<void>;
|
||||
applyLoginAuth: (auth: AuthTokens) => AuthTokens;
|
||||
register: (data: { displayName: string; login: string; password: string }) => Promise<void>;
|
||||
refreshProfile: () => Promise<void>;
|
||||
logout: () => void;
|
||||
@@ -381,6 +384,50 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
|
||||
[saveSession]
|
||||
);
|
||||
|
||||
const beginTotpLogin = React.useCallback(async (recipient: string) => {
|
||||
const response = await apiFetch<{ totpChallengeToken: string }>('/auth/totp/begin', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
recipient,
|
||||
fingerprint: getDeviceFingerprint(),
|
||||
deviceName: navigator.userAgent.includes('Windows') ? 'Windows Browser' : 'Browser',
|
||||
deviceType: 'WEB'
|
||||
})
|
||||
});
|
||||
return response.totpChallengeToken;
|
||||
}, []);
|
||||
|
||||
const verifyTotpLogin = React.useCallback(
|
||||
async (totpChallengeToken: string, code: string) => {
|
||||
const auth = await apiFetch<AuthTokens>('/auth/totp/verify', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ totpChallengeToken, code })
|
||||
});
|
||||
if (auth.pinVerified) {
|
||||
saveSession(auth);
|
||||
} else {
|
||||
persistPartialAuth(auth);
|
||||
setHasStoredSession(true);
|
||||
}
|
||||
return auth;
|
||||
},
|
||||
[saveSession]
|
||||
);
|
||||
|
||||
const applyLoginAuth = React.useCallback(
|
||||
(auth: AuthTokens) => {
|
||||
if (auth.pinVerified) {
|
||||
saveSession(auth);
|
||||
} else {
|
||||
persistPartialAuth(auth);
|
||||
setHasStoredSession(true);
|
||||
activatePinLock(auth.sessionId);
|
||||
}
|
||||
return auth;
|
||||
},
|
||||
[activatePinLock, saveSession]
|
||||
);
|
||||
|
||||
const completePin = React.useCallback(
|
||||
async (sessionId: string, pin: string) => {
|
||||
const response = await apiFetch<PinVerificationResponse>('/auth/pin/verify', {
|
||||
@@ -452,7 +499,10 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
|
||||
verifyLoginOtp,
|
||||
loginWithPassword,
|
||||
loginWithLdap,
|
||||
beginTotpLogin,
|
||||
verifyTotpLogin,
|
||||
completePin,
|
||||
applyLoginAuth,
|
||||
register,
|
||||
refreshProfile,
|
||||
logout
|
||||
|
||||
@@ -6,12 +6,13 @@ import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { useToast } from '@/components/id/toast-provider';
|
||||
import { useAvatarUrl } from '@/hooks/use-avatar-url';
|
||||
import { apiFetch, getApiErrorMessage } from '@/lib/api';
|
||||
import { apiFetch, getApiErrorMessage, uploadMediaObject } from '@/lib/api';
|
||||
|
||||
interface PresignedUploadResponse {
|
||||
uploadUrl: string;
|
||||
storageKey: string;
|
||||
expiresAt: string;
|
||||
uploadToken?: string;
|
||||
}
|
||||
|
||||
export function AvatarUpload({
|
||||
@@ -53,15 +54,7 @@ export function AvatarUpload({
|
||||
token
|
||||
);
|
||||
|
||||
const uploadResponse = await fetch(presigned.uploadUrl, {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': file.type },
|
||||
body: file
|
||||
});
|
||||
|
||||
if (!uploadResponse.ok) {
|
||||
throw new Error('Не удалось загрузить файл в хранилище');
|
||||
}
|
||||
await uploadMediaObject(presigned, file, file.type);
|
||||
|
||||
await apiFetch('/media/avatars/confirm', {
|
||||
method: 'POST',
|
||||
|
||||
Reference in New Issue
Block a user