View Javadoc
1   /*
2    * MIT License
3    * Copyright (c) 2006-2025 JMockit developers
4    * See LICENSE file for full license text.
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          // noinspection ConstantConditions
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                  // noinspection ConstantConditions
63                  account.setRevoked(true);
64                  loginAttemptsRemaining = MAX_LOGIN_ATTEMPTS;
65              }
66          } else {
67              loginAttemptsRemaining = MAX_LOGIN_ATTEMPTS;
68              previousAccountId = accountId;
69          }
70      }
71  }