feat: block user after 5 failed login attemtps

This commit is contained in:
2025-08-04 11:59:52 +05:30
parent 85d98250a7
commit e4817ffdf7
3 changed files with 25 additions and 2 deletions

View File

@@ -44,6 +44,8 @@ export async function authRoutes(fastify: FastifyInstance) {
const hashedPassword = await hash(password);
userInDB.passwordHash = hashedPassword;
userInDB.blocked = false;
userInDB.faliedLoginCount = 0;
await userInDB.save();
} catch (err) {
return err;
@@ -79,9 +81,20 @@ export async function authRoutes(fastify: FastifyInstance) {
if (!userInDB.passwordHash)
return res.code(401).send({ error: "invalid email or password" });
if (userInDB.blocked)
return res
.code(401)
.send({ error: "Account blocked. Contact admin." });
const match = await verify(userInDB.passwordHash, password);
if (!match)
if (!match) {
if (!userInDB.faliedLoginCount) userInDB.faliedLoginCount = 0;
if (userInDB.faliedLoginCount >= 4) userInDB.blocked = true;
userInDB.faliedLoginCount++;
await userInDB.save();
return res.code(401).send({ error: "invalid email or password" });
}
const newSession = await createSession(
userInDB.id,
@@ -90,6 +103,7 @@ export async function authRoutes(fastify: FastifyInstance) {
);
userInDB.lastLogin = new Date();
userInDB.faliedLoginCount = 0;
await userInDB.save();
res.send({ session_token: newSession.sid });

View File

@@ -51,6 +51,11 @@ const userSchema = new mongoose.Schema({
},
lastLogin: Date,
dev: Boolean,
blocked: Boolean,
faliedLoginCount: {
type: Number,
default: 0,
},
});
export const userModel = mongoose.model("user", userSchema);
@@ -116,6 +121,8 @@ const userResponse = z.object({
createdAt: z.string().optional(),
createdBy: z.string().optional(),
lastLogin: z.string().optional(),
blocked: z.boolean().optional(),
failedLoginCount: z.number().optional(),
});
export type CreateUserInput = z.infer<typeof createUserInput>;

View File

@@ -38,6 +38,8 @@ export async function createUser(
createdBy: user.userId,
status: input.password ? "active" : "invited",
passwordHash: hashedPassword,
blocked: false,
faliedLoginCount: 0,
...input,
});
@@ -156,7 +158,7 @@ export async function listUsers(user: AuthenticatedUser) {
],
})
.select(
"_id pid orgId firstName lastName name email role avatar status createdAt createdBy lastLogin"
"_id pid orgId firstName lastName name email role avatar status createdAt createdBy lastLogin blocked failedLoginCount"
)
.populate({ path: "orgId", select: "_id pid name avatar" })
.populate({ path: "createdBy", select: "_id pid name avatar" });