feat: block user after 5 failed login attemtps
This commit is contained in:
@@ -44,6 +44,8 @@ export async function authRoutes(fastify: FastifyInstance) {
|
|||||||
const hashedPassword = await hash(password);
|
const hashedPassword = await hash(password);
|
||||||
userInDB.passwordHash = hashedPassword;
|
userInDB.passwordHash = hashedPassword;
|
||||||
|
|
||||||
|
userInDB.blocked = false;
|
||||||
|
userInDB.faliedLoginCount = 0;
|
||||||
await userInDB.save();
|
await userInDB.save();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return err;
|
return err;
|
||||||
@@ -79,9 +81,20 @@ export async function authRoutes(fastify: FastifyInstance) {
|
|||||||
if (!userInDB.passwordHash)
|
if (!userInDB.passwordHash)
|
||||||
return res.code(401).send({ error: "invalid email or password" });
|
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);
|
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" });
|
return res.code(401).send({ error: "invalid email or password" });
|
||||||
|
}
|
||||||
|
|
||||||
const newSession = await createSession(
|
const newSession = await createSession(
|
||||||
userInDB.id,
|
userInDB.id,
|
||||||
@@ -90,6 +103,7 @@ export async function authRoutes(fastify: FastifyInstance) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
userInDB.lastLogin = new Date();
|
userInDB.lastLogin = new Date();
|
||||||
|
userInDB.faliedLoginCount = 0;
|
||||||
await userInDB.save();
|
await userInDB.save();
|
||||||
|
|
||||||
res.send({ session_token: newSession.sid });
|
res.send({ session_token: newSession.sid });
|
||||||
|
|||||||
@@ -51,6 +51,11 @@ const userSchema = new mongoose.Schema({
|
|||||||
},
|
},
|
||||||
lastLogin: Date,
|
lastLogin: Date,
|
||||||
dev: Boolean,
|
dev: Boolean,
|
||||||
|
blocked: Boolean,
|
||||||
|
faliedLoginCount: {
|
||||||
|
type: Number,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const userModel = mongoose.model("user", userSchema);
|
export const userModel = mongoose.model("user", userSchema);
|
||||||
@@ -116,6 +121,8 @@ const userResponse = z.object({
|
|||||||
createdAt: z.string().optional(),
|
createdAt: z.string().optional(),
|
||||||
createdBy: z.string().optional(),
|
createdBy: z.string().optional(),
|
||||||
lastLogin: z.string().optional(),
|
lastLogin: z.string().optional(),
|
||||||
|
blocked: z.boolean().optional(),
|
||||||
|
failedLoginCount: z.number().optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type CreateUserInput = z.infer<typeof createUserInput>;
|
export type CreateUserInput = z.infer<typeof createUserInput>;
|
||||||
|
|||||||
@@ -38,6 +38,8 @@ export async function createUser(
|
|||||||
createdBy: user.userId,
|
createdBy: user.userId,
|
||||||
status: input.password ? "active" : "invited",
|
status: input.password ? "active" : "invited",
|
||||||
passwordHash: hashedPassword,
|
passwordHash: hashedPassword,
|
||||||
|
blocked: false,
|
||||||
|
faliedLoginCount: 0,
|
||||||
...input,
|
...input,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -156,7 +158,7 @@ export async function listUsers(user: AuthenticatedUser) {
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
.select(
|
.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: "orgId", select: "_id pid name avatar" })
|
||||||
.populate({ path: "createdBy", select: "_id pid name avatar" });
|
.populate({ path: "createdBy", select: "_id pid name avatar" });
|
||||||
|
|||||||
Reference in New Issue
Block a user