From 4ba3dcd907848cb1fabdeca83056e0f6c8e9fdbf Mon Sep 17 00:00:00 2001 From: Colin McDonald Date: Tue, 21 Jun 2016 01:39:14 -0400 Subject: [PATCH] Redo email / user registration to make a lot more sense. Closes #14 and closes #15 --- .../dataImport/converters/UserConverter.java | 9 +++++--- .../java/net/frozenorb/apiv3/model/User.java | 23 ++++++++++++++++--- .../emailToken/POSTEmailTokenConfirm.java | 6 ++--- .../apiv3/route/users/POSTUserRegister.java | 8 +++---- 4 files changed, 32 insertions(+), 14 deletions(-) diff --git a/src/main/java/net/frozenorb/apiv3/dataImport/converters/UserConverter.java b/src/main/java/net/frozenorb/apiv3/dataImport/converters/UserConverter.java index b8effbf..81ec97c 100644 --- a/src/main/java/net/frozenorb/apiv3/dataImport/converters/UserConverter.java +++ b/src/main/java/net/frozenorb/apiv3/dataImport/converters/UserConverter.java @@ -8,6 +8,7 @@ import net.frozenorb.apiv3.util.UuidUtils; import org.bson.Document; import org.bson.types.ObjectId; +import java.time.Instant; import java.util.Map; import java.util.UUID; @@ -35,16 +36,18 @@ public final class UserConverter implements Block { } oidToUniqueId.put(user.getObjectId("_id"), uuid); - + User created = new User( uuid, user.get("name").toString(), ImmutableMap.of(user.get("name").toString(), user.getDate("joined").toInstant()), null, null, - null, - null, user.getString("email"), + Instant.EPOCH, + null, + null, + null, user.getString("phone"), "INVALID", user.getDate("joined").toInstant(), diff --git a/src/main/java/net/frozenorb/apiv3/model/User.java b/src/main/java/net/frozenorb/apiv3/model/User.java index 27a1df5..475e560 100644 --- a/src/main/java/net/frozenorb/apiv3/model/User.java +++ b/src/main/java/net/frozenorb/apiv3/model/User.java @@ -24,6 +24,7 @@ import net.frozenorb.apiv3.unsorted.BlockingCallback; import net.frozenorb.apiv3.util.*; import org.bson.Document; +import java.math.BigInteger; import java.time.Instant; import java.util.*; @@ -37,10 +38,12 @@ public final class User { @Getter private String lastUsername; @Getter @ExcludeFromReplies private Map aliases = new HashMap<>(); @Getter @ExcludeFromReplies @Setter private String totpSecret; - @Getter @ExcludeFromReplies @Setter private String emailToken; - @Getter @ExcludeFromReplies @Setter private Instant emailTokenSetAt; @Getter @ExcludeFromReplies private String password; - @Getter @Setter private String email; + @Getter private String email; + @Getter @ExcludeFromReplies private Instant registeredAt; + @Getter private String pendingEmail; + @Getter @ExcludeFromReplies private String pendingEmailToken; + @Getter @ExcludeFromReplies private Instant pendingEmailTokenSetAt; @Getter private String phoneNumber; @Getter private String lastSeenOn; @Getter private Instant lastSeenAt; @@ -243,6 +246,20 @@ public final class User { } + public void completeRegistration(String email) { + this.email = email; + this.registeredAt = Instant.now(); + this.pendingEmail = null; + this.pendingEmailToken = null; + this.pendingEmailTokenSetAt = null; + } + + public void startRegistration(String pendingEmail) { + this.pendingEmail = pendingEmail; + this.pendingEmailToken = new BigInteger(130, new Random()).toString(32); + this.pendingEmailTokenSetAt = Instant.now(); + } + public Rank getHighestRankAnywhere() { return getHighestRankScoped(null, Grant.findByUserSync(this)); } diff --git a/src/main/java/net/frozenorb/apiv3/route/emailToken/POSTEmailTokenConfirm.java b/src/main/java/net/frozenorb/apiv3/route/emailToken/POSTEmailTokenConfirm.java index 6a5f3a1..b355875 100644 --- a/src/main/java/net/frozenorb/apiv3/route/emailToken/POSTEmailTokenConfirm.java +++ b/src/main/java/net/frozenorb/apiv3/route/emailToken/POSTEmailTokenConfirm.java @@ -21,12 +21,12 @@ public final class POSTEmailTokenConfirm implements Handler { // We can't check email != null as that's set while we're pending // confirmation, we have to check the token. - if (user.getEmailToken() == null) { + if (user.getPendingEmailToken() == null) { ErrorUtils.respondGeneric(ctx, 400, "User provided already has email set."); return; } - if ((System.currentTimeMillis() - user.getEmailTokenSetAt().toEpochMilli()) > TimeUnit.DAYS.toMillis(2)) { + if ((System.currentTimeMillis() - user.getPendingEmailTokenSetAt().toEpochMilli()) > TimeUnit.DAYS.toMillis(2)) { ErrorUtils.respondGeneric(ctx, 200, "Email token is expired"); return; } @@ -38,7 +38,7 @@ public final class POSTEmailTokenConfirm implements Handler { return; } - user.setEmailToken(null); + user.completeRegistration(user.getPendingEmail()); user.setPassword(password); user.save(); diff --git a/src/main/java/net/frozenorb/apiv3/route/users/POSTUserRegister.java b/src/main/java/net/frozenorb/apiv3/route/users/POSTUserRegister.java index 93c50b6..2bf43e2 100644 --- a/src/main/java/net/frozenorb/apiv3/route/users/POSTUserRegister.java +++ b/src/main/java/net/frozenorb/apiv3/route/users/POSTUserRegister.java @@ -43,20 +43,18 @@ public final class POSTUserRegister implements Handler { return; } - if (user.getEmailToken() != null && (System.currentTimeMillis() - user.getEmailTokenSetAt().toEpochMilli()) < TimeUnit.DAYS.toMillis(2)) { + if (user.getPendingEmailToken() != null && (System.currentTimeMillis() - user.getPendingEmailTokenSetAt().toEpochMilli()) < TimeUnit.DAYS.toMillis(2)) { ErrorUtils.respondGeneric(ctx, 200, "We just recently sent you a confirmation email. Please wait before trying to register again."); return; } - user.setEmail(email); - user.setEmailToken(new BigInteger(130, new Random()).toString(32)); - user.setEmailTokenSetAt(Instant.now()); + user.startRegistration(email); user.save(); Map replacements = ImmutableMap.of( "username", user.getLastUsername(), "email", user.getEmail(), - "emailToken", user.getEmailToken() + "emailToken", user.getPendingEmailToken() ); Notification notification = new Notification(NotificationTemplate.findByIdSync("email-confirmation"), replacements, replacements);