Redo email / user registration to make a lot more sense. Closes #14 and closes #15

This commit is contained in:
Colin McDonald 2016-06-21 01:39:14 -04:00
parent 63384231c2
commit 4ba3dcd907
4 changed files with 32 additions and 14 deletions

View File

@ -8,6 +8,7 @@ import net.frozenorb.apiv3.util.UuidUtils;
import org.bson.Document; import org.bson.Document;
import org.bson.types.ObjectId; import org.bson.types.ObjectId;
import java.time.Instant;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
@ -42,9 +43,11 @@ public final class UserConverter implements Block<Document> {
ImmutableMap.of(user.get("name").toString(), user.getDate("joined").toInstant()), ImmutableMap.of(user.get("name").toString(), user.getDate("joined").toInstant()),
null, null,
null, null,
null,
null,
user.getString("email"), user.getString("email"),
Instant.EPOCH,
null,
null,
null,
user.getString("phone"), user.getString("phone"),
"INVALID", "INVALID",
user.getDate("joined").toInstant(), user.getDate("joined").toInstant(),

View File

@ -24,6 +24,7 @@ import net.frozenorb.apiv3.unsorted.BlockingCallback;
import net.frozenorb.apiv3.util.*; import net.frozenorb.apiv3.util.*;
import org.bson.Document; import org.bson.Document;
import java.math.BigInteger;
import java.time.Instant; import java.time.Instant;
import java.util.*; import java.util.*;
@ -37,10 +38,12 @@ public final class User {
@Getter private String lastUsername; @Getter private String lastUsername;
@Getter @ExcludeFromReplies private Map<String, Instant> aliases = new HashMap<>(); @Getter @ExcludeFromReplies private Map<String, Instant> aliases = new HashMap<>();
@Getter @ExcludeFromReplies @Setter private String totpSecret; @Getter @ExcludeFromReplies @Setter private String totpSecret;
@Getter @ExcludeFromReplies @Setter private String emailToken;
@Getter @ExcludeFromReplies @Setter private Instant emailTokenSetAt;
@Getter @ExcludeFromReplies private String password; @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 phoneNumber;
@Getter private String lastSeenOn; @Getter private String lastSeenOn;
@Getter private Instant lastSeenAt; @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() { public Rank getHighestRankAnywhere() {
return getHighestRankScoped(null, Grant.findByUserSync(this)); return getHighestRankScoped(null, Grant.findByUserSync(this));
} }

View File

@ -21,12 +21,12 @@ public final class POSTEmailTokenConfirm implements Handler<RoutingContext> {
// We can't check email != null as that's set while we're pending // We can't check email != null as that's set while we're pending
// confirmation, we have to check the token. // 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."); ErrorUtils.respondGeneric(ctx, 400, "User provided already has email set.");
return; 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"); ErrorUtils.respondGeneric(ctx, 200, "Email token is expired");
return; return;
} }
@ -38,7 +38,7 @@ public final class POSTEmailTokenConfirm implements Handler<RoutingContext> {
return; return;
} }
user.setEmailToken(null); user.completeRegistration(user.getPendingEmail());
user.setPassword(password); user.setPassword(password);
user.save(); user.save();

View File

@ -43,20 +43,18 @@ public final class POSTUserRegister implements Handler<RoutingContext> {
return; 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."); ErrorUtils.respondGeneric(ctx, 200, "We just recently sent you a confirmation email. Please wait before trying to register again.");
return; return;
} }
user.setEmail(email); user.startRegistration(email);
user.setEmailToken(new BigInteger(130, new Random()).toString(32));
user.setEmailTokenSetAt(Instant.now());
user.save(); user.save();
Map<String, Object> replacements = ImmutableMap.of( Map<String, Object> replacements = ImmutableMap.of(
"username", user.getLastUsername(), "username", user.getLastUsername(),
"email", user.getEmail(), "email", user.getEmail(),
"emailToken", user.getEmailToken() "emailToken", user.getPendingEmailToken()
); );
Notification notification = new Notification(NotificationTemplate.findByIdSync("email-confirmation"), replacements, replacements); Notification notification = new Notification(NotificationTemplate.findByIdSync("email-confirmation"), replacements, replacements);