Merge "add: show more certificates on the "roots" page"
[gigi.git] / tests / club / wpia / gigi / pages / wot / TestVerification.java
1 package club.wpia.gigi.pages.wot;
2
3 import static org.hamcrest.CoreMatchers.*;
4 import static org.junit.Assert.*;
5
6 import java.io.IOException;
7 import java.io.UnsupportedEncodingException;
8 import java.net.HttpURLConnection;
9 import java.net.MalformedURLException;
10 import java.net.URLConnection;
11 import java.net.URLEncoder;
12 import java.sql.SQLException;
13 import java.sql.Timestamp;
14 import java.text.SimpleDateFormat;
15 import java.util.Calendar;
16 import java.util.Date;
17 import java.util.regex.Pattern;
18
19 import org.hamcrest.Matcher;
20 import org.junit.Before;
21 import org.junit.Test;
22
23 import club.wpia.gigi.GigiApiException;
24 import club.wpia.gigi.database.GigiPreparedStatement;
25 import club.wpia.gigi.dbObjects.Country;
26 import club.wpia.gigi.dbObjects.Group;
27 import club.wpia.gigi.dbObjects.User;
28 import club.wpia.gigi.pages.account.MyDetails;
29 import club.wpia.gigi.testUtils.IOUtils;
30 import club.wpia.gigi.testUtils.ManagedTest;
31 import club.wpia.gigi.testUtils.TestEmailReceiver.TestMail;
32 import club.wpia.gigi.util.DayDate;
33 import club.wpia.gigi.util.Notary;
34
35 public class TestVerification extends ManagedTest {
36
37     private String agentM;
38
39     private String applicantM;
40
41     private int applicantName;
42
43     private String cookie;
44
45     @Before
46     public void setup() throws IOException {
47         clearCaches();
48         agentM = createUniqueName() + "@example.org";
49         applicantM = createUniqueName() + "@example.org";
50
51         createVerificationUser("a", "b", agentM, TEST_PASSWORD);
52         int applicantId = createVerifiedUser("a", "c", applicantM, TEST_PASSWORD);
53         applicantName = User.getById(applicantId).getPreferredName().getId();
54
55         cookie = login(agentM, TEST_PASSWORD);
56     }
57
58     private Matcher<String> isVerificationForm() {
59         return containsString("<select name=\"verificationType\">");
60     }
61
62     @Test
63     public void testVerifySearch() throws IOException {
64         String loc = search("email=" + URLEncoder.encode(applicantM, "UTF-8") + "&day=1&month=1&year=1910");
65         assertThat(loc, isVerificationForm());
66     }
67
68     @Test
69     public void testVerifySearchEmail() throws IOException {
70         String loc = search("email=1" + URLEncoder.encode(applicantM, "UTF-8") + "&day=1&month=1&year=1910");
71         assertThat(loc, not(isVerificationForm()));
72     }
73
74     @Test
75     public void testVerifySearchDobInvalid() throws IOException {
76         String loc = search("email=" + URLEncoder.encode(applicantM, "UTF-8") + "&day=1&month=1&year=mal");
77         assertThat(loc, not(isVerificationForm()));
78     }
79
80     @Test
81     public void testVerifySearchDob() throws IOException {
82         String loc = search("email=" + URLEncoder.encode(applicantM, "UTF-8") + "&day=2&month=1&year=1910");
83         assertThat(loc, not(isVerificationForm()));
84         loc = search("email=" + URLEncoder.encode(applicantM, "UTF-8") + "&day=1&month=2&year=1910");
85         assertThat(loc, not(isVerificationForm()));
86         loc = search("email=" + URLEncoder.encode(applicantM, "UTF-8") + "&day=1&month=1&year=1911");
87         assertThat(loc, not(isVerificationForm()));
88     }
89
90     private String search(String query) throws MalformedURLException, IOException, UnsupportedEncodingException {
91         URLConnection uc = get(cookie, VerifyPage.PATH);
92         uc.setDoOutput(true);
93         uc.getOutputStream().write(("search&" + query).getBytes("UTF-8"));
94         uc.getOutputStream().flush();
95
96         return IOUtils.readURL(uc);
97     }
98
99     @Test
100     public void testVerifyForm() throws IOException {
101         String body = executeSuccess("date=" + validVerificationDateString() + "&location=testcase&countryCode=DE&certify=1&rules=1&assertion=1&points=10");
102         assertThat(body, containsString("10"));
103         assertThat(body, containsString(applicantM));
104         getMailReceiver().receive(applicantM);
105     }
106
107     @Test
108     public void testVerifyFormEmpty() throws IOException {
109         URLConnection uc = buildupVerifyFormConnection(true);
110         uc.getOutputStream().write(("date=" + validVerificationDateString() + "&location=testcase&countryCode=DE&rules=1&assertion=1&points=10").getBytes("UTF-8"));
111         uc.getOutputStream().flush();
112         String data = IOUtils.readURL(uc);
113         assertThat(data, hasError());
114     }
115
116     @Test
117     public void testVerifyFormContainsData() throws IOException {
118         URLConnection uc = buildupVerifyFormConnection(true);
119         uc.getOutputStream().write(("verifiedName=" + applicantName + "&date=" + validVerificationDateString() + "&location=testcase&countryCode=DE&rules=1&assertion=1&points=10").getBytes("UTF-8"));
120         uc.getOutputStream().flush();
121         String data = IOUtils.readURL(uc);
122         assertThat(data, containsString(validVerificationDateString()));
123         assertThat(data, containsString("testcase"));
124     }
125
126     @Test
127     public void testVerifyFormNoCSRF() throws IOException {
128         // override csrf
129         HttpURLConnection uc = (HttpURLConnection) buildupVerifyFormConnection(false);
130         uc.getOutputStream().write(("date=" + validVerificationDateString() + "&location=testcase&countryCode=DE&certify=1&rules=1&assertion=1&points=10").getBytes("UTF-8"));
131         uc.getOutputStream().flush();
132         assertEquals(500, uc.getResponseCode());
133         uc.getErrorStream().close();
134     }
135
136     @Test
137     public void testVerifyFormWrongCSRF() throws IOException {
138         // override csrf
139         HttpURLConnection uc = (HttpURLConnection) buildupVerifyFormConnection(false);
140         uc.getOutputStream().write(("date=" + validVerificationDateString() + "&location=testcase&countryCode=DE&certify=1&rules=1&assertion=1&points=10&csrf=aragc").getBytes("UTF-8"));
141         uc.getOutputStream().flush();
142         assertEquals(500, uc.getResponseCode());
143         uc.getErrorStream().close();
144     }
145
146     @Test
147     public void testVerifyFormRaceDoB() throws IOException, SQLException {
148         testVerifyFormRace(false);
149     }
150
151     @Test
152     public void testVerifyFormRaceDoBBlind() throws IOException, SQLException {
153         testVerifyFormRace(true);
154     }
155
156     public void testVerifyFormRace(boolean succeed) throws IOException, SQLException {
157         URLConnection uc = buildupVerifyFormConnection(true);
158
159         String applicantCookie = login(applicantM, TEST_PASSWORD);
160         String newDob = "day=1&month=1&year=" + ( !succeed ? 1911 : 1910);
161
162         assertNull(executeBasicWebInteraction(applicantCookie, MyDetails.PATH, newDob + "&action=updateDoB", 0));
163
164         uc.getOutputStream().write(("verifiedName=" + applicantName + "&date=" + validVerificationDateString() + "&location=testcase&countryCode=DE&certify=1&rules=1&assertion=1&points=10").getBytes("UTF-8"));
165         uc.getOutputStream().flush();
166         String error = fetchStartErrorMessage(IOUtils.readURL(uc));
167         if (succeed) {
168             assertNull(error);
169             getMailReceiver().receive(applicantM);
170         } else {
171             assertTrue(error, !error.startsWith("</div>"));
172             assertThat(error, containsString("changed his personal details"));
173         }
174     }
175
176     @Test
177     public void testVerifyFormFuture() throws IOException {
178         SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
179         int year = Integer.parseInt(sdf.format(new Date(System.currentTimeMillis()))) + 2;
180         executeFails("date=" + year + "-01-01&location=testcase&countryCode=DE&certify=1&rules=1&assertion=1&points=10");
181     }
182
183     @Test
184     public void testVerifyFormFutureOK() throws IOException {
185         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
186         Calendar c = Calendar.getInstance();
187         c.setTimeInMillis(System.currentTimeMillis());
188         c.add(Calendar.HOUR_OF_DAY, 12);
189
190         executeSuccess("date=" + sdf.format(new Date(c.getTimeInMillis())) + "&location=testcase&countryCode=DE&certify=1&rules=1&assertion=1&points=10");
191         getMailReceiver().receive(applicantM);
192     }
193
194     @Test
195     public void testVerifyFormPastInRange() throws IOException {
196         executeSuccess("date=" + validVerificationDateString() + "&location=testcase&countryCode=DE&certify=1&rules=1&assertion=1&points=10");
197         getMailReceiver().receive(applicantM);
198     }
199
200     @Test
201     public void testVerifyFormPastOnLimit() throws IOException {
202         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
203         Calendar c = Calendar.getInstance();
204         c.setTimeInMillis(System.currentTimeMillis());
205         c.add(Calendar.MONTH, -Notary.LIMIT_MAX_MONTHS_VERIFICATION);
206         c.add(Calendar.DAY_OF_MONTH, 1);
207
208         executeSuccess("date=" + sdf.format(new Date(c.getTimeInMillis())) + "&location=testcase&countryCode=DE&certify=1&rules=1&assertion=1&points=10");
209         getMailReceiver().receive(applicantM);
210     }
211
212     @Test
213     public void testVerifyFormPastOutOfRange() throws IOException {
214         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
215         Calendar c = Calendar.getInstance();
216         c.setTimeInMillis(System.currentTimeMillis());
217         c.add(Calendar.MONTH, -Notary.LIMIT_MAX_MONTHS_VERIFICATION);
218
219         executeFails("date=" + sdf.format(new Date(c.getTimeInMillis())) + "&location=testcase&countryCode=DE&certify=1&rules=1&assertion=1&points=10");
220     }
221
222     @Test
223     public void testVerifyFormNoLoc() throws IOException {
224         executeFails("date=" + validVerificationDateString() + "&location=a&countryCode=DE&certify=1&rules=1&assertion=1&points=10");
225         executeFails("date=" + validVerificationDateString() + "&location=&countryCode=DE&certify=1&rules=1&assertion=1&points=10");
226     }
227
228     @Test
229     public void testVerifyFormInvalDate() throws IOException {
230         executeFails("date=20000101&location=testcase&countryCode=DE&certify=1&rules=1&assertion=1&points=10");
231         executeFails("date=&location=testcase&countryCode=DE&certify=1&rules=1&assertion=1&points=10");
232     }
233
234     @Test
235     public void testVerifyFormBoxes() throws IOException {
236         executeFails("date=" + validVerificationDateString() + "&location=testcase&countryCode=DE&certify=0&rules=1&assertion=1&points=10");
237         executeFails("date=" + validVerificationDateString() + "&location=testcase&countryCode=DE&certify=1&rules=&assertion=1&points=10");
238         executeFails("date=" + validVerificationDateString() + "&location=testcase&countryCode=DE&certify=1&rules=1&assertion=z&points=10");
239     }
240
241     @Test
242     public void testVerifyListingValid() throws IOException, GigiApiException {
243         String uniqueLoc = createUniqueName();
244         executeSuccess("date=" + validVerificationDateString() + "&location=" + uniqueLoc + "&countryCode=DE&certify=1&rules=1&assertion=1&points=10");
245         getMailReceiver().receive(applicantM);
246
247         String cookie = login(applicantM, TEST_PASSWORD);
248         URLConnection url = get(cookie, Points.PATH);
249         String resp = IOUtils.readURL(url);
250         resp = resp.split(Pattern.quote("</table>"))[1];
251         assertThat(resp, containsString(uniqueLoc));
252         assertThat(resp, containsString(Country.getCountryByCode("DE", Country.CountryCodeType.CODE_2_CHARS).getName()));
253     }
254
255     @Test
256     public void testAgentListingValid() throws IOException, GigiApiException {
257         String uniqueLoc = createUniqueName();
258         executeSuccess("date=" + validVerificationDateString() + "&location=" + uniqueLoc + "&countryCode=DE&certify=1&rules=1&assertion=1&points=10");
259         getMailReceiver().receive(applicantM);
260
261         String cookie = login(agentM, TEST_PASSWORD);
262         URLConnection url = get(cookie, Points.PATH);
263         String resp = IOUtils.readURL(url);
264         resp = resp.split(Pattern.quote("</table>"))[2];
265         assertThat(resp, containsString(uniqueLoc));
266         assertThat(resp, containsString(Country.getCountryByCode("DE", Country.CountryCodeType.CODE_2_CHARS).getName()));
267     }
268
269     private void executeFails(String query) throws MalformedURLException, IOException {
270         assertThat(execute(query), hasError());
271
272     }
273
274     private String executeSuccess(String query) throws MalformedURLException, IOException {
275         String response = execute(query);
276         assertThat(response, hasNoError());
277         return response;
278     }
279
280     private String execute(String query) throws MalformedURLException, IOException {
281         URLConnection uc = buildupVerifyFormConnection(true);
282         uc.getOutputStream().write(("verifiedName=" + applicantName + "&" + query).getBytes("UTF-8"));
283         uc.getOutputStream().flush();
284         return IOUtils.readURL(uc);
285     }
286
287     private URLConnection buildupVerifyFormConnection(boolean doCSRF) throws MalformedURLException, IOException {
288         return buildupVerifyFormConnection(cookie, applicantM, doCSRF);
289     }
290
291     public static URLConnection buildupVerifyFormConnection(String cookie, String email, boolean doCSRF) throws MalformedURLException, IOException {
292         URLConnection uc = get(cookie, VerifyPage.PATH);
293         uc.setDoOutput(true);
294         uc.getOutputStream().write(("email=" + URLEncoder.encode(email, "UTF-8") + "&day=1&month=1&year=1910&search").getBytes("UTF-8"));
295
296         String csrf = getCSRF(uc);
297         uc = get(cookie, VerifyPage.PATH);
298         uc.setDoOutput(true);
299         if (doCSRF) {
300             uc.getOutputStream().write(("csrf=" + csrf + "&").getBytes("UTF-8"));
301         }
302         return uc;
303     }
304
305     @Test
306     public void testMultipleVerification() throws IOException {
307
308         User users[] = User.findByEmail(agentM);
309         int agentID = users[0].getId();
310
311         users = User.findByEmail(applicantM);
312         int applicantID = users[0].getId();
313
314         // enter first entry 200 days in the past
315         try (GigiPreparedStatement ps = new GigiPreparedStatement("INSERT INTO `notary` SET `from`=?, `to`=?, `points`=?, `location`=?, `date`=?, `when`=? ")) {
316             ps.setInt(1, agentID);
317             ps.setInt(2, applicantID);
318             ps.setInt(3, 10);
319             ps.setString(4, "test-location");
320             ps.setString(5, "2010-01-01");
321             ps.setTimestamp(6, new Timestamp(System.currentTimeMillis() - DayDate.MILLI_DAY * 200));
322             ps.execute();
323         }
324
325         // enter second entry
326         String uniqueLoc = createUniqueName();
327         executeSuccess("date=" + validVerificationDateString() + "&location=" + uniqueLoc + "&countryCode=DE&certify=1&rules=1&assertion=1&points=10");
328         getMailReceiver().receive(applicantM);
329
330         // enter third entry on the same day
331         URLConnection uc = get(cookie, VerifyPage.PATH);
332         uc.setDoOutput(true);
333         uc.getOutputStream().write(("email=" + URLEncoder.encode(applicantM, "UTF-8") + "&day=1&month=1&year=1910&search").getBytes("UTF-8"));
334         assertThat(IOUtils.readURL(uc), hasError());
335
336     }
337
338     @Test
339     public void testVerifyFormNoCountry() throws IOException {
340         executeFails("date=" + validVerificationDateString() + "&location=testcase&countryCode=&certify=1&rules=1&assertion=1&points=10");
341     }
342
343     @Test
344     public void testRANotificationSet() throws IOException, GigiApiException {
345         getMailReceiver().assertEmpty();
346
347         User users[] = User.findByEmail(agentM);
348         assertTrue("user RA Agent not found", users != null && users.length > 0);
349
350         User u = users[0];
351         u.grantGroup(u, Group.VERIFY_NOTIFICATION);
352         clearCaches();
353         cookie = login(agentM, TEST_PASSWORD);
354
355         String targetMail = u.getEmail();
356
357         // enter verification
358         String uniqueLoc = createUniqueName();
359         executeSuccess("date=" + validVerificationDateString() + "&location=" + uniqueLoc + "&countryCode=DE&certify=1&rules=1&assertion=1&points=10");
360         getMailReceiver().receive(applicantM);
361         TestMail tm = getMailReceiver().receive(targetMail);
362         assertThat(tm.getMessage(), containsString("You entered a verification for the account with email address " + applicantM));
363
364     }
365
366     @Test
367     public void testRANotificationNotSet() throws IOException, GigiApiException {
368         getMailReceiver().assertEmpty();
369
370         User users[] = User.findByEmail(agentM);
371         assertTrue("user RA Agent not found", users != null && users.length > 0);
372
373         User u = users[0];
374         u.revokeGroup(u, Group.VERIFY_NOTIFICATION);
375         clearCaches();
376         cookie = login(agentM, TEST_PASSWORD);
377
378         // enter verification
379         String uniqueLoc = createUniqueName();
380         executeSuccess("date=" + validVerificationDateString() + "&location=" + uniqueLoc + "&countryCode=DE&certify=1&rules=1&assertion=1&points=10");
381
382         TestMail tm;
383
384         tm = getMailReceiver().receive(applicantM);
385         assertThat(tm.getMessage(), not(containsString("You entered a verification for the account with email address " + applicantM)));
386
387     }
388 }