1
2
3
4
5
6 package jmockit.loginExample.domain.userLogin;
7
8 import edu.umd.cs.findbugs.annotations.NonNull;
9 import edu.umd.cs.findbugs.annotations.Nullable;
10
11 import org.checkerframework.checker.index.qual.NonNegative;
12
13 import jmockit.loginExample.domain.userAccount.UserAccount;
14
15 public final class LoginService {
16 private static final int MAX_LOGIN_ATTEMPTS = 3;
17
18 @NonNegative
19 private int loginAttemptsRemaining = MAX_LOGIN_ATTEMPTS;
20 @Nullable
21 private String previousAccountId;
22 @Nullable
23 private UserAccount account;
24
25 public void login(@NonNull String accountId, @NonNull String password)
26 throws UserAccountNotFoundException, UserAccountRevokedException, AccountLoginLimitReachedException {
27 account = UserAccount.find(accountId);
28
29 if (account == null) {
30 throw new UserAccountNotFoundException();
31 }
32
33 if (account.passwordMatches(password)) {
34 registerNewLogin();
35 } else {
36 handleFailedLoginAttempt(accountId);
37 }
38 }
39
40 private void registerNewLogin() throws AccountLoginLimitReachedException, UserAccountRevokedException {
41
42 if (account.isLoggedIn()) {
43 throw new AccountLoginLimitReachedException();
44 }
45
46 if (account.isRevoked()) {
47 throw new UserAccountRevokedException();
48 }
49
50 account.setLoggedIn(true);
51 loginAttemptsRemaining = MAX_LOGIN_ATTEMPTS;
52 }
53
54 private void handleFailedLoginAttempt(@NonNull String accountId) {
55 if (previousAccountId == null) {
56 loginAttemptsRemaining--;
57 previousAccountId = accountId;
58 } else if (accountId.equals(previousAccountId)) {
59 loginAttemptsRemaining--;
60
61 if (loginAttemptsRemaining == 0) {
62
63 account.setRevoked(true);
64 loginAttemptsRemaining = MAX_LOGIN_ATTEMPTS;
65 }
66 } else {
67 loginAttemptsRemaining = MAX_LOGIN_ATTEMPTS;
68 previousAccountId = accountId;
69 }
70 }
71 }