X-Git-Url: https://code.wpia.club/?p=gigi.git;a=blobdiff_plain;f=src%2Forg%2Fcacert%2Fgigi%2FdbObjects%2FEmailAddress.java;h=b2106d8bff71c901c3e51c1bfe9e6b3d8f160c8c;hp=7a053201c0cf6e1cc4a46d20202f297ffd8e5915;hb=a34a7467a812ed5735b8ce196f9821f75134250b;hpb=17c03c2e6e0b88545a4ebeb377fff0953e446c93 diff --git a/src/org/cacert/gigi/dbObjects/EmailAddress.java b/src/org/cacert/gigi/dbObjects/EmailAddress.java index 7a053201..b2106d8b 100644 --- a/src/org/cacert/gigi/dbObjects/EmailAddress.java +++ b/src/org/cacert/gigi/dbObjects/EmailAddress.java @@ -1,6 +1,8 @@ package org.cacert.gigi.dbObjects; import java.io.IOException; +import java.util.Date; +import java.util.LinkedList; import java.util.Locale; import org.cacert.gigi.GigiApiException; @@ -9,20 +11,21 @@ import org.cacert.gigi.database.GigiResultSet; import org.cacert.gigi.email.EmailProvider; import org.cacert.gigi.email.MailProbe; import org.cacert.gigi.localisation.Language; +import org.cacert.gigi.output.template.SprintfCommand; import org.cacert.gigi.util.RandomToken; public class EmailAddress implements IdCachable, Verifyable { + public static final int REPING_MINIMUM_DELAY = 5 * 60 * 1000; + private String address; private int id; private User owner; - private String hash = null; - private EmailAddress(int id) { - try (GigiPreparedStatement ps = new GigiPreparedStatement("SELECT `memid`, `email`, `hash` FROM `emails` WHERE `id`=? AND `deleted` IS NULL")) { + try (GigiPreparedStatement ps = new GigiPreparedStatement("SELECT `memid`, `email` FROM `emails` WHERE `id`=? AND `deleted` IS NULL")) { ps.setInt(1, id); GigiResultSet rs = ps.executeQuery(); @@ -32,17 +35,16 @@ public class EmailAddress implements IdCachable, Verifyable { this.id = id; owner = User.getById(rs.getInt(1)); address = rs.getString(2); - hash = rs.getString(3); } } public EmailAddress(User owner, String address, Locale mailLocale) throws GigiApiException { - if ( !EmailProvider.MAIL.matcher(address).matches()) { + address = address.toLowerCase(); + if ( !EmailProvider.isValidMailAddress(address)) { throw new IllegalArgumentException("Invalid email."); } this.address = address; this.owner = owner; - this.hash = RandomToken.generateToken(16); insert(Language.getInstance(mailLocale)); } @@ -52,26 +54,39 @@ public class EmailAddress implements IdCachable, Verifyable { if (id != 0) { throw new IllegalStateException("already inserted."); } - try (GigiPreparedStatement psCheck = new GigiPreparedStatement("SELECT 1 FROM `emails` WHERE email=? AND deleted is NULL"); GigiPreparedStatement ps = new GigiPreparedStatement("INSERT INTO `emails` SET memid=?, hash=?, email=?")) { - ps.setInt(1, owner.getId()); - ps.setString(2, hash); - ps.setString(3, address); + try (GigiPreparedStatement psCheck = new GigiPreparedStatement("SELECT 1 FROM `emails` WHERE email=? AND deleted is NULL")) { psCheck.setString(1, address); GigiResultSet res = psCheck.executeQuery(); if (res.next()) { throw new GigiApiException("The email address is already known to the system."); } + } + try (GigiPreparedStatement ps = new GigiPreparedStatement("INSERT INTO `emails` SET memid=?, email=?")) { + ps.setInt(1, owner.getId()); + ps.setString(2, address); ps.execute(); id = ps.lastInsertId(); } myCache.put(this); } - MailProbe.sendMailProbe(l, "email", id, hash, address); + ping(l); } catch (IOException e) { e.printStackTrace(); } } + private void ping(Language l) throws IOException { + String hash = RandomToken.generateToken(16); + try (GigiPreparedStatement statmt = new GigiPreparedStatement("INSERT INTO `emailPinglog` SET `when`=NOW(), `email`=?, `result`='', `uid`=?, `type`='active', `status`='open'::`pingState`, `challenge`=?")) { + statmt.setString(1, address); + statmt.setInt(2, owner.getId()); + statmt.setString(3, hash); + statmt.execute(); + } + + MailProbe.sendMailProbe(l, "email", id, hash, address); + } + public int getId() { return id; } @@ -81,28 +96,53 @@ public class EmailAddress implements IdCachable, Verifyable { } public synchronized void verify(String hash) throws GigiApiException { - if (this.hash.equals(hash)) { - try (GigiPreparedStatement ps = new GigiPreparedStatement("UPDATE `emails` SET hash='' WHERE id=?")) { - ps.setInt(1, id); - ps.execute(); + 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); + stmt.setInt(2, owner.getId()); + stmt.setString(3, hash); + if ( !stmt.executeMaybeUpdate()) { + throw new IllegalArgumentException("Given token could not be found to complete the verification process (Domain Ping)."); } - hash = ""; + } + // Verify user with that primary email + try (GigiPreparedStatement ps2 = new GigiPreparedStatement("update `users` set `verified`='1' where `id`=? and `email`=? and `verified`='0'")) { + ps2.setInt(1, owner.getId()); + ps2.setString(2, address); + ps2.execute(); + } + } - // Verify user with that primary email - try (GigiPreparedStatement ps2 = new GigiPreparedStatement("update `users` set `verified`='1' where `id`=? and `email`=? and `verified`='0'")) { - ps2.setInt(1, owner.getId()); - ps2.setString(2, address); - ps2.execute(); - } - this.hash = ""; + public boolean isVerified() { + try (GigiPreparedStatement statmt = new GigiPreparedStatement("SELECT 1 FROM `emailPinglog` WHERE `email`=? AND `uid`=? AND `type`='active' AND `status`='success'")) { + statmt.setString(1, address); + statmt.setInt(2, owner.getId()); + GigiResultSet e = statmt.executeQuery(); + return e.next(); + } + } - } else { - throw new GigiApiException("Email verification hash is invalid."); + public Date getLastPing(boolean onlySuccess) { + Date lastExecution; + try (GigiPreparedStatement statmt = new GigiPreparedStatement("SELECT MAX(`when`) FROM `emailPinglog` WHERE `email`=? AND `uid`=? AND `type`='active'" + (onlySuccess ? " AND `status`='success'" : ""))) { + statmt.setString(1, address); + statmt.setInt(2, owner.getId()); + GigiResultSet e = statmt.executeQuery(); + if ( !e.next()) { + return null; + } + lastExecution = e.getTimestamp(1); } + return lastExecution; } - public boolean isVerified() { - return hash.isEmpty(); + public synchronized void requestReping(Language l) throws IOException, GigiApiException { + Date lastExecution = getLastPing(false); + + if (lastExecution != null && lastExecution.getTime() + REPING_MINIMUM_DELAY >= System.currentTimeMillis()) { + throw new GigiApiException(SprintfCommand.createSimple("Reping is only allowed after {0} minutes, yours end at {1}.", REPING_MINIMUM_DELAY / 60 / 1000, new Date(lastExecution.getTime() + REPING_MINIMUM_DELAY))); + } + ping(l); + return; } private static ObjectCache myCache = new ObjectCache<>(); @@ -114,4 +154,20 @@ public class EmailAddress implements IdCachable, Verifyable { } return em; } + + public User getOwner() { + return owner; + } + + public static EmailAddress[] findByAllEmail(String mail) { + LinkedList results = new LinkedList(); + try (GigiPreparedStatement ps = new GigiPreparedStatement("SELECT `emails`.`id` FROM `emails` INNER JOIN `users` ON `users`.`id` = `emails`.`memid` INNER JOIN `certOwners` ON `certOwners`.`id` = `users`.`id` WHERE `emails`.`email` LIKE ? AND `emails`.`deleted` IS NULL AND `certOwners`.`deleted` IS NULL ORDER BY `users`.`id`, `emails`.`email` LIMIT 100")) { + ps.setString(1, mail); + GigiResultSet rs = ps.executeQuery(); + while (rs.next()) { + results.add(EmailAddress.getById(rs.getInt(1))); + } + return results.toArray(new EmailAddress[results.size()]); + } + } }