upd: terminology in code
[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         executeSuccess("date=" + validVerificationDateString() + "&location=testcase&countryCode=DE&certify=1&rules=1&assertion=1&points=10");
102     }
103
104     @Test
105     public void testVerifyFormEmpty() throws IOException {
106         URLConnection uc = buildupVerifyFormConnection(true);
107         uc.getOutputStream().write(("date=" + validVerificationDateString() + "&location=testcase&countryCode=DE&rules=1&assertion=1&points=10").getBytes("UTF-8"));
108         uc.getOutputStream().flush();
109         String data = IOUtils.readURL(uc);
110         assertThat(data, hasError());
111     }
112
113     @Test
114     public void testVerifyFormContainsData() throws IOException {
115         URLConnection uc = buildupVerifyFormConnection(true);
116         uc.getOutputStream().write(("verifiedName=" + applicantName + "&date=" + validVerificationDateString() + "&location=testcase&countryCode=DE&rules=1&assertion=1&points=10").getBytes("UTF-8"));
117         uc.getOutputStream().flush();
118         String data = IOUtils.readURL(uc);
119         assertThat(data, containsString(validVerificationDateString()));
120         assertThat(data, containsString("testcase"));
121     }
122
123     @Test
124     public void testVerifyFormNoCSRF() throws IOException {
125         // override csrf
126         HttpURLConnection uc = (HttpURLConnection) buildupVerifyFormConnection(false);
127         uc.getOutputStream().write(("date=" + validVerificationDateString() + "&location=testcase&countryCode=DE&certify=1&rules=1&assertion=1&points=10").getBytes("UTF-8"));
128         uc.getOutputStream().flush();
129         assertEquals(500, uc.getResponseCode());
130     }
131
132     @Test
133     public void testVerifyFormWrongCSRF() throws IOException {
134         // override csrf
135         HttpURLConnection uc = (HttpURLConnection) buildupVerifyFormConnection(false);
136         uc.getOutputStream().write(("date=" + validVerificationDateString() + "&location=testcase&countryCode=DE&certify=1&rules=1&assertion=1&points=10&csrf=aragc").getBytes("UTF-8"));
137         uc.getOutputStream().flush();
138         assertEquals(500, uc.getResponseCode());
139     }
140
141     @Test
142     public void testVerifyFormRaceDoB() throws IOException, SQLException {
143         testVerifyFormRace(false);
144     }
145
146     @Test
147     public void testVerifyFormRaceDoBBlind() throws IOException, SQLException {
148         testVerifyFormRace(true);
149     }
150
151     public void testVerifyFormRace(boolean succeed) throws IOException, SQLException {
152         URLConnection uc = buildupVerifyFormConnection(true);
153
154         String applicantCookie = login(applicantM, TEST_PASSWORD);
155         String newDob = "day=1&month=1&year=" + ( !succeed ? 1911 : 1910);
156
157         assertNull(executeBasicWebInteraction(applicantCookie, MyDetails.PATH, newDob + "&action=updateDoB", 0));
158
159         uc.getOutputStream().write(("verifiedName=" + applicantName + "&date=" + validVerificationDateString() + "&location=testcase&countryCode=DE&certify=1&rules=1&assertion=1&points=10").getBytes("UTF-8"));
160         uc.getOutputStream().flush();
161         String error = fetchStartErrorMessage(IOUtils.readURL(uc));
162         if (succeed) {
163             assertNull(error);
164         } else {
165             assertTrue(error, !error.startsWith("</div>"));
166             assertThat(error, containsString("changed his personal details"));
167         }
168     }
169
170     @Test
171     public void testVerifyFormFuture() throws IOException {
172         SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
173         int year = Integer.parseInt(sdf.format(new Date(System.currentTimeMillis()))) + 2;
174         executeFails("date=" + year + "-01-01&location=testcase&countryCode=DE&certify=1&rules=1&assertion=1&points=10");
175     }
176
177     @Test
178     public void testVerifyFormFutureOK() throws IOException {
179         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
180         Calendar c = Calendar.getInstance();
181         c.setTimeInMillis(System.currentTimeMillis());
182         c.add(Calendar.HOUR_OF_DAY, 12);
183
184         executeSuccess("date=" + sdf.format(new Date(c.getTimeInMillis())) + "&location=testcase&countryCode=DE&certify=1&rules=1&assertion=1&points=10");
185     }
186
187     @Test
188     public void testVerifyFormPastInRange() throws IOException {
189         executeSuccess("date=" + validVerificationDateString() + "&location=testcase&countryCode=DE&certify=1&rules=1&assertion=1&points=10");
190     }
191
192     @Test
193     public void testVerifyFormPastOnLimit() throws IOException {
194         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
195         Calendar c = Calendar.getInstance();
196         c.setTimeInMillis(System.currentTimeMillis());
197         c.add(Calendar.MONTH, -Notary.LIMIT_MAX_MONTHS_VERIFICATION);
198         c.add(Calendar.DAY_OF_MONTH, 1);
199
200         executeSuccess("date=" + sdf.format(new Date(c.getTimeInMillis())) + "&location=testcase&countryCode=DE&certify=1&rules=1&assertion=1&points=10");
201     }
202
203     @Test
204     public void testVerifyFormPastOutOfRange() throws IOException {
205         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
206         Calendar c = Calendar.getInstance();
207         c.setTimeInMillis(System.currentTimeMillis());
208         c.add(Calendar.MONTH, -Notary.LIMIT_MAX_MONTHS_VERIFICATION);
209
210         executeFails("date=" + sdf.format(new Date(c.getTimeInMillis())) + "&location=testcase&countryCode=DE&certify=1&rules=1&assertion=1&points=10");
211     }
212
213     @Test
214     public void testVerifyFormNoLoc() throws IOException {
215         executeFails("date=" + validVerificationDateString() + "&location=a&countryCode=DE&certify=1&rules=1&assertion=1&points=10");
216         executeFails("date=" + validVerificationDateString() + "&location=&countryCode=DE&certify=1&rules=1&assertion=1&points=10");
217     }
218
219     @Test
220     public void testVerifyFormInvalDate() throws IOException {
221         executeFails("date=20000101&location=testcase&countryCode=DE&certify=1&rules=1&assertion=1&points=10");
222         executeFails("date=&location=testcase&countryCode=DE&certify=1&rules=1&assertion=1&points=10");
223     }
224
225     @Test
226     public void testVerifyFormBoxes() throws IOException {
227         executeFails("date=" + validVerificationDateString() + "&location=testcase&countryCode=DE&certify=0&rules=1&assertion=1&points=10");
228         executeFails("date=" + validVerificationDateString() + "&location=testcase&countryCode=DE&certify=1&rules=&assertion=1&points=10");
229         executeFails("date=" + validVerificationDateString() + "&location=testcase&countryCode=DE&certify=1&rules=1&assertion=z&points=10");
230     }
231
232     @Test
233     public void testVerifyListingValid() throws IOException, GigiApiException {
234         String uniqueLoc = createUniqueName();
235         execute("date=" + validVerificationDateString() + "&location=" + uniqueLoc + "&countryCode=DE&certify=1&rules=1&assertion=1&points=10");
236
237         String cookie = login(applicantM, TEST_PASSWORD);
238         URLConnection url = get(cookie, Points.PATH);
239         String resp = IOUtils.readURL(url);
240         resp = resp.split(Pattern.quote("</table>"))[1];
241         assertThat(resp, containsString(uniqueLoc));
242         assertThat(resp, containsString(Country.getCountryByCode("DE", Country.CountryCodeType.CODE_2_CHARS).getName()));
243     }
244
245     @Test
246     public void testAgentListingValid() throws IOException, GigiApiException {
247         String uniqueLoc = createUniqueName();
248         executeSuccess("date=" + validVerificationDateString() + "&location=" + uniqueLoc + "&countryCode=DE&certify=1&rules=1&assertion=1&points=10");
249         String cookie = login(agentM, TEST_PASSWORD);
250         URLConnection url = get(cookie, Points.PATH);
251         String resp = IOUtils.readURL(url);
252         resp = resp.split(Pattern.quote("</table>"))[2];
253         assertThat(resp, containsString(uniqueLoc));
254         assertThat(resp, containsString(Country.getCountryByCode("DE", Country.CountryCodeType.CODE_2_CHARS).getName()));
255     }
256
257     private void executeFails(String query) throws MalformedURLException, IOException {
258         assertThat(execute(query), hasError());
259
260     }
261
262     private void executeSuccess(String query) throws MalformedURLException, IOException {
263         assertThat(execute(query), hasNoError());
264
265     }
266
267     private String execute(String query) throws MalformedURLException, IOException {
268         URLConnection uc = buildupVerifyFormConnection(true);
269         uc.getOutputStream().write(("verifiedName=" + applicantName + "&" + query).getBytes("UTF-8"));
270         uc.getOutputStream().flush();
271         return IOUtils.readURL(uc);
272     }
273
274     private URLConnection buildupVerifyFormConnection(boolean doCSRF) throws MalformedURLException, IOException {
275         return buildupVerifyFormConnection(cookie, applicantM, doCSRF);
276     }
277
278     public static URLConnection buildupVerifyFormConnection(String cookie, String email, boolean doCSRF) throws MalformedURLException, IOException {
279         URLConnection uc = get(cookie, VerifyPage.PATH);
280         uc.setDoOutput(true);
281         uc.getOutputStream().write(("email=" + URLEncoder.encode(email, "UTF-8") + "&day=1&month=1&year=1910&search").getBytes("UTF-8"));
282
283         String csrf = getCSRF(uc);
284         uc = get(cookie, VerifyPage.PATH);
285         uc.setDoOutput(true);
286         if (doCSRF) {
287             uc.getOutputStream().write(("csrf=" + csrf + "&").getBytes("UTF-8"));
288         }
289         return uc;
290     }
291
292     @Test
293     public void testMultipleVerification() throws IOException {
294
295         User users[] = User.findByEmail(agentM);
296         int agentID = users[0].getId();
297
298         users = User.findByEmail(applicantM);
299         int applicantID = users[0].getId();
300
301         // enter first entry 200 days in the past
302         try (GigiPreparedStatement ps = new GigiPreparedStatement("INSERT INTO `notary` SET `from`=?, `to`=?, `points`=?, `location`=?, `date`=?, `when`=? ")) {
303             ps.setInt(1, agentID);
304             ps.setInt(2, applicantID);
305             ps.setInt(3, 10);
306             ps.setString(4, "test-location");
307             ps.setString(5, "2010-01-01");
308             ps.setTimestamp(6, new Timestamp(System.currentTimeMillis() - DayDate.MILLI_DAY * 200));
309             ps.execute();
310         }
311
312         // enter second entry
313         String uniqueLoc = createUniqueName();
314         executeSuccess("date=" + validVerificationDateString() + "&location=" + uniqueLoc + "&countryCode=DE&certify=1&rules=1&assertion=1&points=10");
315
316         // enter third entry on the same day
317         URLConnection uc = get(cookie, VerifyPage.PATH);
318         uc.setDoOutput(true);
319         uc.getOutputStream().write(("email=" + URLEncoder.encode(applicantM, "UTF-8") + "&day=1&month=1&year=1910&search").getBytes("UTF-8"));
320         assertThat(IOUtils.readURL(uc), hasError());
321
322     }
323
324     @Test
325     public void testVerifyFormNoCountry() throws IOException {
326         executeFails("date=" + validVerificationDateString() + "&location=testcase&countryCode=&certify=1&rules=1&assertion=1&points=10");
327     }
328
329     @Test
330     public void testRANotificationSet() throws IOException, GigiApiException {
331         getMailReceiver().clearMails();
332
333         User users[] = User.findByEmail(agentM);
334         assertTrue("user RA Agent not found", users != null && users.length > 0);
335
336         User u = users[0];
337         u.grantGroup(u, Group.VERIFY_NOTIFICATION);
338         clearCaches();
339         cookie = login(agentM, TEST_PASSWORD);
340
341         String targetMail = u.getEmail();
342
343         // enter verification
344         String uniqueLoc = createUniqueName();
345         executeSuccess("date=" + validVerificationDateString() + "&location=" + uniqueLoc + "&countryCode=DE&certify=1&rules=1&assertion=1&points=10");
346         TestMail tm;
347
348         do {
349             tm = getMailReceiver().receive();
350         } while ( !tm.getTo().equals(targetMail));
351         assertThat(tm.getMessage(), containsString("You entered a verification for the account with email address " + applicantM));
352
353     }
354
355     @Test
356     public void testRANotificationNotSet() throws IOException, GigiApiException {
357         getMailReceiver().clearMails();
358
359         User users[] = User.findByEmail(agentM);
360         assertTrue("user RA Agent not found", users != null && users.length > 0);
361
362         User u = users[0];
363         u.revokeGroup(u, Group.VERIFY_NOTIFICATION);
364         clearCaches();
365         cookie = login(agentM, TEST_PASSWORD);
366
367         // enter verification
368         String uniqueLoc = createUniqueName();
369         executeSuccess("date=" + validVerificationDateString() + "&location=" + uniqueLoc + "&countryCode=DE&certify=1&rules=1&assertion=1&points=10");
370
371         TestMail tm;
372
373         tm = getMailReceiver().receive();
374         assertThat(tm.getMessage(), not(containsString("You entered a verification for the account with email address " + applicantM)));
375
376     }
377 }