X-Git-Url: https://code.wpia.club/?p=gigi.git;a=blobdiff_plain;f=src%2Forg%2Fcacert%2Fgigi%2FdbObjects%2FEmailAddress.java;h=d92338ca9899f0dc8e126159e005e26863cd0b88;hp=f398087d16bf067213afc0b2507557de10cfc658;hb=a8422ae5d5dc70c5a2776d3cead356c111e5b9d7;hpb=701ba7f582c84412cabd47aeb9d785b93a892c07 diff --git a/src/org/cacert/gigi/dbObjects/EmailAddress.java b/src/org/cacert/gigi/dbObjects/EmailAddress.java index f398087d..d92338ca 100644 --- a/src/org/cacert/gigi/dbObjects/EmailAddress.java +++ b/src/org/cacert/gigi/dbObjects/EmailAddress.java @@ -1,17 +1,25 @@ package org.cacert.gigi.dbObjects; import java.io.IOException; +import java.util.Arrays; +import java.util.Date; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; import org.cacert.gigi.GigiApiException; -import org.cacert.gigi.database.DatabaseConnection; import org.cacert.gigi.database.GigiPreparedStatement; 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.Scope; +import org.cacert.gigi.output.template.SprintfCommand; import org.cacert.gigi.util.RandomToken; -public class EmailAddress implements IdCachable { +public class EmailAddress implements IdCachable, Verifyable { + + public static final int REPING_MINIMUM_DELAY = 5 * 60 * 1000; private String address; @@ -19,52 +27,66 @@ public class EmailAddress implements IdCachable { private User owner; - private String hash = null; - private EmailAddress(int id) { - GigiPreparedStatement ps = DatabaseConnection.getInstance().prepare("SELECT memid, email, hash FROM `emails` WHERE id=? AND deleted is NULL"); - ps.setInt(1, id); + try (GigiPreparedStatement ps = new GigiPreparedStatement("SELECT `memid`, `email` FROM `emails` WHERE `id`=? AND `deleted` IS NULL")) { + ps.setInt(1, id); - GigiResultSet rs = ps.executeQuery(); - if ( !rs.next()) { - throw new IllegalArgumentException("Invalid email id " + id); + GigiResultSet rs = ps.executeQuery(); + if ( !rs.next()) { + throw new IllegalArgumentException("Invalid email id " + id); + } + this.id = id; + owner = User.getById(rs.getInt(1)); + address = rs.getString(2); } - this.id = id; - owner = User.getById(rs.getInt(1)); - address = rs.getString(2); - hash = rs.getString(3); - rs.close(); } - public EmailAddress(User owner, String address) { + public EmailAddress(User owner, String address, Locale mailLocale) throws GigiApiException { if ( !EmailProvider.MAIL.matcher(address).matches()) { throw new IllegalArgumentException("Invalid email."); } this.address = address; this.owner = owner; - this.hash = RandomToken.generateToken(16); + insert(Language.getInstance(mailLocale)); } - public void insert(Language l) { - if (id != 0) { - throw new IllegalStateException("already inserted."); - } + private void insert(Language l) throws GigiApiException { try { - GigiPreparedStatement ps = DatabaseConnection.getInstance().prepare("INSERT INTO `emails` SET memid=?, hash=?, email=?"); - ps.setInt(1, owner.getId()); - ps.setString(2, hash); - ps.setString(3, address); synchronized (EmailAddress.class) { - ps.execute(); - id = ps.lastInsertId(); + 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=?, email=?")) { + ps.setInt(1, owner.getId()); + ps.setString(2, address); + psCheck.setString(1, address); + GigiResultSet res = psCheck.executeQuery(); + if (res.next()) { + throw new GigiApiException("The email address is already known to the system."); + } + 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; } @@ -74,26 +96,53 @@ public class EmailAddress implements IdCachable { } public synchronized void verify(String hash) throws GigiApiException { - if (this.hash.equals(hash)) { - GigiPreparedStatement ps = DatabaseConnection.getInstance().prepare("UPDATE `emails` SET hash='' WHERE id=?"); - ps.setInt(1, id); - ps.execute(); - hash = ""; - - // Verify user with that primary email - GigiPreparedStatement ps2 = DatabaseConnection.getInstance().prepare("update `users` set `verified`='1' where `id`=? and `email`=? and `verified`='0'"); + try (GigiPreparedStatement stmt = new GigiPreparedStatement("UPDATE `emailPinglog` SET `status`='success'::`pingState` WHERE `email`=? AND `uid`=? AND `type`='active' AND `challenge`=?")) { + stmt.setString(1, address); + stmt.setInt(2, owner.getId()); + stmt.setString(3, hash); + stmt.executeUpdate(); + } + // 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 = ""; - - } else { - throw new GigiApiException("Email verification hash is invalid."); } } public boolean isVerified() { - return hash.isEmpty(); + 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(); + } + } + + 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 synchronized void requestReping(Language l) throws IOException, GigiApiException { + Date lastExecution = getLastPing(false); + + if (lastExecution != null && lastExecution.getTime() + REPING_MINIMUM_DELAY >= System.currentTimeMillis()) { + Map data = new HashMap(); + data.put("data", new Date(lastExecution.getTime() + REPING_MINIMUM_DELAY)); + throw new GigiApiException(new Scope(new SprintfCommand("Reping is only allowed after 5 minutes, yours end at {0}.", Arrays.asList("${data}")), data)); + } + ping(l); + return; } private static ObjectCache myCache = new ObjectCache<>();