Prefixes and more

This commit is contained in:
Topu 2022-10-20 08:59:02 +03:00
parent 0da3fd9476
commit b82effe163
28 changed files with 290 additions and 236 deletions

View File

@ -1,5 +1,5 @@
mongoUri: mongodb://localhost:27017/HQAPI
redisUri: redis://localhost:6379
mongoUri: mongodb://Admin:admin@15.160.229.161:27017/HQAPI?authMechanism=SCRAM-SHA-1&authSource=admin
redisUri: redis://15.160.229.161:6379
network:
name: MineHQ Network

View File

@ -80,22 +80,7 @@ import net.frozenorb.apiv3.web.route.servers.GETServersId;
import net.frozenorb.apiv3.web.route.servers.GETServersPlayerCountId;
import net.frozenorb.apiv3.web.route.servers.POSTServers;
import net.frozenorb.apiv3.web.route.servers.POSTServersHeartbeat;
import net.frozenorb.apiv3.web.route.users.GETStaff;
import net.frozenorb.apiv3.web.route.users.GETUsersId;
import net.frozenorb.apiv3.web.route.users.GETUsersIdCompoundedPermissions;
import net.frozenorb.apiv3.web.route.users.GETUsersIdDetails;
import net.frozenorb.apiv3.web.route.users.GETUsersIdRequiresTotp;
import net.frozenorb.apiv3.web.route.users.GETUsersIdVerifyPassword;
import net.frozenorb.apiv3.web.route.users.POSTUsersIdChangePassword;
import net.frozenorb.apiv3.web.route.users.POSTUsersIdConfirmPhone;
import net.frozenorb.apiv3.web.route.users.POSTUsersIdLogin;
import net.frozenorb.apiv3.web.route.users.POSTUsersIdNotify;
import net.frozenorb.apiv3.web.route.users.POSTUsersIdPasswordReset;
import net.frozenorb.apiv3.web.route.users.POSTUsersIdRegisterEmail;
import net.frozenorb.apiv3.web.route.users.POSTUsersIdRegisterPhone;
import net.frozenorb.apiv3.web.route.users.POSTUsersIdSetupTotp;
import net.frozenorb.apiv3.web.route.users.POSTUsersIdVerifyTotp;
import net.frozenorb.apiv3.web.route.users.POSTUsersUsePasswordResetToken;
import net.frozenorb.apiv3.web.route.users.*;
import net.frozenorb.apiv3.util.SpringUtils;
import org.springframework.beans.factory.annotation.Value;
@ -223,7 +208,7 @@ public final class APIv3 {
httpDelete(router, "/ranks/:rankId", DELETERanksId.class);
httpGet(router, "/serverGroups/:serverGroupId", GETServerGroupsId.class);
httpGet(router, "/serverGroups/:serverGroupId/playerCount", GETServerGroupsPlayerCount.class);
httpGet(router, "/serverGroups/:serverGroupId/playerCount", GETServerGroupsPlayerCount.class);
httpGet(router, "/serverGroups", GETServerGroups.class);
httpPost(router, "/serverGroups", POSTServerGroups.class);
//httpPut(router, "/serverGroups/:serverGroupId", PUTServerGroupsId.class);
@ -237,7 +222,6 @@ public final class APIv3 {
//httpPut(router, "/servers/:serverId", PUTServersId.class);
httpDelete(router, "/servers/:serverId", DELETEServersId.class);
httpGet(router, "/prefixes/:prefixId", GETPrefixesId.class);
httpGet(router, "/prefixes", GETPrefixes.class);
httpPost(router, "/prefixes", POSTPrefixes.class);
@ -266,6 +250,8 @@ public final class APIv3 {
httpPost(router, "/users/usePasswordResetToken", POSTUsersUsePasswordResetToken.class);
httpPost(router, "/users/:userId/setupTotp", POSTUsersIdSetupTotp.class);
httpPost(router, "/users/:userId/verifyTotp", POSTUsersIdVerifyTotp.class);
httpPost(router, "/users/:userId/colors", POSTUsersIdChangeColors.class);
httpPost(router, "/users/:userId/prefix", POSTUsersIdChangePrefix.class);
httpGet(router, "/dumps/:dumpType", GETDumpsType.class);
httpGet(router, "/search", GETSearch.class);
@ -288,17 +274,17 @@ public final class APIv3 {
}
}
public static void respondRawJson(RoutingContext ctx, int code, String response) {
ctx.response().putHeader(HttpHeaders.CONTENT_TYPE, MediaType.JSON_UTF_8.toString());
public static void respondRawJson(RoutingContext ctx, int code, String response) {
ctx.response().putHeader(HttpHeaders.CONTENT_TYPE, MediaType.JSON_UTF_8.toString());
if (response == null) {
ctx.response().setStatusCode(404);
ctx.response().end("{}");
} else {
ctx.response().setStatusCode(code);
ctx.response().end(response);
}
}
if (response == null) {
ctx.response().setStatusCode(404);
ctx.response().end("{}");
} else {
ctx.response().setStatusCode(code);
ctx.response().end(response);
}
}
private void httpGet(Router router, String route, Class<?> handler) {
router.get(route).blockingHandler((Handler<RoutingContext>) SpringUtils.getBean(handler), false);

View File

@ -14,8 +14,6 @@ import com.mongodb.async.SingleResultCallback;
import com.mongodb.async.client.MongoCollection;
import com.mongodb.async.client.MongoDatabase;
import net.frozenorb.apiv3.service.geoip.GeoIpInfo;
import net.frozenorb.apiv3.service.geoip.GeoIpUserType;
import net.frozenorb.apiv3.service.mojang.MojangService;
import net.frozenorb.apiv3.serialization.gson.ExcludeFromReplies;
import net.frozenorb.apiv3.serialization.jackson.UuidJsonDeserializer;
@ -66,7 +64,7 @@ public final class User {
@Getter @Id @JsonSerialize(using = UuidJsonSerializer.class) @JsonDeserialize(using = UuidJsonDeserializer.class) private UUID id;
@Getter private String lastUsername;
@Getter private String lastUsernameLower;
@Getter private String lastUsernameLower;
@Getter @ExcludeFromReplies private Map<String, Instant> aliases = new HashMap<>();
@Getter @ExcludeFromReplies @Setter private String totpSecret;
@Getter @ExcludeFromReplies private String password;
@ -88,6 +86,9 @@ public final class User {
@Getter private Instant lastSeenAt;
@Getter private Instant firstSeenAt;
@Getter private boolean online;
@Getter private String activePrefix;
@Getter private String iconColor;
@Getter private String nameColor;
public static void findAll(SingleResultCallback<List<User>> callback) {
usersCollection.find().sort(new Document("lastSeenAt", -1)).into(new LinkedList<>(), SyncUtils.vertxWrap(callback));
@ -178,26 +179,26 @@ public final class User {
usersCollection.find(new Document("lastUsername", lastUsername)).first(SyncUtils.vertxWrap(callback));
}
public static void findByLastUsernameLower(String lastUsernameLower, SingleResultCallback<User> callback) {
usersCollection.find(new Document("lastUsernameLower", lastUsernameLower.toLowerCase())).first(SyncUtils.vertxWrap(callback));
}
public static void findByLastUsernameLower(String lastUsernameLower, SingleResultCallback<User> callback) {
usersCollection.find(new Document("lastUsernameLower", lastUsernameLower.toLowerCase())).first(SyncUtils.vertxWrap(callback));
}
public static void findByIdGrouped(Set<UUID> search, SingleResultCallback<Map<UUID, User>> callback) {
usersCollection.find(new Document("_id", new Document("$in", search))).into(new LinkedList<>(), SyncUtils.vertxWrap((users, error) -> {
if (error != null) {
callback.onResult(null, error);
return;
}
public static void findByIdGrouped(Set<UUID> search, SingleResultCallback<Map<UUID, User>> callback) {
usersCollection.find(new Document("_id", new Document("$in", search))).into(new LinkedList<>(), SyncUtils.vertxWrap((users, error) -> {
if (error != null) {
callback.onResult(null, error);
return;
}
Map<UUID, User> result = new HashMap<>();
Map<UUID, User> result = new HashMap<>();
for (User user : users) {
result.put(user.getId(), user);
}
for (User user : users) {
result.put(user.getId(), user);
}
callback.onResult(result, null);
}));
}
callback.onResult(result, null);
}));
}
public static void findOrCreateByIdGrouped(Map<UUID, String> search, SingleResultCallback<Map<UUID, User>> callback) {
usersCollection.find(new Document("_id", new Document("$in", search.keySet()))).into(new LinkedList<>(), SyncUtils.vertxWrap((users, error) -> {
@ -256,7 +257,7 @@ public final class User {
public User(UUID id, String lastUsername) {
this.id = id;
this.lastUsername = lastUsername;
this.lastUsernameLower = lastUsername.toLowerCase();
this.lastUsernameLower = lastUsername.toLowerCase();
this.aliases = new HashMap<>();
this.lastSeenAt = Instant.now();
this.firstSeenAt = Instant.now();
@ -267,7 +268,7 @@ public final class User {
public void updateUsername(String newUsername) {
this.aliases.put(newUsername, Instant.now());
this.lastUsername = newUsername;
this.lastUsernameLower = newUsername.toLowerCase();
this.lastUsernameLower = newUsername.toLowerCase();
}
public void checkNameCollisions(SingleResultCallback<Void> callback) {
@ -311,6 +312,7 @@ public final class User {
Future<List<Punishment>> punishmentsFuture = Future.future();
Future<List<IpBan>> ipBansFuture = Future.future();
Future<List<Grant>> grantsFuture = Future.future();
Future<List<PrefixGrant>> prefixGrantsFuture = Future.future();
Punishment.findByUserAndType(this, ImmutableSet.of(
Punishment.PunishmentType.BLACKLIST,
@ -325,8 +327,9 @@ public final class User {
}
Grant.findByUser(this, new MongoToVertxCallback<>(grantsFuture));
PrefixGrant.findByUser(this, new MongoToVertxCallback<>(prefixGrantsFuture));
CompositeFuture.all(punishmentsFuture, ipBansFuture, grantsFuture).setHandler((result) -> {
CompositeFuture.all(punishmentsFuture, ipBansFuture, grantsFuture, prefixGrantsFuture).setHandler((result) -> {
if (result.failed()) {
callback.onResult(null, result.cause());
return;
@ -335,8 +338,9 @@ public final class User {
Iterable<Punishment> punishments = result.result().result(0);
Iterable<IpBan> ipBans = result.result().result(1);
Iterable<Grant> grants = result.result().result(2);
Iterable<PrefixGrant> prefixGrants = result.result().result(3);
getLoginInfo(server, punishments, ipBans, grants, (loginInfo, error) -> {
getLoginInfo(server, punishments, ipBans, grants, prefixGrants, (loginInfo, error) -> {
if (error != null) {
callback.onResult(null, error);
} else {
@ -347,7 +351,7 @@ public final class User {
}
// This is only used to help batch requests to mongo
public void getLoginInfo(Server server, Iterable<Punishment> punishments, Iterable<IpBan> ipBans, Iterable<Grant> grants, SingleResultCallback<Map<String, Object>> callback) {
public void getLoginInfo(Server server, Iterable<Punishment> punishments, Iterable<IpBan> ipBans, Iterable<Grant> grants, Iterable<PrefixGrant> prefixGrants, SingleResultCallback<Map<String, Object>> callback) {
getAccessInfo(punishments, ipBans, (accessInfo, error) -> {
if (error != null) {
callback.onResult(null, error);
@ -390,6 +394,23 @@ public final class User {
result.put("access", accessInfo);
}
if (iconColor != null) {
result.put("iconColor", iconColor);
}
if (nameColor != null) {
result.put("nameColor", nameColor);
}
List<Prefix> prefixes = getPrefixesScoped(serverGroup, prefixGrants);
if (!prefixes.isEmpty()) {
result.put("prefixes", Collections2.transform(prefixes, Prefix::getId));
}
if (activePrefix != null) {
result.put("activePrefix", activePrefix);
}
callback.onResult(result, null);
});
}
@ -603,6 +624,15 @@ public final class User {
this.phoneVerificationFailedAttempts = null;
}
public void updateColors(String iconColor, String nameColor) {
this.iconColor = iconColor;
this.nameColor = nameColor;
}
public void updateActivePrefix(String prefix) {
this.activePrefix = prefix;
}
public void hasPermissionAnywhere(String permission, SingleResultCallback<Boolean> callback) {
getCompoundedPermissions((permissions, error) -> {
if (error != null) {
@ -690,16 +720,14 @@ public final class User {
}
Rank parent = otherRank;
if(parent != null) {
// Iterate up the inheritance tree to detect rank redundancies.
while (parent.getInheritsFromId() != null) {
if (parent == grantedRank) {
grantedRanks.remove(grantedRank);
}
parent = Rank.findById(parent.getInheritsFromId());
// Iterate up the inheritance tree to detect rank redundancies.
while (parent.getInheritsFromId() != null) {
if (parent == grantedRank) {
grantedRanks.remove(grantedRank);
}
parent = Rank.findById(parent.getInheritsFromId());
}
}
}
@ -709,6 +737,27 @@ public final class User {
return ImmutableList.copyOf(grantedRanksList);
}
private List<Prefix> getPrefixesScoped(ServerGroup serverGroup, Iterable<PrefixGrant> grants) {
Set<Prefix> grantedPrefixes = new HashSet<>();
for (PrefixGrant grant : grants) {
if (!grant.isActive() || (serverGroup != null && !grant.appliesOn(serverGroup))) {
continue;
}
Prefix grantedPrefix = Prefix.findById(grant.getPrefix());
if (grantedPrefix != null) {
grantedPrefixes.add(grantedPrefix);
} else {
log.warn(lastUsername + " (" + id + ") has a grant for a non-existant rank: " + grant.getPrefix());
}
}
List<Prefix> grantedRanksList = new ArrayList<>(grantedPrefixes);
return ImmutableList.copyOf(grantedRanksList);
}
public void insert(SingleResultCallback<Void> callback) {
usersCollection.insertOne(this, SyncUtils.vertxWrap(callback));
}
@ -717,4 +766,4 @@ public final class User {
usersCollection.replaceOne(new Document("_id", id), this, SyncUtils.vertxWrap(new MongoToVoidMongoCallback<>(callback)));
}
}
}

View File

@ -30,7 +30,6 @@ public enum AuditLogActionType {
PREFIXGRANT_CREATE(false),
PREFIXGRANT_UPDATE(false),
PREFIXGRANT_DELETE(false),
IP_BAN_CREATE(false),
IP_BAN_UPDATE(false),
IP_BAN_DELETE(false),
@ -69,8 +68,6 @@ public enum AuditLogActionType {
PREFIX_CREATE(false),
PREFIX_UPDATE(false),
PREFIX_DELETE(false),
SERVER_GROUP_CREATE(false),
SERVER_GROUP_UPDATE(false),
SERVER_GROUP_DELETE(false),
@ -86,7 +83,9 @@ public enum AuditLogActionType {
USER_CONFIRM_EMAIL(false),
USER_CONFIRM_PHONE(false),
USER_SETUP_TOTP(false),
USER_VERIFY_TOTP(false);
USER_VERIFY_TOTP(false),
USER_CHANGE_COLORS(false),
USER_CHANGE_PREFIX(false);
@Getter private boolean reversible;

View File

@ -19,4 +19,5 @@ public class Permissions {
public static final String CREATE_PREFIXGRANT = rootPermission + ".prefixgrant.create";
public static final String REMOVE_PREFIXGRANT = rootPermission + ".prefixgrant.remove";
}

View File

@ -4,11 +4,8 @@ import io.vertx.core.Handler;
import io.vertx.ext.web.RoutingContext;
import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.domain.Prefix;
import net.frozenorb.apiv3.domain.Rank;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
@Component
public final class GETPrefixes implements Handler<RoutingContext> {

View File

@ -1,18 +1,16 @@
package net.frozenorb.apiv3.web.route.prefixGrants;
import io.vertx.core.Handler;
import io.vertx.ext.web.RoutingContext;
import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.domain.PrefixGrant;
import net.frozenorb.apiv3.util.ErrorUtils;
import net.frozenorb.apiv3.util.UuidUtils;
import org.bson.Document;
import org.springframework.stereotype.Component;
import java.util.stream.Collectors;
import io.vertx.core.Handler;
import io.vertx.ext.web.RoutingContext;
@Component
public final class GETPrefixGrants implements Handler<RoutingContext> {

View File

@ -3,7 +3,6 @@ package net.frozenorb.apiv3.web.route.prefixGrants;
import io.vertx.core.Handler;
import io.vertx.ext.web.RoutingContext;
import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.domain.Grant;
import net.frozenorb.apiv3.domain.PrefixGrant;
import net.frozenorb.apiv3.util.ErrorUtils;
import org.springframework.stereotype.Component;

View File

@ -5,7 +5,10 @@ import io.vertx.core.Handler;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.RoutingContext;
import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.domain.*;
import net.frozenorb.apiv3.domain.Prefix;
import net.frozenorb.apiv3.domain.PrefixGrant;
import net.frozenorb.apiv3.domain.ServerGroup;
import net.frozenorb.apiv3.domain.User;
import net.frozenorb.apiv3.service.auditlog.AuditLog;
import net.frozenorb.apiv3.service.auditlog.AuditLogActionType;
import net.frozenorb.apiv3.service.totp.TotpAuthorizationResult;

View File

@ -4,14 +4,9 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.domain.*;
import net.frozenorb.apiv3.unsorted.actor.Actor;
import net.frozenorb.apiv3.unsorted.actor.ActorType;
import net.frozenorb.apiv3.domain.Grant;
import net.frozenorb.apiv3.domain.Punishment;
import net.frozenorb.apiv3.domain.Rank;
import net.frozenorb.apiv3.domain.Server;
import net.frozenorb.apiv3.domain.ServerGroup;
import net.frozenorb.apiv3.domain.User;
import net.frozenorb.apiv3.unsorted.MongoToVertxCallback;
import net.frozenorb.apiv3.util.ErrorUtils;
import net.frozenorb.apiv3.util.IpUtils;
@ -40,16 +35,14 @@ public final class POSTServersHeartbeat implements Handler<RoutingContext> {
public void handle(RoutingContext ctx) {
Actor actor = ctx.get("actor");
if (actor.getType() != ActorType.SERVER) {
ErrorUtils.respondOther(ctx, 403,
"This action can only be performed when requested by a server.", "serverOnly", ImmutableMap.of());
ErrorUtils.respondOther(ctx, 403, "This action can only be performed when requested by a server.", "serverOnly", ImmutableMap.of());
return;
}
Server actorServer = Server.findById(actor.getName());
JsonObject requestBody = ctx.getBodyAsJson();
JsonObject players = requestBody.getJsonObject("players");
Map<UUID, String> playerNames = extractPlayerNames(players);
Map<UUID, String> playerIps = extractPlayerIps(players);
@ -69,46 +62,44 @@ public final class POSTServersHeartbeat implements Handler<RoutingContext> {
"events", result.result().result(3)
));
} else {
result.cause().printStackTrace();
ErrorUtils.respondInternalError(ctx, result.cause());
}
});
}
private Future<Void> createInfoResponse(Server server, double tps, Map<UUID, String> playerNames) {
Future<Void> callback = Future.future();
if (server != null && playerNames != null) {
server.receivedHeartbeat(tps, playerNames.keySet());
server.save((ignored, error) -> {
if (error != null) {
callback.fail(error);
} else {
callback.complete();
}
});
}
server.receivedHeartbeat(tps, playerNames.keySet());
server.save((ignored, error) -> {
if (error != null) {
callback.fail(error);
} else {
callback.complete();
}
});
return callback;
}
private Future<Map<String, Object>> createPlayerResponse(Server server, Map<UUID, String> playerNames, Map<UUID, String> playerIps) {
Future<Map<String, Object>> callback = Future.future();
Future<Map<UUID, User>> userLookupCallback = Future.future();
Future<Map<UUID, List<Grant>>> grantLookupCallback = Future.future();
Future<Map<UUID, List<Punishment>>> punishmentLookupCallback = Future.future();
Future<Map<UUID, List<PrefixGrant>>> prefixGrantLookupCallback = Future.future();
User.findOrCreateByIdGrouped(playerNames, new MongoToVertxCallback<>(userLookupCallback));
Grant.findByUserGrouped(playerNames.keySet(), new MongoToVertxCallback<>(grantLookupCallback));
Punishment.findByUserGrouped(playerNames.keySet(), new MongoToVertxCallback<>(punishmentLookupCallback));
PrefixGrant.findByUserGrouped(playerNames.keySet(), new MongoToVertxCallback<>(prefixGrantLookupCallback));
CompositeFuture.all(
userLookupCallback,
grantLookupCallback,
punishmentLookupCallback
punishmentLookupCallback,
prefixGrantLookupCallback
).setHandler((batchLookupInfo) -> {
if (batchLookupInfo.failed()) {
callback.fail(batchLookupInfo.cause());
@ -118,11 +109,12 @@ public final class POSTServersHeartbeat implements Handler<RoutingContext> {
Map<UUID, User> users = batchLookupInfo.result().result(0);
Map<UUID, List<Grant>> grants = batchLookupInfo.result().result(1);
Map<UUID, List<Punishment>> punishments = batchLookupInfo.result().result(2);
Map<UUID, List<PrefixGrant>> prefixGrants = batchLookupInfo.result().result(3);
Map<UUID, Future> loginInfoFutures = new HashMap<>();
users.forEach((uuid, user) -> {
Future<Map<String, Object>> loginInfoFuture = Future.future();
createLoginInfo(user, server, grants.get(uuid), punishments.get(uuid), loginInfoFuture);
createLoginInfo(user, server, grants.get(uuid), punishments.get(uuid), prefixGrants.get(uuid), loginInfoFuture);
loginInfoFutures.put(uuid, loginInfoFuture);
});
@ -142,19 +134,18 @@ public final class POSTServersHeartbeat implements Handler<RoutingContext> {
}
private Future<Map<String, Object>> createPermissionsResponse(ServerGroup serverGroup) {
Future<Map<String, Object>> callback = Future.future();
Map<String, Object> permissionsResponse = new HashMap<>();
for (Rank rank : Rank.findAll()) {
Map<String, Boolean> defaultCalculatedPermissions = ServerGroup.findDefault().calculatePermissions(rank);
Map<String, Boolean> calculatedPermissions = serverGroup.calculatePermissions(rank);
Map<String, Boolean> scopedPermissions = PermissionUtils.mergePermissions(
defaultCalculatedPermissions,
calculatedPermissions
ServerGroup.findDefault().calculatePermissions(rank),
serverGroup.calculatePermissions(rank)
);
permissionsResponse.put(rank.getId(), PermissionUtils.convertToList(scopedPermissions));
}
callback.complete(permissionsResponse);
return callback;
}
@ -245,7 +236,7 @@ public final class POSTServersHeartbeat implements Handler<RoutingContext> {
return result;
}
private void createLoginInfo(User user, Server server, List<Grant> grants, List<Punishment> punishments, Future<Map<String, Object>> callback) {
private void createLoginInfo(User user, Server server, List<Grant> grants, List<Punishment> punishments, List<PrefixGrant> prefixGrants, Future<Map<String, Object>> callback) {
if (user.seenOnServer(server)) {
user.save((ignored, error) -> {
if (error != null) {
@ -253,10 +244,10 @@ public final class POSTServersHeartbeat implements Handler<RoutingContext> {
return;
}
user.getLoginInfo(server, punishments, ImmutableList.of(), grants, new MongoToVertxCallback<>(callback));
user.getLoginInfo(server, punishments, ImmutableList.of(), grants, prefixGrants, new MongoToVertxCallback<>(callback));
});
} else {
user.getLoginInfo(server, punishments, ImmutableList.of(), grants, new MongoToVertxCallback<>(callback));
user.getLoginInfo(server, punishments, ImmutableList.of(), grants, prefixGrants, new MongoToVertxCallback<>(callback));
}
}

View File

@ -1,21 +1,15 @@
package net.frozenorb.apiv3.web.route.users;
import io.vertx.core.Handler;
import io.vertx.ext.web.RoutingContext;
import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.domain.Grant;
import net.frozenorb.apiv3.domain.Rank;
import net.frozenorb.apiv3.domain.User;
import net.frozenorb.apiv3.util.SyncUtils;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import io.vertx.core.Handler;
import io.vertx.ext.web.RoutingContext;
import java.util.*;
@Component
public final class GETStaff implements Handler<RoutingContext> {

View File

@ -1,13 +1,11 @@
package net.frozenorb.apiv3.web.route.users;
import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.domain.User;
import net.frozenorb.apiv3.util.ErrorUtils;
import org.springframework.stereotype.Component;
import io.vertx.core.Handler;
import io.vertx.ext.web.RoutingContext;
import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.domain.User;
import net.frozenorb.apiv3.util.ErrorUtils;
import org.springframework.stereotype.Component;
@Component
public final class GETUsersId implements Handler<RoutingContext> {

View File

@ -1,15 +1,13 @@
package net.frozenorb.apiv3.web.route.users;
import io.vertx.core.Handler;
import io.vertx.ext.web.RoutingContext;
import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.domain.User;
import net.frozenorb.apiv3.util.ErrorUtils;
import net.frozenorb.apiv3.util.PermissionUtils;
import org.springframework.stereotype.Component;
import io.vertx.core.Handler;
import io.vertx.ext.web.RoutingContext;
@Component
public final class GETUsersIdCompoundedPermissions implements Handler<RoutingContext> {

View File

@ -1,5 +1,7 @@
package net.frozenorb.apiv3.web.route.users;
import io.vertx.core.Handler;
import io.vertx.ext.web.RoutingContext;
import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.domain.Grant;
import net.frozenorb.apiv3.domain.IpLogEntry;
@ -7,16 +9,12 @@ import net.frozenorb.apiv3.domain.Punishment;
import net.frozenorb.apiv3.domain.User;
import net.frozenorb.apiv3.util.ErrorUtils;
import net.frozenorb.apiv3.util.SyncUtils;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import io.vertx.core.Handler;
import io.vertx.ext.web.RoutingContext;
@Component
public final class GETUsersIdDetails implements Handler<RoutingContext> {

View File

@ -1,18 +1,15 @@
package net.frozenorb.apiv3.web.route.users;
import com.google.common.collect.ImmutableMap;
import io.vertx.core.Handler;
import io.vertx.ext.web.RoutingContext;
import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.domain.User;
import net.frozenorb.apiv3.service.totp.RequiresTotpResult;
import net.frozenorb.apiv3.util.ErrorUtils;
import net.frozenorb.apiv3.util.IpUtils;
import org.springframework.stereotype.Component;
import io.vertx.core.Handler;
import io.vertx.ext.web.RoutingContext;
@Component
public final class GETUsersIdRequiresTotp implements Handler<RoutingContext> {

View File

@ -1,16 +1,16 @@
package net.frozenorb.apiv3.web.route.users;
import com.mongodb.async.SingleResultCallback;
import io.vertx.core.Handler;
import io.vertx.ext.web.RoutingContext;
import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.domain.User;
import net.frozenorb.apiv3.service.auditlog.AuditLog;
import net.frozenorb.apiv3.service.auditlog.AuditLogActionType;
import net.frozenorb.apiv3.domain.User;
import net.frozenorb.apiv3.service.usersession.UserSessionService;
import net.frozenorb.apiv3.util.ErrorUtils;
import net.frozenorb.apiv3.util.IpUtils;
import net.frozenorb.apiv3.util.SyncUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@ -18,9 +18,6 @@ import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import io.vertx.core.Handler;
import io.vertx.ext.web.RoutingContext;
@Component
public final class GETUsersIdVerifyPassword implements Handler<RoutingContext> {

View File

@ -0,0 +1,36 @@
package net.frozenorb.apiv3.web.route.users;
import com.google.common.collect.ImmutableMap;
import io.vertx.core.Handler;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.RoutingContext;
import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.domain.User;
import net.frozenorb.apiv3.util.ErrorUtils;
import net.frozenorb.apiv3.util.SyncUtils;
import org.springframework.stereotype.Component;
@Component
public final class POSTUsersIdChangeColors implements Handler<RoutingContext> {
@Override
public void handle(RoutingContext ctx) {
User user = SyncUtils.runBlocking(v -> User.findById(ctx.request().getParam("userId"), v));
if (user == null) {
ErrorUtils.respondNotFound(ctx, "User", ctx.request().getParam("userId"));
return;
}
JsonObject requestBody = ctx.getBodyAsJson();
String iconColor = requestBody.getString("iconColor");
String nameColor = requestBody.getString("nameColor");
user.updateColors(iconColor, nameColor);
SyncUtils.<Void>runBlocking(user::save);
APIv3.respondJson(ctx, 200, ImmutableMap.of(
"success", true
));
}
}

View File

@ -1,11 +1,13 @@
package net.frozenorb.apiv3.web.route.users;
import com.google.common.collect.ImmutableMap;
import io.vertx.core.Handler;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.RoutingContext;
import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.domain.User;
import net.frozenorb.apiv3.service.auditlog.AuditLog;
import net.frozenorb.apiv3.service.auditlog.AuditLogActionType;
import net.frozenorb.apiv3.domain.User;
import net.frozenorb.apiv3.service.totp.RequiresTotpResult;
import net.frozenorb.apiv3.service.totp.TotpAuthorizationResult;
import net.frozenorb.apiv3.service.usersession.UserSessionService;
@ -13,14 +15,9 @@ import net.frozenorb.apiv3.util.ErrorUtils;
import net.frozenorb.apiv3.util.IpUtils;
import net.frozenorb.apiv3.util.PasswordUtils;
import net.frozenorb.apiv3.util.SyncUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import io.vertx.core.Handler;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.RoutingContext;
@Component
public final class POSTUsersIdChangePassword implements Handler<RoutingContext> {

View File

@ -0,0 +1,44 @@
package net.frozenorb.apiv3.web.route.users;
import com.google.common.collect.ImmutableMap;
import io.vertx.core.Handler;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.RoutingContext;
import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.domain.Prefix;
import net.frozenorb.apiv3.domain.User;
import net.frozenorb.apiv3.util.ErrorUtils;
import net.frozenorb.apiv3.util.SyncUtils;
import org.springframework.stereotype.Component;
@Component
public final class POSTUsersIdChangePrefix implements Handler<RoutingContext> {
@Override
public void handle(RoutingContext ctx) {
User user = SyncUtils.runBlocking(v -> User.findById(ctx.request().getParam("userId"), v));
if (user == null) {
ErrorUtils.respondNotFound(ctx, "User", ctx.request().getParam("userId"));
return;
}
JsonObject requestBody = ctx.getBodyAsJson();
String prefixId = requestBody.getString("prefix");
// prefixid can be null
if (prefixId != null) {
Prefix prefix = Prefix.findById(prefixId);
if (prefix == null) {
ErrorUtils.respondNotFound(ctx, "Prefix", requestBody.getString("prefix"));
return;
}
}
user.updateActivePrefix(prefixId);
SyncUtils.<Void>runBlocking(user::save);
APIv3.respondJson(ctx, 200, ImmutableMap.of(
"success", true
));
}
}

View File

@ -1,22 +1,19 @@
package net.frozenorb.apiv3.web.route.users;
import com.google.common.collect.ImmutableMap;
import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.service.auditlog.AuditLog;
import net.frozenorb.apiv3.service.auditlog.AuditLogActionType;
import net.frozenorb.apiv3.domain.User;
import net.frozenorb.apiv3.util.ErrorUtils;
import net.frozenorb.apiv3.util.IpUtils;
import net.frozenorb.apiv3.util.SyncUtils;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
import io.vertx.core.Handler;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.RoutingContext;
import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.domain.User;
import net.frozenorb.apiv3.service.auditlog.AuditLog;
import net.frozenorb.apiv3.service.auditlog.AuditLogActionType;
import net.frozenorb.apiv3.util.ErrorUtils;
import net.frozenorb.apiv3.util.IpUtils;
import net.frozenorb.apiv3.util.SyncUtils;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
@Component
public final class POSTUsersIdConfirmPhone implements Handler<RoutingContext> {

View File

@ -1,26 +1,22 @@
package net.frozenorb.apiv3.web.route.users;
import com.google.common.collect.ImmutableMap;
import com.mongodb.async.SingleResultCallback;
import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.unsorted.actor.Actor;
import net.frozenorb.apiv3.unsorted.actor.ActorType;
import net.frozenorb.apiv3.domain.IpLogEntry;
import net.frozenorb.apiv3.domain.Server;
import net.frozenorb.apiv3.domain.User;
import net.frozenorb.apiv3.util.ErrorUtils;
import net.frozenorb.apiv3.util.IpUtils;
import net.frozenorb.apiv3.util.UuidUtils;
import org.springframework.stereotype.Component;
import java.util.UUID;
import io.vertx.core.Handler;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.RoutingContext;
import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.domain.IpLogEntry;
import net.frozenorb.apiv3.domain.Server;
import net.frozenorb.apiv3.domain.User;
import net.frozenorb.apiv3.unsorted.actor.Actor;
import net.frozenorb.apiv3.unsorted.actor.ActorType;
import net.frozenorb.apiv3.util.ErrorUtils;
import net.frozenorb.apiv3.util.IpUtils;
import net.frozenorb.apiv3.util.UuidUtils;
import org.springframework.stereotype.Component;
import java.util.UUID;
@Component
public final class POSTUsersIdLogin implements Handler<RoutingContext> {

View File

@ -1,24 +1,21 @@
package net.frozenorb.apiv3.web.route.users;
import com.google.common.collect.ImmutableMap;
import io.vertx.core.Handler;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.RoutingContext;
import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.service.email.EmailService;
import net.frozenorb.apiv3.domain.NotificationTemplate;
import net.frozenorb.apiv3.domain.User;
import net.frozenorb.apiv3.service.email.EmailService;
import net.frozenorb.apiv3.unsorted.Notification;
import net.frozenorb.apiv3.util.ErrorUtils;
import net.frozenorb.apiv3.util.SyncUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Map;
import io.vertx.core.Handler;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.RoutingContext;
@Component
public final class POSTUsersIdNotify implements Handler<RoutingContext> {

View File

@ -1,28 +1,25 @@
package net.frozenorb.apiv3.web.route.users;
import com.google.common.collect.ImmutableMap;
import io.vertx.core.Handler;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.RoutingContext;
import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.domain.NotificationTemplate;
import net.frozenorb.apiv3.domain.User;
import net.frozenorb.apiv3.service.auditlog.AuditLog;
import net.frozenorb.apiv3.service.auditlog.AuditLogActionType;
import net.frozenorb.apiv3.service.email.EmailService;
import net.frozenorb.apiv3.domain.NotificationTemplate;
import net.frozenorb.apiv3.domain.User;
import net.frozenorb.apiv3.unsorted.Notification;
import net.frozenorb.apiv3.util.ErrorUtils;
import net.frozenorb.apiv3.util.IpUtils;
import net.frozenorb.apiv3.util.SyncUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import io.vertx.core.Handler;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.RoutingContext;
@Component
public final class POSTUsersIdPasswordReset implements Handler<RoutingContext> {

View File

@ -1,30 +1,27 @@
package net.frozenorb.apiv3.web.route.users;
import com.google.common.collect.ImmutableMap;
import io.vertx.core.Handler;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.RoutingContext;
import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.service.auditlog.AuditLog;
import net.frozenorb.apiv3.service.auditlog.AuditLogActionType;
import net.frozenorb.apiv3.service.emaildomain.EmailDomainService;
import net.frozenorb.apiv3.service.email.EmailService;
import net.frozenorb.apiv3.domain.NotificationTemplate;
import net.frozenorb.apiv3.domain.User;
import net.frozenorb.apiv3.service.auditlog.AuditLog;
import net.frozenorb.apiv3.service.auditlog.AuditLogActionType;
import net.frozenorb.apiv3.service.email.EmailService;
import net.frozenorb.apiv3.service.emaildomain.EmailDomainService;
import net.frozenorb.apiv3.unsorted.Notification;
import net.frozenorb.apiv3.util.EmailUtils;
import net.frozenorb.apiv3.util.ErrorUtils;
import net.frozenorb.apiv3.util.IpUtils;
import net.frozenorb.apiv3.util.SyncUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import io.vertx.core.Handler;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.RoutingContext;
@Component
public final class POSTUsersIdRegisterEmail implements Handler<RoutingContext> {

View File

@ -1,31 +1,28 @@
package net.frozenorb.apiv3.web.route.users;
import com.google.common.collect.ImmutableMap;
import io.vertx.core.Handler;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.RoutingContext;
import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.service.auditlog.AuditLog;
import net.frozenorb.apiv3.service.auditlog.AuditLogActionType;
import net.frozenorb.apiv3.domain.BannedCellCarrier;
import net.frozenorb.apiv3.domain.NotificationTemplate;
import net.frozenorb.apiv3.domain.PhoneIntel;
import net.frozenorb.apiv3.domain.User;
import net.frozenorb.apiv3.service.auditlog.AuditLog;
import net.frozenorb.apiv3.service.auditlog.AuditLogActionType;
import net.frozenorb.apiv3.service.sms.SmsService;
import net.frozenorb.apiv3.unsorted.Notification;
import net.frozenorb.apiv3.util.ErrorUtils;
import net.frozenorb.apiv3.util.IpUtils;
import net.frozenorb.apiv3.util.PhoneUtils;
import net.frozenorb.apiv3.util.SyncUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import io.vertx.core.Handler;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.RoutingContext;
@Component
public final class POSTUsersIdRegisterPhone implements Handler<RoutingContext> {

View File

@ -1,23 +1,20 @@
package net.frozenorb.apiv3.web.route.users;
import com.google.common.collect.ImmutableMap;
import io.vertx.core.Handler;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.RoutingContext;
import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.domain.User;
import net.frozenorb.apiv3.service.auditlog.AuditLog;
import net.frozenorb.apiv3.service.auditlog.AuditLogActionType;
import net.frozenorb.apiv3.domain.User;
import net.frozenorb.apiv3.service.totp.TotpService;
import net.frozenorb.apiv3.util.ErrorUtils;
import net.frozenorb.apiv3.util.IpUtils;
import net.frozenorb.apiv3.util.SyncUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import io.vertx.core.Handler;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.RoutingContext;
@Component
public final class POSTUsersIdSetupTotp implements Handler<RoutingContext> {

View File

@ -1,19 +1,16 @@
package net.frozenorb.apiv3.web.route.users;
import com.google.common.collect.ImmutableMap;
import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.service.auditlog.AuditLog;
import net.frozenorb.apiv3.service.auditlog.AuditLogActionType;
import net.frozenorb.apiv3.domain.User;
import net.frozenorb.apiv3.util.ErrorUtils;
import net.frozenorb.apiv3.util.IpUtils;
import org.springframework.stereotype.Component;
import io.vertx.core.Handler;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.RoutingContext;
import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.domain.User;
import net.frozenorb.apiv3.service.auditlog.AuditLog;
import net.frozenorb.apiv3.service.auditlog.AuditLogActionType;
import net.frozenorb.apiv3.util.ErrorUtils;
import net.frozenorb.apiv3.util.IpUtils;
import org.springframework.stereotype.Component;
@Component
public final class POSTUsersIdVerifyTotp implements Handler<RoutingContext> {

View File

@ -1,26 +1,23 @@
package net.frozenorb.apiv3.web.route.users;
import com.google.common.collect.ImmutableMap;
import io.vertx.core.Handler;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.RoutingContext;
import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.domain.User;
import net.frozenorb.apiv3.service.auditlog.AuditLog;
import net.frozenorb.apiv3.service.auditlog.AuditLogActionType;
import net.frozenorb.apiv3.domain.User;
import net.frozenorb.apiv3.service.usersession.UserSessionService;
import net.frozenorb.apiv3.util.ErrorUtils;
import net.frozenorb.apiv3.util.IpUtils;
import net.frozenorb.apiv3.util.PasswordUtils;
import net.frozenorb.apiv3.util.SyncUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
import io.vertx.core.Handler;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.RoutingContext;
@Component
public final class POSTUsersUsePasswordResetToken implements Handler<RoutingContext> {