Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ public static void main(String[] args) {
case 3:
Checkable.CheckStatus status = lockoutRequirement.check();
System.out.println("Password lockout requirement check: " + status);
if (status == Checkable.CheckStatus.FAIL)
System.out.println("Account is locked.");
break;

case 4:
Expand Down
84 changes: 84 additions & 0 deletions PasswordLockoutRequirement.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import java.util.HashMap;
import java.util.Map;

public class PasswordLockoutRequirement extends Requirement {

private static final int MAX_FAILED_ATTEMPTS = 5; // Maximum allowed failed attempts
private static final long LOCKOUT_DURATION_MS = 1 * 10 * 1000; // Lockout duration in milliseconds (10 seconds)
private final Map<String, UserLoginStatus> userStatusMap = new HashMap<>();
private final String username;

public PasswordLockoutRequirement(String username) {
this.username = username;
userStatusMap.putIfAbsent(username, new UserLoginStatus());
}


@Override
public Checkable.CheckStatus check() {
UserLoginStatus status = userStatusMap.get(username);

if (status.isLocked()) {
if (System.currentTimeMillis() - status.getLockoutStartTime() > LOCKOUT_DURATION_MS) {
status.resetLockout(); // Unlock after the lockout period
} else {
return Checkable.CheckStatus.FAIL;
}
}

return status.getFailedAttempts() >= MAX_FAILED_ATTEMPTS
? Checkable.CheckStatus.FAIL
: Checkable.CheckStatus.PASS;
}

// public void recordCorrectAttempt() {
// if (this.check() != Checkable.CheckStatus.FAIL)
// userStatusMap.get(username).resetFailedAttempts();
// }

public void recordFailedAttempt() {
userStatusMap.get(username).incrementFailedAttempts();
}

public void resetFailedAttempts() {
userStatusMap.get(username).resetFailedAttempts();
}

@Override
public String toString() {
return "The system must lock a user’s account after " + MAX_FAILED_ATTEMPTS + " consecutive failed login attempts.";
}

private static class UserLoginStatus {
private int failedAttempts = 0;
private long lockoutStartTime = 0;

public int getFailedAttempts() {
return failedAttempts;
}

public void incrementFailedAttempts() {
failedAttempts++;
if (failedAttempts >= MAX_FAILED_ATTEMPTS) {
lockoutStartTime = System.currentTimeMillis();
}
}

public void resetFailedAttempts() {
failedAttempts = 0;
lockoutStartTime = 0;
}

public boolean isLocked() {
return lockoutStartTime > 0;
}

public long getLockoutStartTime() {
return lockoutStartTime;
}

public void resetLockout() {
lockoutStartTime = 0;
}
}
}
2 changes: 1 addition & 1 deletion PasswordMinimumLength.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

import rqcode.concepts.Requirement;
// import rqcode.concepts.Requirement;

public class PasswordMinimumLength extends Requirement {
private static final int MIN_LENGTH = 8;
Expand Down
6 changes: 3 additions & 3 deletions PasswordPolicy.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package rqcode.tutorial.tutorial_new;
import rqcode.concepts.CombinedRequirements;
import rqcode.concepts.Requirement;
// package rqcode.tutorial.tutorial_new;
// import rqcode.concepts.CombinedRequirements;
// import rqcode.concepts.Requirement;
import java.util.Arrays;
import java.util.List;

Expand Down