]> WPIA git - gigi.git/commitdiff
add: DelegatingPasswordChecker implementation
authorLucas Werkmeister <mail@lucaswerkmeister.de>
Sun, 14 Jan 2018 14:12:56 +0000 (15:12 +0100)
committerLucas Werkmeister <mail@lucaswerkmeister.de>
Sun, 10 Jun 2018 11:24:31 +0000 (13:24 +0200)
This PasswordChecker implementation delegates to several other checkers,
which lets us use a series of checkers (e. g. one which rates the
password’s strength and one that checks against a list of known weak
passwords) in place of one.

In theory, this would also let us split up the existing
PasswordStrengthChecker into two checkers, one grading the password
strength in general and one checking whether the password contains parts
of the name or the email address. However, this would remove the current
behavior where a password that contains part of the name or email can be
“redeemed” by being otherwise strong enough: DelegatingPasswordChecker
does not support any such kind of interoperation of checkers.

Change-Id: I1066ab11cac8c756a2972128257a65d29cd2d365

src/club/wpia/gigi/passwords/DelegatingPasswordChecker.java [new file with mode: 0644]
tests/club/wpia/gigi/passwords/TestDelegatingPasswordChecker.java [new file with mode: 0644]

diff --git a/src/club/wpia/gigi/passwords/DelegatingPasswordChecker.java b/src/club/wpia/gigi/passwords/DelegatingPasswordChecker.java
new file mode 100644 (file)
index 0000000..3d6c9d9
--- /dev/null
@@ -0,0 +1,32 @@
+package club.wpia.gigi.passwords;
+
+import club.wpia.gigi.GigiApiException;
+
+/**
+ * A {@link PasswordChecker} that delegates checks to several other PasswordCheckers
+ * and merges their error messages.
+ */
+public class DelegatingPasswordChecker implements PasswordChecker {
+
+    private final PasswordChecker[] checkers;
+
+    public DelegatingPasswordChecker(PasswordChecker[] checkers) {
+        this.checkers = checkers;
+    }
+
+    @Override
+    public GigiApiException checkPassword(String password, String[] nameParts, String email) {
+        GigiApiException exception = new GigiApiException();
+        for (PasswordChecker checker : checkers) {
+            GigiApiException currentException = checker.checkPassword(password, nameParts, email);
+            if (currentException != null) {
+                exception.mergeInto(currentException);
+            }
+        }
+        if (exception.isEmpty()) {
+            return null;
+        } else {
+            return exception;
+        }
+    }
+}
diff --git a/tests/club/wpia/gigi/passwords/TestDelegatingPasswordChecker.java b/tests/club/wpia/gigi/passwords/TestDelegatingPasswordChecker.java
new file mode 100644 (file)
index 0000000..250758a
--- /dev/null
@@ -0,0 +1,77 @@
+package club.wpia.gigi.passwords;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+import club.wpia.gigi.GigiApiException;
+import club.wpia.gigi.passwords.DelegatingPasswordChecker;
+import club.wpia.gigi.passwords.PasswordChecker;
+
+public class TestDelegatingPasswordChecker {
+
+    @Test
+    public void testNoCheckers() {
+        DelegatingPasswordChecker checker = new DelegatingPasswordChecker(new PasswordChecker[0]);
+
+        assertNull(checker.checkPassword("", new String[0], ""));
+    }
+
+    @Test
+    public void testOneChecker() {
+        DelegatingPasswordChecker checker = new DelegatingPasswordChecker(new PasswordChecker[] {
+            new PasswordChecker() {
+                @Override
+                public GigiApiException checkPassword(String password, String[] nameParts, String email) {
+                    return password.isEmpty() ?
+                        new GigiApiException("empty password") :
+                        null;
+                }
+            }
+        });
+
+        assertNull(checker.checkPassword("a strong password", new String[0], ""));
+
+        GigiApiException exception = checker.checkPassword("", new String[0], "");
+        assertNotNull(exception);
+        assertEquals("empty password", exception.getMessage());
+    }
+
+    @Test
+    public void testTwoCheckers() {
+        DelegatingPasswordChecker checker = new DelegatingPasswordChecker(new PasswordChecker[] {
+            new PasswordChecker() {
+                @Override
+                public GigiApiException checkPassword(String password, String[] nameParts, String email) {
+                    return password.equals(email) ?
+                        new GigiApiException("password = email") :
+                        null;
+                }
+            },
+            new PasswordChecker() {
+                @Override
+                public GigiApiException checkPassword(String password, String[] nameParts, String email) {
+                    return password.equals("12345") ?
+                        new GigiApiException("12345 is a bad password") :
+                        null;
+                }
+            }
+        });
+
+        assertNull(checker.checkPassword("a strong password", new String[0], "email"));
+
+        GigiApiException exception1 = checker.checkPassword("email", new String[0], "email");
+        assertNotNull(exception1);
+        assertEquals("password = email", exception1.getMessage());
+
+        GigiApiException exception2 = checker.checkPassword("12345", new String[0], "email");
+        assertNotNull(exception2);
+        assertEquals("12345 is a bad password", exception2.getMessage());
+
+        GigiApiException exception3 = checker.checkPassword("12345", new String[0], "12345");
+        assertNotNull(exception3);
+        assertThat(exception3.getMessage(), containsString("password = email"));
+        assertThat(exception3.getMessage(), containsString("12345 is a bad password"));
+    }
+}