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