feat: integration user lock flow to frontend

This commit is contained in:
Sheen Capadngan
2024-05-22 22:51:20 +08:00
parent 41d72d5dc6
commit e3dae9d498
5 changed files with 34 additions and 25 deletions

View File

@@ -49,6 +49,7 @@ export const registerUserRouter = async (server: FastifyZodProvider) => {
await server.services.user.unlockUser(req.params.userId, req.query.token);
} catch (err) {
logger.error(`User unlock failed for ${req.params.userId}`);
logger.error(err);
}
return res.redirect(`${appCfg.SITE_URL}/login`);
}

View File

@@ -59,7 +59,7 @@ export const enforceUserLockStatus = (isLocked: boolean, temporaryLockDateEnd?:
if (timeDiff < 0)
throw new UnauthorizedError({
name: "User Locked",
message: `User is locked due to multiple failed login attempts. Try logging in again after ${Math.round(
message: `User is locked due to multiple failed login attempts. Try again after ${Math.round(
(-1 * timeDiff) / 1000
)} seconds.`
});

View File

@@ -38,7 +38,7 @@ export const processFailedMfaAttempt = async (userId: string, userDAL: Pick<TUse
const progressiveDelaysInMins = [5, 30, 60];
// lock user when failed attempt exceeds threshold
if (user.consecutiveFailedMfaAttempts > PROGRESSIVE_DELAY_INTERVAL * progressiveDelaysInMins.length) {
if (user.consecutiveFailedMfaAttempts >= PROGRESSIVE_DELAY_INTERVAL * (progressiveDelaysInMins.length + 1)) {
return (
await tx(TableName.Users)
.where("id", userId)

View File

@@ -105,8 +105,18 @@ export const InitialStep = ({ setStep, email, setEmail, password, setPassword }:
});
}
}
} catch (err) {
} catch (err: any) {
console.error(err);
if (err.response.data.error === "User Locked") {
createNotification({
title: err.response.data.error,
text: err.response.data.message,
type: "error"
});
setIsLoading(false);
return;
}
setLoginError(true);
createNotification({
text: "Login unsuccessful. Double-check your credentials and try again.",

View File

@@ -46,20 +46,7 @@ type Props = {
callbackPort?: string | null;
};
interface VerifyMfaTokenError {
response: {
data: {
context: {
code: string;
triesLeft: number;
};
};
status: number;
};
}
export const MFAStep = ({ email, password, providerAuthToken }: Props) => {
const router = useRouter();
const [isLoading, setIsLoading] = useState(false);
const [isLoadingResend, setIsLoadingResend] = useState(false);
@@ -178,20 +165,31 @@ export const MFAStep = ({ email, password, providerAuthToken }: Props) => {
});
}
}
} catch (err) {
const error = err as VerifyMfaTokenError;
} catch (err: any) {
if (err.response.data.error === "User Locked") {
createNotification({
title: err.response.data.error,
text: err.response.data.message,
type: "error"
});
setIsLoading(false);
return;
}
createNotification({
text: "Failed to log in",
type: "error"
});
if (error?.response?.status === 500) {
window.location.reload();
} else if (error?.response?.data?.context?.triesLeft) {
setTriesLeft(error?.response?.data?.context?.triesLeft);
if (error.response.data.context.triesLeft === 0) {
window.location.reload();
}
if (triesLeft) {
setTriesLeft((left) => {
if (triesLeft === 1) {
window.location.reload();
}
return (left as number) - 1;
});
} else {
setTriesLeft(2);
}
setIsLoading(false);