Finish up punishment/grant routes, finish GET /dump, begin permission implementation

This commit is contained in:
Colin McDonald 2016-04-22 21:04:15 -04:00
parent fb12a13528
commit 2b57a5ef98
11 changed files with 156 additions and 14 deletions

View File

@ -8,6 +8,7 @@ import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress; import com.mongodb.ServerAddress;
import lombok.Getter; import lombok.Getter;
import net.frozenorb.apiv3.models.ServerGroup; import net.frozenorb.apiv3.models.ServerGroup;
import net.frozenorb.apiv3.routes.GETDump;
import net.frozenorb.apiv3.routes.announcements.GETAnnouncements; import net.frozenorb.apiv3.routes.announcements.GETAnnouncements;
import net.frozenorb.apiv3.routes.chatFilterList.GETChatFilterList; import net.frozenorb.apiv3.routes.chatFilterList.GETChatFilterList;
import net.frozenorb.apiv3.routes.grants.DELETEGrant; import net.frozenorb.apiv3.routes.grants.DELETEGrant;
@ -81,6 +82,8 @@ public final class APIv3 {
get("/users", new GETUsers(), gson::toJson); get("/users", new GETUsers(), gson::toJson);
get("/staff", new GETStaff(), gson::toJson); get("/staff", new GETStaff(), gson::toJson);
get("/dump/:type", new GETDump(), gson::toJson);
after(new ContentTypeFilter()); after(new ContentTypeFilter());
} }

View File

@ -68,7 +68,7 @@ public final class Punishment {
public enum PunishmentType { public enum PunishmentType {
BAN, MUTE, WARN BLACKLIST, BAN, MUTE, WARN
} }

View File

@ -30,6 +30,9 @@ public final class User {
return APIv3.getDatastore().createQuery(User.class).field("id").equal(id).get(); return APIv3.getDatastore().createQuery(User.class).field("id").equal(id).get();
} }
// TODO: FIND ALL USAGES OF THIS AND
// SEE HOW MANY OF THEM (EX NON GET REQUESTS)
// WE CAN DROP
public static User byIdOrName(String idOrName) { public static User byIdOrName(String idOrName) {
if (idOrName.length() == 36) { if (idOrName.length() == 36) {
return byId(UUID.fromString(idOrName)); return byId(UUID.fromString(idOrName));

View File

@ -0,0 +1,48 @@
package net.frozenorb.apiv3.routes;
import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.models.Grant;
import net.frozenorb.apiv3.models.Punishment;
import net.frozenorb.apiv3.weirdStuff.ErrorUtils;
import spark.Request;
import spark.Response;
import spark.Route;
import java.util.ArrayList;
import java.util.List;
public final class GETDump implements Route {
public Object handle(Request req, Response res) {
String type = req.params("type");
switch (type.toLowerCase()) {
case "blacklist":
case "ban":
case "mute":
case "warn":
List<Punishment> activePunishments = new ArrayList<>();
APIv3.getDatastore().createQuery(Punishment.class).field("type").equal(type.toUpperCase()).forEach((punishment) -> {
if (punishment.isActive()) {
activePunishments.add(punishment);
}
});
return activePunishments;
case "grant":
List<Grant> activeGrants = new ArrayList<>();
APIv3.getDatastore().createQuery(Grant.class).forEach((grant) -> {
if (grant.isActive()) {
activeGrants.add(grant);
}
});
return activeGrants;
default:
return ErrorUtils.invalidInput(type + " is not a valid type. Not in [blacklist, ban, mute, warn, grant]");
}
}
}

View File

@ -9,10 +9,10 @@ import spark.Route;
public final class GETGrants implements Route { public final class GETGrants implements Route {
public Object handle(Request req, Response res) { public Object handle(Request req, Response res) {
int limit = Integer.parseInt(req.queryParams("limit")); int limit = req.queryParams("limit") == null ? 100 : Integer.parseInt(req.queryParams("limit"));
int offset = Integer.parseInt(req.queryParams("offset")); int offset = req.queryParams("offset") == null ? 0 : Integer.parseInt(req.queryParams("offset"));
return APIv3.getDatastore().createQuery(Grant.class).limit(limit).offset(offset).asList(); return APIv3.getDatastore().createQuery(Grant.class).order("addedAt").limit(limit).offset(offset).asList();
} }
} }

View File

@ -3,26 +3,60 @@ package net.frozenorb.apiv3.routes.grants;
import net.frozenorb.apiv3.APIv3; import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.models.Grant; import net.frozenorb.apiv3.models.Grant;
import net.frozenorb.apiv3.models.Rank; import net.frozenorb.apiv3.models.Rank;
import net.frozenorb.apiv3.models.ServerGroup;
import net.frozenorb.apiv3.models.User; import net.frozenorb.apiv3.models.User;
import net.frozenorb.apiv3.weirdStuff.ErrorUtils;
import net.frozenorb.apiv3.weirdStuff.Permissions;
import spark.Request; import spark.Request;
import spark.Response; import spark.Response;
import spark.Route; import spark.Route;
import java.util.*; import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
public final class POSTUserGrant implements Route { public final class POSTUserGrant implements Route {
public Object handle(Request req, Response res) { public Object handle(Request req, Response res) {
User target = User.byIdOrName(req.params("id")); User target = User.byIdOrName(req.params("id"));
if (target == null) {
return ErrorUtils.notFound("User", req.params("id"));
}
String reason = req.queryParams("reason"); String reason = req.queryParams("reason");
Set<String> scopes = new HashSet<>(Arrays.asList(req.queryParams("scopes").split(",")));
if (reason.trim().isEmpty()) {
return ErrorUtils.invalidInput("A reason must be provided.");
}
Set<ServerGroup> scopes = new HashSet<>(/*Arrays.asList(req.queryParams("scopes").split(","))*/);
// TODO
Rank rank = Rank.byId(req.queryParams("rank")); Rank rank = Rank.byId(req.queryParams("rank"));
if (rank == null) {
return ErrorUtils.notFound("Rank", req.queryParams("rank"));
}
Date expiresAt = new Date(Long.parseLong(req.queryParams("expiresAt"))); Date expiresAt = new Date(Long.parseLong(req.queryParams("expiresAt")));
if (expiresAt.before(new Date())) {
return ErrorUtils.invalidInput("Expiration date cannot be in the past.");
}
User addedBy = User.byId(UUID.fromString(req.queryParams("addedBy"))); User addedBy = User.byId(UUID.fromString(req.queryParams("addedBy")));
String requiredPermission = Permissions.CREATE_GRANT + "." + rank.getId();
if (addedBy == null) {
return ErrorUtils.notFound("User", req.queryParams("addedBy"));
} else if (!addedBy.hasPermissionAnywhere(requiredPermission)) {
return ErrorUtils.unauthorized(requiredPermission);
}
Grant grant = new Grant(target, reason, scopes, rank, expiresAt, addedBy); Grant grant = new Grant(target, reason, scopes, rank, expiresAt, addedBy);
APIv3.getDatastore().save(grant); APIv3.getDatastore().save(grant);
return grant; return grant;
} }
} }

View File

@ -3,6 +3,8 @@ package net.frozenorb.apiv3.routes.punishments;
import net.frozenorb.apiv3.models.Punishment; import net.frozenorb.apiv3.models.Punishment;
import net.frozenorb.apiv3.models.User; import net.frozenorb.apiv3.models.User;
import net.frozenorb.apiv3.weirdStuff.AuditLog; import net.frozenorb.apiv3.weirdStuff.AuditLog;
import net.frozenorb.apiv3.weirdStuff.ErrorUtils;
import net.frozenorb.apiv3.weirdStuff.Permissions;
import org.bson.Document; import org.bson.Document;
import spark.Request; import spark.Request;
import spark.Response; import spark.Response;
@ -14,7 +16,22 @@ public final class DELETEPunishment implements Route {
public Object handle(Request req, Response res) { public Object handle(Request req, Response res) {
Punishment punishment = Punishment.byId(req.params("id")); Punishment punishment = Punishment.byId(req.params("id"));
if (punishment == null) {
return ErrorUtils.notFound("Punishment", req.params("id"));
} else if (!punishment.isActive()) {
return ErrorUtils.error("Cannot remove an inactive punishment.");
}
User removedBy = User.byId(UUID.fromString(req.queryParams("removedBy"))); User removedBy = User.byId(UUID.fromString(req.queryParams("removedBy")));
String requiredPermission = Permissions.REMOVE_PUNISHMENT + "." + punishment.getType().name();
if (removedBy == null) {
return ErrorUtils.notFound("User", req.queryParams("removedBy"));
} else if (!removedBy.hasPermissionAnywhere(requiredPermission)) {
return ErrorUtils.unauthorized(requiredPermission);
}
String removedByIp = req.queryParams("removedByIp"); String removedByIp = req.queryParams("removedByIp");
String reason = req.queryParams("removalReason"); String reason = req.queryParams("removalReason");

View File

@ -9,10 +9,10 @@ import spark.Route;
public final class GETPunishments implements Route { public final class GETPunishments implements Route {
public Object handle(Request req, Response res) { public Object handle(Request req, Response res) {
int limit = Integer.parseInt(req.queryParams("limit")); int limit = req.queryParams("limit") == null ? 100 : Integer.parseInt(req.queryParams("limit"));
int offset = Integer.parseInt(req.queryParams("offset")); int offset = req.queryParams("offset") == null ? 0 : Integer.parseInt(req.queryParams("offset"));
return APIv3.getDatastore().createQuery(Punishment.class).limit(limit).offset(offset).asList(); return APIv3.getDatastore().createQuery(Punishment.class).order("addedAt").limit(limit).offset(offset).asList();
} }
} }

View File

@ -4,6 +4,8 @@ import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.models.Punishment; import net.frozenorb.apiv3.models.Punishment;
import net.frozenorb.apiv3.models.Server; import net.frozenorb.apiv3.models.Server;
import net.frozenorb.apiv3.models.User; import net.frozenorb.apiv3.models.User;
import net.frozenorb.apiv3.weirdStuff.ErrorUtils;
import net.frozenorb.apiv3.weirdStuff.Permissions;
import spark.Request; import spark.Request;
import spark.Response; import spark.Response;
import spark.Route; import spark.Route;
@ -15,13 +17,40 @@ public final class POSTUserPunish implements Route {
public Object handle(Request req, Response res) { public Object handle(Request req, Response res) {
User target = User.byIdOrName(req.params("id")); User target = User.byIdOrName(req.params("id"));
if (target == null) {
return ErrorUtils.notFound("User", req.params("id"));
}
String reason = req.queryParams("reason"); String reason = req.queryParams("reason");
if (reason.trim().isEmpty()) {
return ErrorUtils.invalidInput("A reason must be provided.");
}
Punishment.PunishmentType type = Punishment.PunishmentType.valueOf(req.queryParams("type")); Punishment.PunishmentType type = Punishment.PunishmentType.valueOf(req.queryParams("type"));
Date expiresAt = new Date(Long.parseLong(req.queryParams("expiresAt"))); Date expiresAt = new Date(Long.parseLong(req.queryParams("expiresAt")));
User createdBy = User.byId(UUID.fromString(req.queryParams("createdBy")));
if (expiresAt.before(new Date())) {
return ErrorUtils.invalidInput("Expiration date cannot be in the past.");
}
User addedBy = User.byId(UUID.fromString(req.queryParams("addedBy")));
String requiredPermission = Permissions.CREATE_PUNISHMENT + "." + type.name();
if (addedBy == null) {
return ErrorUtils.notFound("User", req.queryParams("addedBy"));
} else if (!addedBy.hasPermissionAnywhere(requiredPermission)) {
return ErrorUtils.unauthorized(requiredPermission);
}
Server addedOn = Server.byId(req.queryParams("addedOn")); Server addedOn = Server.byId(req.queryParams("addedOn"));
Punishment punishment = new Punishment(target, reason, type, expiresAt, createdBy, addedOn); if (addedOn == null) {
return ErrorUtils.notFound("Server", req.queryParams("addedOn"));
}
Punishment punishment = new Punishment(target, reason, type, expiresAt, addedBy, addedOn);
APIv3.getDatastore().save(punishment); APIv3.getDatastore().save(punishment);
return punishment; return punishment;
} }

View File

@ -7,11 +7,15 @@ import org.bson.Document;
public class ErrorUtils { public class ErrorUtils {
public static Document notFound(String itemType, String id) { public static Document notFound(String itemType, String id) {
return error(itemType + " with id " + id + " cannot be found."); return error("Not found: " + itemType + " with id " + id + " cannot be found.");
} }
public static Document unauthorized(String permission) { public static Document unauthorized(String permission) {
return error("Unauthorized access. Permission \"" + permission + "\" required."); return error("Unauthorized access: Permission \"" + permission + "\" required.");
}
public static Document invalidInput(String reason) {
return error("Invalid input: " + reason);
} }
public static Document error(String reason) { public static Document error(String reason) {

View File

@ -6,5 +6,9 @@ import lombok.experimental.UtilityClass;
public class Permissions { public class Permissions {
public static final String REMOVE_GRANT = "minehq.grant.remove"; // minehq.grant.remove.%RANK% public static final String REMOVE_GRANT = "minehq.grant.remove"; // minehq.grant.remove.%RANK%
public static final String CREATE_GRANT = "minehq.grant.create"; // minehq.grant.create.%RANK%
public static final String REMOVE_PUNISHMENT = "minehq.punishment.remove"; // minehq.punishment.remove.%TYPE%
public static final String CREATE_PUNISHMENT = "minehq.punishment.create"; // minehq.punishment.remove.%TYPE%
} }