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.post("/users/:userId/changePassword").blockingHandler(new POSTUsersIdChangePassword(), 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/passwordReset").blockingHandler(new POSTUsersIdPasswordReset(), 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) {
|
||||
usersCollection.find(new Document("$or", ImmutableList.of(
|
||||
new Document("phone", phoneNumber),
|
||||
|
@ -1,6 +1,7 @@
|
||||
package net.frozenorb.apiv3.route.users;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.mongodb.async.SingleResultCallback;
|
||||
import io.vertx.core.Handler;
|
||||
import io.vertx.core.json.JsonObject;
|
||||
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.util.ErrorUtils;
|
||||
import net.frozenorb.apiv3.util.IpUtils;
|
||||
import net.frozenorb.apiv3.util.SyncUtils;
|
||||
import net.frozenorb.apiv3.util.UuidUtils;
|
||||
|
||||
import java.util.UUID;
|
||||
@ -23,12 +23,11 @@ public final class POSTUsersIdLogin implements Handler<RoutingContext> {
|
||||
UUID uuid = UuidUtils.parseUuid(ctx.request().getParam("userId"));
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
JsonObject requestBody = ctx.getBodyAsJson();
|
||||
User user = SyncUtils.runBlocking(v -> User.findById(uuid, v));
|
||||
String currentUsername = requestBody.getString("username");
|
||||
String userIp = requestBody.getString("userIp");
|
||||
Actor actor = ctx.get("actor");
|
||||
@ -45,49 +44,72 @@ public final class POSTUsersIdLogin implements Handler<RoutingContext> {
|
||||
return;
|
||||
}
|
||||
|
||||
if (user == null) {
|
||||
user = new User(uuid, currentUsername);
|
||||
User finalUser = user;
|
||||
User.findOrCreateById(uuid, currentUsername, (user, findUserError) -> {
|
||||
if (findUserError != null) {
|
||||
ErrorUtils.respondInternalError(ctx, findUserError);
|
||||
return;
|
||||
}
|
||||
|
||||
SyncUtils.<Void>runBlocking(v -> finalUser.checkNameCollisions(v));
|
||||
SyncUtils.<Void>runBlocking(v -> finalUser.insert(v));
|
||||
}
|
||||
incrementIpLog(user, userIp, (ignored, ipLogError) -> {
|
||||
if (ipLogError != null) {
|
||||
ErrorUtils.respondInternalError(ctx, ipLogError);
|
||||
return;
|
||||
}
|
||||
|
||||
User finalUser = user;
|
||||
IpLogEntry ipLogEntry = SyncUtils.runBlocking(v -> IpLogEntry.findByUserAndIp(finalUser, userIp, v));
|
||||
updateUsername(user, currentUsername, (ignored2, updateUsernameError) -> {
|
||||
if (updateUsernameError != null) {
|
||||
ErrorUtils.respondInternalError(ctx, updateUsernameError);
|
||||
return;
|
||||
}
|
||||
|
||||
// We use a little bit more verbose code here to save on the
|
||||
// overhead of a .insert() immediately followed by a .save()
|
||||
if (ipLogEntry == null) {
|
||||
ipLogEntry = new IpLogEntry(user, userIp);
|
||||
ipLogEntry.used();
|
||||
user.seenOnServer(actorServer);
|
||||
user.save((ignored3, saveUserError) -> {
|
||||
if (saveUserError != null) {
|
||||
ErrorUtils.respondInternalError(ctx, saveUserError);
|
||||
return;
|
||||
}
|
||||
|
||||
IpLogEntry finalIpLogEntry = ipLogEntry;
|
||||
SyncUtils.<Void>runBlocking(v -> finalIpLogEntry.insert(v));
|
||||
} else {
|
||||
ipLogEntry.used();
|
||||
user.getLoginInfo(actorServer, userIp, (loginInfo, loginInfoError) -> {
|
||||
if (loginInfoError != null) {
|
||||
ErrorUtils.respondInternalError(ctx, loginInfoError);
|
||||
} else {
|
||||
APIv3.respondJson(ctx, 200, loginInfo);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
IpLogEntry finalIpLogEntry = ipLogEntry;
|
||||
SyncUtils.<Void>runBlocking(v -> finalIpLogEntry.save(v));
|
||||
}
|
||||
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)) {
|
||||
SyncUtils.<Void>runBlocking(v -> finalUser.checkNameCollisions(v));
|
||||
user.checkNameCollisions(callback);
|
||||
} else {
|
||||
callback.onResult(null, null);
|
||||
}
|
||||
|
||||
finalUser.seenOnServer(actorServer);
|
||||
SyncUtils.<Void>runBlocking(v -> finalUser.save(v));
|
||||
|
||||
user.getLoginInfo(actorServer, userIp, (loginInfo, error) -> {
|
||||
if (error != null) {
|
||||
ErrorUtils.respondInternalError(ctx, error);
|
||||
} else {
|
||||
APIv3.respondJson(ctx, 200, loginInfo);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user