fine
This commit is contained in:
parent
6df2812a4e
commit
9e4e65fa2a
35 changed files with 1172 additions and 70 deletions
|
|
@ -32,6 +32,16 @@ function authRefreshInvalidated(error: unknown): boolean {
|
|||
return status === 401 || status === 403;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize an email so login and registration are case- and
|
||||
* whitespace-insensitive: ` John@Example.com` and `john@example.com`
|
||||
* resolve to the same account. Applied at the PocketBase boundary rather
|
||||
* than on the input field, so the user still sees exactly what they typed.
|
||||
*/
|
||||
function normalizeEmail(email: string): string {
|
||||
return email.trim().toLowerCase();
|
||||
}
|
||||
|
||||
export function useAuth() {
|
||||
const { t } = useTranslation();
|
||||
const [user, setUser] = useState<AuthUser | null>(() => {
|
||||
|
|
@ -62,7 +72,9 @@ export function useAuth() {
|
|||
setError(null);
|
||||
setErrorAction(null);
|
||||
try {
|
||||
const result = await pb.collection('users').authWithPassword(email, password);
|
||||
const result = await pb
|
||||
.collection('users')
|
||||
.authWithPassword(normalizeEmail(email), password);
|
||||
setUser(recordToUser(result.record));
|
||||
trackEvent('Login', { method: 'email' });
|
||||
} catch (err) {
|
||||
|
|
@ -82,12 +94,13 @@ export function useAuth() {
|
|||
setLoading(true);
|
||||
setError(null);
|
||||
setErrorAction(null);
|
||||
const normalizedEmail = normalizeEmail(email);
|
||||
try {
|
||||
// Step 1: create the account. A failure here means nothing was created,
|
||||
// so surface a friendly, field-aware message (e.g. "email already exists").
|
||||
try {
|
||||
await pb.collection('users').create({
|
||||
email,
|
||||
email: normalizedEmail,
|
||||
password,
|
||||
passwordConfirm: password,
|
||||
newsletter: true,
|
||||
|
|
@ -103,7 +116,7 @@ export function useAuth() {
|
|||
// orphaned: tell the user it was created and let them log in with the
|
||||
// same credentials, instead of a misleading "registration failed".
|
||||
try {
|
||||
const result = await pb.collection('users').authWithPassword(email, password);
|
||||
const result = await pb.collection('users').authWithPassword(normalizedEmail, password);
|
||||
setUser(recordToUser(result.record));
|
||||
trackEvent('Register');
|
||||
} catch (err) {
|
||||
|
|
@ -159,7 +172,7 @@ export function useAuth() {
|
|||
setError(null);
|
||||
setErrorAction(null);
|
||||
try {
|
||||
await pb.collection('users').requestPasswordReset(email);
|
||||
await pb.collection('users').requestPasswordReset(normalizeEmail(email));
|
||||
} catch (err) {
|
||||
const { message, action } = resolveAuthError(err, 'reset', t);
|
||||
setError(message);
|
||||
|
|
@ -172,6 +185,27 @@ export function useAuth() {
|
|||
[t]
|
||||
);
|
||||
|
||||
const confirmPasswordReset = useCallback(
|
||||
async (token: string, password: string) => {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
setErrorAction(null);
|
||||
try {
|
||||
// PocketBase requires the password twice; the reset form uses a single
|
||||
// (show/hide) field, so both arguments are the same value.
|
||||
await pb.collection('users').confirmPasswordReset(token, password, password);
|
||||
} catch (err) {
|
||||
const { message, action } = resolveAuthError(err, 'confirmReset', t);
|
||||
setError(message);
|
||||
setErrorAction(action);
|
||||
throw err;
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
},
|
||||
[t]
|
||||
);
|
||||
|
||||
const refreshAuth = useCallback(async () => {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
|
|
@ -208,6 +242,7 @@ export function useAuth() {
|
|||
loginWithOAuth,
|
||||
logout,
|
||||
requestPasswordReset,
|
||||
confirmPasswordReset,
|
||||
refreshAuth,
|
||||
clearError,
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue