]> WPIA git - gigi.git/commitdiff
fix: display verify information only when verification token is known.
authorFelix Dörre <felix@dogcraft.de>
Mon, 6 Feb 2017 22:45:13 +0000 (23:45 +0100)
committerFelix Dörre <felix@dogcraft.de>
Tue, 7 Feb 2017 08:59:55 +0000 (09:59 +0100)
Change-Id: I12ea06f13fddc3ad931751e9751f7d87fefd6c60

src/org/cacert/gigi/dbObjects/Domain.java
src/org/cacert/gigi/dbObjects/EmailAddress.java
src/org/cacert/gigi/dbObjects/Verifyable.java
src/org/cacert/gigi/pages/Verify.java
tests/org/cacert/gigi/pages/TestVerify.java [new file with mode: 0644]

index 3ecf728567f6c166aa5dc960091c8c26061c6f28..f7c963c9e40e83c1033943d0d5d6f3004ac5add2 100644 (file)
@@ -125,6 +125,14 @@ public class Domain implements IdCachable, Verifyable {
         configs = null;
     }
 
+    public synchronized boolean isVerifyable(String hash) throws GigiApiException {
+        try (GigiPreparedStatement ps = new GigiPreparedStatement("SELECT 1 FROM `domainPinglog` WHERE `challenge`=? AND `state`='open' AND `configId` IN (SELECT `id` FROM `pingconfig` WHERE `domainid`=? AND `type`='email')")) {
+            ps.setString(1, hash);
+            ps.setInt(2, id);
+            return ps.executeQuery().next();
+        }
+    }
+
     public synchronized void verify(String hash) throws GigiApiException {
         try (GigiPreparedStatement ps = new GigiPreparedStatement("UPDATE `domainPinglog` SET `state`='success' WHERE `challenge`=? AND `state`='open' AND `configId` IN (SELECT `id` FROM `pingconfig` WHERE `domainid`=? AND `type`='email')")) {
             ps.setString(1, hash);
index b2106d8bff71c901c3e51c1bfe9e6b3d8f160c8c..7847035914140891a829d1e18daedbd968b1fd0e 100644 (file)
@@ -95,6 +95,15 @@ public class EmailAddress implements IdCachable, Verifyable {
         return address;
     }
 
+    public synchronized boolean isVerifyable(String hash) throws GigiApiException {
+        try (GigiPreparedStatement stmt = new GigiPreparedStatement("SELECT 1 FROM `emailPinglog` WHERE `email`=? AND `uid`=? AND `type`='active' AND `challenge`=? AND `status`='open'::`pingState`")) {
+            stmt.setString(1, address);
+            stmt.setInt(2, owner.getId());
+            stmt.setString(3, hash);
+            return stmt.executeQuery().next();
+        }
+    }
+
     public synchronized void verify(String hash) throws GigiApiException {
         try (GigiPreparedStatement stmt = new GigiPreparedStatement("UPDATE `emailPinglog` SET `status`='success'::`pingState` WHERE `email`=? AND `uid`=? AND `type`='active' AND `challenge`=? AND `status`='open'::`pingState`")) {
             stmt.setString(1, address);
index e1c997e44ec4fbcb6298c9bef1225cab26ae4d2d..ba4dd0c58bca4904dc67f6d21212e906defe3365 100644 (file)
@@ -6,4 +6,6 @@ public interface Verifyable {
 
     public void verify(String hash) throws GigiApiException;
 
+    public boolean isVerifyable(String hash) throws GigiApiException;
+
 }
index 2b4cd82605cfe2ffc62fa76b2cde50e489717ad0..bc4639810cd591dcc5cf7a53e4117d3cb12f3fed 100644 (file)
@@ -52,6 +52,13 @@ public class Verify extends Page {
             } else {
                 throw new IllegalArgumentException();
             }
+            try {
+                if ( !target.isVerifyable(hash)) {
+                    throw new IllegalArgumentException();
+                }
+            } catch (GigiApiException e) {
+                throw new IllegalArgumentException(e);
+            }
         }
 
         @Override
diff --git a/tests/org/cacert/gigi/pages/TestVerify.java b/tests/org/cacert/gigi/pages/TestVerify.java
new file mode 100644 (file)
index 0000000..28572eb
--- /dev/null
@@ -0,0 +1,74 @@
+package org.cacert.gigi.pages;
+
+import static org.junit.Assert.*;
+
+import java.util.Locale;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.cacert.gigi.GigiApiException;
+import org.cacert.gigi.dbObjects.EmailAddress;
+import org.cacert.gigi.testUtils.ClientBusinessTest;
+import org.cacert.gigi.testUtils.TestEmailReceiver.TestMail;
+import org.hamcrest.CustomMatcher;
+import org.junit.Test;
+
+public class TestVerify extends ClientBusinessTest {
+
+    @Test
+    public void testVerify() throws GigiApiException {
+        EmailAddress ea = new EmailAddress(u, "test@example.com", Locale.ENGLISH);
+        TestMail tm = getMailReceiver().receive();
+        Pattern p = Pattern.compile(".*hash=(.*)");
+        Matcher m = p.matcher(tm.extractLink());
+        assertTrue(m.matches());
+        String correctToken = m.group(1);
+
+        // Assert initial state
+        assertFalse(ea.isVerified());
+
+        // wrong hashes
+        assertFalse(ea.isVerifyable(correctToken + "w"));
+        assertFalse(ea.isVerifyable(""));
+        // correct token
+        assertTrue(ea.isVerifyable(correctToken));
+        // state transition not possible with wrong token
+        org.hamcrest.Matcher<String> isInvalidToken = verificationDoesNotWork(ea);
+        assertThat(correctToken + "a", isInvalidToken);
+        assertThat("", isInvalidToken);
+
+        // state transition
+        assertFalse(ea.isVerified());
+        ea.verify(correctToken);
+        assertTrue(ea.isVerified());
+
+        // no token is correct anymore
+        assertFalse(ea.isVerifyable(correctToken));
+        assertFalse(ea.isVerifyable(""));
+        // no verification is possible anymore
+        assertThat(correctToken + "a", isInvalidToken);
+        assertThat(correctToken, isInvalidToken);
+        assertThat("", isInvalidToken);
+    }
+
+    private org.hamcrest.Matcher<String> verificationDoesNotWork(final EmailAddress ea) {
+        return new CustomMatcher<String>("Invalid token for validation.") {
+
+            @Override
+            public boolean matches(Object item) {
+                if ( !(item instanceof String)) {
+                    return false;
+                }
+                String s = (String) item;
+                try {
+                    ea.verify(s);
+                    return false;
+                } catch (IllegalArgumentException e) {
+                    return true;
+                } catch (GigiApiException e) {
+                    throw new Error(e);
+                }
+            }
+        };
+    }
+}