Merge pull request #42 from FrozenOrb/async-user-login
Make POST /users/:id/login fully asynchronous
This commit is contained in:
commit
ad0140d29f
@ -372,7 +372,7 @@ public final class APIv3 extends AbstractVerticle {
|
|||||||
http.get("/users/:userId/verifyPassword").blockingHandler(new GETUsersIdVerifyPassword(), false);
|
http.get("/users/:userId/verifyPassword").blockingHandler(new GETUsersIdVerifyPassword(), false);
|
||||||
http.post("/users/:userId/changePassword").blockingHandler(new POSTUsersIdChangePassword(), false);
|
http.post("/users/:userId/changePassword").blockingHandler(new POSTUsersIdChangePassword(), false);
|
||||||
http.post("/users/:userId/confirmPhone").blockingHandler(new POSTUsersIdConfirmPhone(), false);
|
http.post("/users/:userId/confirmPhone").blockingHandler(new POSTUsersIdConfirmPhone(), false);
|
||||||
http.post("/users/:userId/login").blockingHandler(new POSTUsersIdLogin());
|
http.post("/users/:userId/login").handler(new POSTUsersIdLogin());
|
||||||
http.post("/users/:userId/notify").blockingHandler(new POSTUsersIdNotify(), false);
|
http.post("/users/:userId/notify").blockingHandler(new POSTUsersIdNotify(), false);
|
||||||
http.post("/users/:userId/passwordReset").blockingHandler(new POSTUsersIdPasswordReset(), false);
|
http.post("/users/:userId/passwordReset").blockingHandler(new POSTUsersIdPasswordReset(), false);
|
||||||
http.post("/users/:userId/registerEmail").blockingHandler(new POSTUsersIdRegisterEmail(), false);
|
http.post("/users/:userId/registerEmail").blockingHandler(new POSTUsersIdRegisterEmail(), false);
|
||||||
|
@ -79,6 +79,43 @@ public final class User {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void findOrCreateById(UUID id, String username, SingleResultCallback<User> callback) {
|
||||||
|
if (!UuidUtils.isAcceptableUuid(id)) {
|
||||||
|
callback.onResult(null, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
usersCollection.find(new Document("_id", id)).first(SyncUtils.vertxWrap((user, error) -> {
|
||||||
|
if (error != null) {
|
||||||
|
callback.onResult(null, error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user != null) {
|
||||||
|
callback.onResult(user, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
User created = new User(id, username);
|
||||||
|
|
||||||
|
created.checkNameCollisions((ignored, nameCollisionsError) -> {
|
||||||
|
if (nameCollisionsError != null) {
|
||||||
|
callback.onResult(null, nameCollisionsError);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
created.insert((ignored2, insertUserError) -> {
|
||||||
|
if (insertUserError != null) {
|
||||||
|
callback.onResult(null, insertUserError);
|
||||||
|
} else {
|
||||||
|
callback.onResult(created, null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
public static void findByPhone(String phoneNumber, SingleResultCallback<User> callback) {
|
public static void findByPhone(String phoneNumber, SingleResultCallback<User> callback) {
|
||||||
usersCollection.find(new Document("$or", ImmutableList.of(
|
usersCollection.find(new Document("$or", ImmutableList.of(
|
||||||
new Document("phone", phoneNumber),
|
new Document("phone", phoneNumber),
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package net.frozenorb.apiv3.route.users;
|
package net.frozenorb.apiv3.route.users;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.mongodb.async.SingleResultCallback;
|
||||||
import io.vertx.core.Handler;
|
import io.vertx.core.Handler;
|
||||||
import io.vertx.core.json.JsonObject;
|
import io.vertx.core.json.JsonObject;
|
||||||
import io.vertx.ext.web.RoutingContext;
|
import io.vertx.ext.web.RoutingContext;
|
||||||
@ -12,7 +13,6 @@ import net.frozenorb.apiv3.model.Server;
|
|||||||
import net.frozenorb.apiv3.model.User;
|
import net.frozenorb.apiv3.model.User;
|
||||||
import net.frozenorb.apiv3.util.ErrorUtils;
|
import net.frozenorb.apiv3.util.ErrorUtils;
|
||||||
import net.frozenorb.apiv3.util.IpUtils;
|
import net.frozenorb.apiv3.util.IpUtils;
|
||||||
import net.frozenorb.apiv3.util.SyncUtils;
|
|
||||||
import net.frozenorb.apiv3.util.UuidUtils;
|
import net.frozenorb.apiv3.util.UuidUtils;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@ -23,12 +23,11 @@ public final class POSTUsersIdLogin implements Handler<RoutingContext> {
|
|||||||
UUID uuid = UuidUtils.parseUuid(ctx.request().getParam("userId"));
|
UUID uuid = UuidUtils.parseUuid(ctx.request().getParam("userId"));
|
||||||
|
|
||||||
if (!UuidUtils.isAcceptableUuid(uuid)) {
|
if (!UuidUtils.isAcceptableUuid(uuid)) {
|
||||||
ErrorUtils.respondInvalidInput(ctx, "UUID \"" + uuid + "\" is not valid - must be version 4 UUID.");
|
ErrorUtils.respondInvalidInput(ctx, "Uuid \"" + uuid + "\" is not valid.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonObject requestBody = ctx.getBodyAsJson();
|
JsonObject requestBody = ctx.getBodyAsJson();
|
||||||
User user = SyncUtils.runBlocking(v -> User.findById(uuid, v));
|
|
||||||
String currentUsername = requestBody.getString("username");
|
String currentUsername = requestBody.getString("username");
|
||||||
String userIp = requestBody.getString("userIp");
|
String userIp = requestBody.getString("userIp");
|
||||||
Actor actor = ctx.get("actor");
|
Actor actor = ctx.get("actor");
|
||||||
@ -45,49 +44,72 @@ public final class POSTUsersIdLogin implements Handler<RoutingContext> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user == null) {
|
User.findOrCreateById(uuid, currentUsername, (user, findUserError) -> {
|
||||||
user = new User(uuid, currentUsername);
|
if (findUserError != null) {
|
||||||
User finalUser = user;
|
ErrorUtils.respondInternalError(ctx, findUserError);
|
||||||
|
return;
|
||||||
SyncUtils.<Void>runBlocking(v -> finalUser.checkNameCollisions(v));
|
|
||||||
SyncUtils.<Void>runBlocking(v -> finalUser.insert(v));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
User finalUser = user;
|
incrementIpLog(user, userIp, (ignored, ipLogError) -> {
|
||||||
IpLogEntry ipLogEntry = SyncUtils.runBlocking(v -> IpLogEntry.findByUserAndIp(finalUser, userIp, v));
|
if (ipLogError != null) {
|
||||||
|
ErrorUtils.respondInternalError(ctx, ipLogError);
|
||||||
// We use a little bit more verbose code here to save on the
|
return;
|
||||||
// overhead of a .insert() immediately followed by a .save()
|
|
||||||
if (ipLogEntry == null) {
|
|
||||||
ipLogEntry = new IpLogEntry(user, userIp);
|
|
||||||
ipLogEntry.used();
|
|
||||||
|
|
||||||
IpLogEntry finalIpLogEntry = ipLogEntry;
|
|
||||||
SyncUtils.<Void>runBlocking(v -> finalIpLogEntry.insert(v));
|
|
||||||
} else {
|
|
||||||
ipLogEntry.used();
|
|
||||||
|
|
||||||
IpLogEntry finalIpLogEntry = ipLogEntry;
|
|
||||||
SyncUtils.<Void>runBlocking(v -> finalIpLogEntry.save(v));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String lastUsername = user.getLastUsername();
|
updateUsername(user, currentUsername, (ignored2, updateUsernameError) -> {
|
||||||
user.updateUsername(currentUsername);
|
if (updateUsernameError != null) {
|
||||||
|
ErrorUtils.respondInternalError(ctx, updateUsernameError);
|
||||||
if (!currentUsername.equals(lastUsername)) {
|
return;
|
||||||
SyncUtils.<Void>runBlocking(v -> finalUser.checkNameCollisions(v));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
finalUser.seenOnServer(actorServer);
|
user.seenOnServer(actorServer);
|
||||||
SyncUtils.<Void>runBlocking(v -> finalUser.save(v));
|
user.save((ignored3, saveUserError) -> {
|
||||||
|
if (saveUserError != null) {
|
||||||
|
ErrorUtils.respondInternalError(ctx, saveUserError);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
user.getLoginInfo(actorServer, userIp, (loginInfo, error) -> {
|
user.getLoginInfo(actorServer, userIp, (loginInfo, loginInfoError) -> {
|
||||||
if (error != null) {
|
if (loginInfoError != null) {
|
||||||
ErrorUtils.respondInternalError(ctx, error);
|
ErrorUtils.respondInternalError(ctx, loginInfoError);
|
||||||
} else {
|
} else {
|
||||||
APIv3.respondJson(ctx, 200, loginInfo);
|
APIv3.respondJson(ctx, 200, loginInfo);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void incrementIpLog(User user, String userIp, SingleResultCallback<Void> callback) {
|
||||||
|
IpLogEntry.findByUserAndIp(user, userIp, (existingEntry, error) -> {
|
||||||
|
if (error != null) {
|
||||||
|
callback.onResult(null, error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (existingEntry != null) {
|
||||||
|
existingEntry.used();
|
||||||
|
existingEntry.save(callback);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IpLogEntry inserted = new IpLogEntry(user, userIp);
|
||||||
|
inserted.used();
|
||||||
|
inserted.insert(callback);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateUsername(User user, String currentUsername, SingleResultCallback<Void> callback) {
|
||||||
|
String lastUsername = user.getLastUsername();
|
||||||
|
user.updateUsername(currentUsername);
|
||||||
|
|
||||||
|
if (!currentUsername.equals(lastUsername)) {
|
||||||
|
user.checkNameCollisions(callback);
|
||||||
|
} else {
|
||||||
|
callback.onResult(null, null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user