1 package club.wpia.gigi.util;
3 import java.io.IOException;
4 import java.text.ParseException;
5 import java.util.Calendar;
6 import java.util.GregorianCalendar;
7 import java.util.HashMap;
10 import club.wpia.gigi.GigiApiException;
11 import club.wpia.gigi.database.GigiPreparedStatement;
12 import club.wpia.gigi.database.GigiResultSet;
13 import club.wpia.gigi.dbObjects.Country;
14 import club.wpia.gigi.dbObjects.Group;
15 import club.wpia.gigi.dbObjects.Name;
16 import club.wpia.gigi.dbObjects.User;
17 import club.wpia.gigi.dbObjects.Verification.VerificationType;
18 import club.wpia.gigi.localisation.Language;
19 import club.wpia.gigi.output.ArrayIterable;
20 import club.wpia.gigi.output.DateSelector;
21 import club.wpia.gigi.output.template.MailTemplate;
22 import club.wpia.gigi.output.template.SprintfCommand;
26 // minimum date range between 2 verifications of the RA-Agent to the same
28 public final static int LIMIT_DAYS_VERIFICATION = TimeConditions.getInstance().getVerificationLimitDays();
30 // maximum date range from date when the verification took place and the
31 // entering to the system
32 public final static int LIMIT_MAX_MONTHS_VERIFICATION = TimeConditions.getInstance().getVerificationMaxAgeMonths();
34 public static void writeUserAgreement(User member, String document, String method, String comment, boolean active, int secmemid) {
35 try (GigiPreparedStatement q = new GigiPreparedStatement("INSERT INTO `user_agreements` SET `memid`=?, `secmemid`=?," + " `document`=?,`date`=NOW(), `active`=?,`method`=?,`comment`=?")) {
36 q.setInt(1, member.getId());
37 q.setInt(2, secmemid);
38 q.setString(3, document);
39 q.setBoolean(4, active);
40 q.setString(5, method);
41 q.setString(6, comment);
46 public static boolean checkVerificationIsPossible(User agent, Name target) {
47 try (GigiPreparedStatement ps = new GigiPreparedStatement("SELECT 1 FROM `notary` where `to`=? and `from`=? and `method` = ? ::`notaryType` AND `deleted` IS NULL AND `when` > (now() - interval '1 days' * ?::INTEGER)")) {
48 ps.setInt(1, target.getId());
49 ps.setInt(2, agent.getId());
50 ps.setEnum(3, VerificationType.FACE_TO_FACE);
51 ps.setInt(4, LIMIT_DAYS_VERIFICATION);
52 GigiResultSet rs = ps.executeQuery();
57 public static final Group AGENT_BLOCKED = Group.BLOCKED_AGENT;
59 public static final Group APPLICANT_BLOCKED = Group.BLOCKED_APPLICANT;
61 public static final Group VERIFY_NOTIFICATION = Group.VERIFY_NOTIFICATION;
64 * This method verifies another user.
66 * @see User#canVerify() (for agent)
67 * @see #checkVerificationIsPossible(User, User) (for agent or applicant)
69 * the person that wants to verify
71 * the person that should be verified
72 * @param applicantName
73 * the Name that was personally verified
75 * the Date of birth that the agent verified
77 * the points that should be awarded in total
79 * the location where the verification took place
81 * the date when the verification took place
82 * @throws GigiApiException
83 * if the verification fails (for various reasons)
85 public synchronized static void verify(User agent, User applicant, Name applicantName, DayDate dob, int awarded, String location, String date, VerificationType type, Country country) throws GigiApiException {
86 may(agent, applicant, VerificationType.FACE_TO_FACE);
87 GigiApiException gae = new GigiApiException();
88 if ( !gae.isEmpty()) {
91 if (date == null || date.equals("")) {
92 gae.mergeInto(new GigiApiException("You must enter the date when you met the applicant."));
95 DayDate d = new DayDate(DateSelector.getDateFormat().parse(date).getTime());
96 if (d.start().getTime() > System.currentTimeMillis()) {
97 gae.mergeInto(new GigiApiException("You must not enter a date in the future."));
99 Calendar gc = GregorianCalendar.getInstance();
100 gc.setTimeInMillis(System.currentTimeMillis());
101 gc.add(Calendar.MONTH, -LIMIT_MAX_MONTHS_VERIFICATION);
102 if (d.getTime() < gc.getTimeInMillis()) {
103 gae.mergeInto(new GigiApiException(SprintfCommand.createSimple("Verifications older than {0} months are not accepted.", LIMIT_MAX_MONTHS_VERIFICATION)));
105 } catch (ParseException e) {
106 gae.mergeInto(new GigiApiException("You must enter the date in this format: YYYY-MM-DD."));
109 // check location, min 3 characters
110 if (location == null || location.equals("")) {
111 gae.mergeInto(new GigiApiException("You failed to enter a location of your meeting."));
112 } else if (location.length() <= 2) {
113 gae.mergeInto(new GigiApiException("You must enter a location with at least 3 characters eg town and country."));
116 if (country == null) {
117 gae.mergeInto(new GigiApiException("You failed to enter the country of your meeting."));
120 synchronized (applicant) {
121 if (agent.getId() == applicant.getId()) {
122 throw new GigiApiException("You cannot verify yourself.");
124 if (applicantName.getOwner() != applicant) {
125 throw new GigiApiException("Internal error, name does not belong to applicant.");
127 if ( !agent.canVerify()) {
128 throw new GigiApiException("You are not an RA-Agent.");
131 if ( !checkVerificationIsPossible(agent, applicantName)) {
132 gae.mergeInto(new GigiApiException(SprintfCommand.createSimple("You have already verified this applicant within the last {0} days.", LIMIT_DAYS_VERIFICATION)));
135 if ( !applicant.getDoB().equals(dob)) {
136 gae.mergeInto(new GigiApiException("The person you are verifying changed his personal details."));
140 gae.mergeInto(new GigiApiException("The points you are trying to award are out of range."));
142 if (type == VerificationType.NUCLEUS) {
144 gae.mergeInto(new GigiApiException("The points you are trying to award are out of range."));
147 if (awarded > agent.getMaxVerifyPoints()) {
148 gae.mergeInto(new GigiApiException("The points you are trying to award are out of range."));
153 if ( !gae.isEmpty()) {
157 if (type == VerificationType.FACE_TO_FACE) {
158 verifyF2F(agent, applicant, applicantName, awarded, location, date, country);
159 } else if (type == VerificationType.NUCLEUS) {
160 verifyNucleus(agent, applicant, applicantName, awarded, location, date, country);
161 } else if (type == VerificationType.TTP_ASSISTED) {
162 verifyTTP(agent, applicant, applicantName, awarded, location, date, country);
164 throw new GigiApiException(SprintfCommand.createSimple("Unknown Verification type: {0}", type.toString()));
166 agent.invalidateMadeVerifications();
167 applicant.invalidateReceivedVerifications();
171 private static void verifyF2F(User agent, User applicant, Name name, int awarded, String location, String date, Country country) throws GigiApiException {
172 may(agent, applicant, VerificationType.FACE_TO_FACE);
173 try (GigiPreparedStatement ps = new GigiPreparedStatement("INSERT INTO `notary` SET `from`=?, `to`=?, `points`=?, `location`=?, `date`=?, `country`=?")) {
174 ps.setInt(1, agent.getId());
175 ps.setInt(2, name.getId());
176 ps.setInt(3, awarded);
177 ps.setString(4, location);
178 ps.setString(5, date);
179 ps.setString(6, country.getCode());
184 private static void verifyTTP(User agent, User applicant, Name name, int awarded, String location, String date, Country country) throws GigiApiException {
185 may(agent, applicant, VerificationType.TTP_ASSISTED);
186 try (GigiPreparedStatement ps = new GigiPreparedStatement("INSERT INTO `notary` SET `from`=?, `to`=?, `points`=?, `location`=?, `date`=?, `country`=?, `method`='TTP-Assisted'")) {
187 ps.setInt(1, agent.getId());
188 ps.setInt(2, name.getId());
189 ps.setInt(3, awarded);
190 ps.setString(4, location);
191 ps.setString(5, date);
192 ps.setString(6, country.getCode());
194 applicant.revokeGroup(agent, Group.TTP_APPLICANT);
198 public static void may(User agent, User applicant, VerificationType t) throws GigiApiException {
199 if (applicant.isInGroup(APPLICANT_BLOCKED)) {
200 throw new GigiApiException("The applicant is blocked.");
202 if (agent.isInGroup(AGENT_BLOCKED)) {
203 throw new GigiApiException("The RA Agent is blocked.");
206 if (t == VerificationType.NUCLEUS) {
207 if ( !agent.isInGroup(Group.NUCLEUS_AGENT)) {
208 throw new GigiApiException("RA Agent needs to be Nucleus RA Agent.");
211 } else if (t == VerificationType.TTP_ASSISTED) {
212 if ( !agent.isInGroup(Group.TTP_AGENT)) {
213 throw new GigiApiException("RA Agent needs to be TTP RA Agent.");
215 if ( !applicant.isInGroup(Group.TTP_APPLICANT)) {
216 throw new GigiApiException("Applicant needs to be TTP Applicant.");
219 } else if (t == VerificationType.FACE_TO_FACE) {
222 throw new GigiApiException("Verification type not possible.");
225 private static void verifyNucleus(User agent, User applicant, Name name, int awarded, String location, String date, Country country) throws GigiApiException {
226 may(agent, applicant, VerificationType.NUCLEUS);
227 // Do up to 35 points as f2f
228 int f2fPoints = Math.min(agent.getMaxVerifyPoints(), awarded);
229 verifyF2F(agent, applicant, name, f2fPoints, location, date, country);
231 awarded -= f2fPoints;
236 // Verify remaining points as "Nucleus Bonus"
237 // Valid for 4 Weeks = 28 days
238 try (GigiPreparedStatement ps = new GigiPreparedStatement("INSERT INTO `notary` SET `from`=?, `to`=?, `points`=?, `location`=?, `date`=?, `country`=?, `method`='Nucleus Bonus', `expire` = CURRENT_TIMESTAMP + interval '28 days'")) {
239 ps.setInt(1, agent.getId());
240 ps.setInt(2, name.getId());
241 ps.setInt(3, awarded);
242 ps.setString(4, location);
243 ps.setString(5, date);
244 ps.setString(6, country.getCode());
249 public synchronized static void verifyAll(User agent, User applicant, DayDate dob, int awarded, String location, String date, VerificationType type, Name[] toVerify, Country country) throws GigiApiException {
250 if (toVerify.length == 0) {
251 throw new GigiApiException("You must confirm at least one name to verify an account.");
253 boolean[] hadLessThan50Points = new boolean[toVerify.length];
254 boolean hadTotalLessThan100 = applicant.getVerificationPoints() < 100;
255 for (int i = 0; i < toVerify.length; i++) {
256 hadLessThan50Points[i] = toVerify[i].getVerificationPoints() < 50;
258 verify(agent, applicant, toVerify[i], dob, awarded, location, date, type, country);
260 sendVerificationNotificationApplicant(agent, applicant, toVerify, awarded, hadLessThan50Points, hadTotalLessThan100);
261 if (agent.isInGroup(VERIFY_NOTIFICATION)) {
262 sendVerificationNotificationAgent(agent, applicant, toVerify, awarded, location, date, country);
266 private static final MailTemplate verificationEntered = new MailTemplate(Notary.class.getResource("VerificationEntered.templ"));
268 private static final MailTemplate verificationAgentEntered = new MailTemplate(Notary.class.getResource("VerificationAgentEntered.templ"));
270 private static void sendVerificationNotificationApplicant(User agent, User applicant, Name[] toVerify, final int awarded, final boolean[] hadLessThan50Points, boolean hadTotalLessThan100) {
271 HashMap<String, Object> mailVars = new HashMap<>();
272 mailVars.put("agent", agent.getPreferredName().toString());
273 mailVars.put("names", new ArrayIterable<Name>(toVerify) {
276 public void apply(Name t, Language l, Map<String, Object> vars) {
277 int totalVP = t.getVerificationPoints();
278 vars.put("name", t.toString());
279 vars.put("points", Integer.toString(awarded));
280 vars.put("total", totalVP);
282 vars.put("rem", (50 - totalVP));
283 vars.remove("gotGreater");
284 } else if (hadLessThan50Points[i]) {
285 vars.put("gotGreater", true);
292 int grandTotalVP = applicant.getVerificationPoints();
293 if (grandTotalVP >= 50 && grandTotalVP < 100) {
294 mailVars.put("remAll", (100 - grandTotalVP));
295 mailVars.remove("gotGreaterAll");
296 } else if (hadTotalLessThan100) {
297 mailVars.put("gotGreaterAll", true);
298 mailVars.remove("remAll");
301 verificationEntered.sendMail(Language.getInstance(applicant.getPreferredLocale()), mailVars, applicant.getEmail());
302 } catch (IOException e) {
307 private static void sendVerificationNotificationAgent(User agent, User applicant, Name[] toVerify, final int awarded, String location, String date, Country country) {
308 HashMap<String, Object> mailVars = new HashMap<>();
309 mailVars.put("email", applicant.getEmail());
310 mailVars.put("location", location);
311 mailVars.put("date", date);
312 mailVars.put("country", country.getName());
313 mailVars.put("points", Integer.toString(awarded));
314 mailVars.put("names", new ArrayIterable<Name>(toVerify) {
317 public void apply(Name t, Language l, Map<String, Object> vars) {
318 vars.put("name", t.toString());
324 verificationAgentEntered.sendMail(Language.getInstance(applicant.getPreferredLocale()), mailVars, agent.getEmail());
325 } catch (IOException e) {