feat(auth): improve otp delivery and verification flow
This commit is contained in:
@@ -1,29 +1,44 @@
|
||||
import { authFetch, buildApiError, buildApiUrl } from './client';
|
||||
|
||||
// --- Auth Endpoints ---
|
||||
|
||||
|
||||
const normalizeDigits = (value: string) =>
|
||||
value
|
||||
.replace(/[۰-۹]/g, (digit) => String("۰۱۲۳۴۵۶۷۸۹".indexOf(digit)))
|
||||
.replace(/[٠-٩]/g, (digit) => String("٠١٢٣٤٥٦٧٨٩".indexOf(digit)))
|
||||
|
||||
// --- Auth Endpoints ---
|
||||
|
||||
export const loginWithPassword = async (mobile: string, password: string) => {
|
||||
const normalizedMobile = normalizeDigits(mobile)
|
||||
const response = await authFetch('/api/users/login/', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ mobile, password })
|
||||
body: JSON.stringify({ mobile: normalizedMobile, password })
|
||||
});
|
||||
if (!response.ok) throw await buildApiError(response);
|
||||
return response.json();
|
||||
};
|
||||
|
||||
export const sendOtp = async (mobile: string, mode: string) => {
|
||||
export interface SendOtpResponse {
|
||||
detail: string
|
||||
expires_in_seconds: number
|
||||
expires_at?: string | null
|
||||
}
|
||||
|
||||
export const sendOtp = async (mobile: string, mode: string): Promise<SendOtpResponse> => {
|
||||
const normalizedMobile = normalizeDigits(mobile)
|
||||
const response = await authFetch('/api/users/otp/send/', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ mobile, mode })
|
||||
body: JSON.stringify({ mobile: normalizedMobile, mode })
|
||||
});
|
||||
if (!response.ok) throw await buildApiError(response);
|
||||
return response.json();
|
||||
};
|
||||
|
||||
export const loginWithOtp = async (mobile: string, otp: string) => {
|
||||
const normalizedMobile = normalizeDigits(mobile)
|
||||
const normalizedOtp = normalizeDigits(otp)
|
||||
const response = await authFetch('/api/users/otp/login/', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ mobile, code: otp })
|
||||
body: JSON.stringify({ mobile: normalizedMobile, code: normalizedOtp })
|
||||
});
|
||||
if (!response.ok) throw await buildApiError(response);
|
||||
return response.json();
|
||||
@@ -37,9 +52,18 @@ export const registerWithOtp = async (
|
||||
first_name = "",
|
||||
last_name = "",
|
||||
) => {
|
||||
const normalizedMobile = normalizeDigits(mobile)
|
||||
const normalizedCode = normalizeDigits(code)
|
||||
const response = await authFetch("/api/users/register/", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ mobile, code, password, re_password, first_name, last_name }),
|
||||
body: JSON.stringify({
|
||||
mobile: normalizedMobile,
|
||||
code: normalizedCode,
|
||||
password,
|
||||
re_password,
|
||||
first_name,
|
||||
last_name,
|
||||
}),
|
||||
})
|
||||
if (!response.ok) throw await buildApiError(response)
|
||||
return response.json()
|
||||
@@ -51,9 +75,16 @@ export const resetPasswordWithOtp = async (
|
||||
password: string,
|
||||
re_password: string,
|
||||
) => {
|
||||
const normalizedMobile = normalizeDigits(mobile)
|
||||
const normalizedCode = normalizeDigits(code)
|
||||
const response = await authFetch("/api/users/password/reset/", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ mobile, code, password, re_password }),
|
||||
body: JSON.stringify({
|
||||
mobile: normalizedMobile,
|
||||
code: normalizedCode,
|
||||
password,
|
||||
re_password,
|
||||
}),
|
||||
})
|
||||
if (!response.ok) throw await buildApiError(response)
|
||||
return response.json()
|
||||
@@ -107,9 +138,10 @@ export const completeGoogleOAuthSignup = async (
|
||||
flow: string,
|
||||
mobile: string,
|
||||
): Promise<GoogleOAuthFlowResponse> => {
|
||||
const normalizedMobile = normalizeDigits(mobile)
|
||||
const response = await authFetch("/api/users/oauth/google/complete/", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ flow, mobile }),
|
||||
body: JSON.stringify({ flow, mobile: normalizedMobile }),
|
||||
});
|
||||
if (!response.ok) throw await buildApiError(response);
|
||||
return response.json();
|
||||
@@ -128,9 +160,10 @@ export const verifyGoogleOAuthClaim = async (
|
||||
flow: string,
|
||||
code: string,
|
||||
): Promise<GoogleOAuthFlowResponse> => {
|
||||
const normalizedCode = normalizeDigits(code)
|
||||
const response = await authFetch("/api/users/oauth/google/claim/verify/", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ flow, code }),
|
||||
body: JSON.stringify({ flow, code: normalizedCode }),
|
||||
});
|
||||
if (!response.ok) throw await buildApiError(response);
|
||||
return response.json();
|
||||
@@ -193,9 +226,9 @@ export interface SearchedUser {
|
||||
profile_picture: string | null;
|
||||
}
|
||||
|
||||
export const searchUserByExactMobile = async (mobile: string): Promise<SearchedUser | null> => {
|
||||
try {
|
||||
const response = await authFetch(`/api/users/search/?mobile=${encodeURIComponent(mobile)}`);
|
||||
export const searchUserByExactMobile = async (mobile: string): Promise<SearchedUser | null> => {
|
||||
try {
|
||||
const response = await authFetch(`/api/users/search/?mobile=${encodeURIComponent(normalizeDigits(mobile))}`);
|
||||
if (!response.ok) return null; // Returns null on 404 or other errors
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user