Reorganize routes

This commit is contained in:
Colin McDonald 2016-04-08 07:12:31 -04:00
parent f627ba9358
commit 922357fc7f
27 changed files with 412 additions and 131 deletions

View File

@ -1,16 +1,28 @@
package net.frozenorb.apiv3;
import com.google.common.collect.ImmutableList;
import com.google.gson.ExclusionStrategy;
import com.google.gson.FieldAttributes;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.mongodb.MongoClient;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import lombok.Getter;
import net.frozenorb.apiv3.model.*;
import net.frozenorb.apiv3.weirdStuff.ExcludeFromReplies;
import net.frozenorb.apiv3.models.*;
import net.frozenorb.apiv3.routes.announcements.GETAnnouncements;
import net.frozenorb.apiv3.routes.chatFilterList.GETChatFilterList;
import net.frozenorb.apiv3.routes.grants.DELETEGrant;
import net.frozenorb.apiv3.routes.grants.GETGrants;
import net.frozenorb.apiv3.routes.grants.POSTUserGrant;
import net.frozenorb.apiv3.routes.punishments.DELETEPunishment;
import net.frozenorb.apiv3.routes.punishments.GETPunishments;
import net.frozenorb.apiv3.routes.punishments.POSTUserPunish;
import net.frozenorb.apiv3.routes.servers.GETServer;
import net.frozenorb.apiv3.routes.servers.GETServers;
import net.frozenorb.apiv3.routes.users.GETUser;
import net.frozenorb.apiv3.routes.users.GETUsers;
import net.frozenorb.apiv3.routes.users.GETStaff;
import net.frozenorb.apiv3.weirdStuff.ActorAttributeFilter;
import net.frozenorb.apiv3.weirdStuff.ContentTypeFilter;
import net.frozenorb.apiv3.weirdStuff.FollowAnnotationExclusionStrategy;
import net.frozenorb.apiv3.weirdStuff.ObjectIdTypeAdapter;
import org.bson.types.ObjectId;
@ -46,83 +58,28 @@ public final class APIv3 {
private void setupHttp() {
port(80);
before(new ActorAttributeFilter());
before((req, res) -> {
req.attribute("server", Server.byId(req.queryParams("server")));
});
get("/announcements", new GETAnnouncements(), gson::toJson);
get("/announcements", (req, res) -> {
Server sender = req.attribute("server");
ServerGroup senderGroup = sender.resolveGroup();
get("/chatFilterList", new GETChatFilterList(), gson::toJson);
return senderGroup.getAnnouncements();
}, gson::toJson);
delete("/grant/:id", new DELETEGrant(), gson::toJson);
get("/grants", new GETGrants(), gson::toJson);
post("/user/:id:/grant", new POSTUserGrant(), gson::toJson);
get("/chatFilterList", (req, res) -> {
Server sender = req.attribute("server");
ServerGroup senderGroup = sender.resolveGroup();
delete("/punishment/:id", new DELETEPunishment(), gson::toJson);
get("/punishments", new GETPunishments(), gson::toJson);
post("/user/:id:/punish", new POSTUserPunish(), gson::toJson);
return senderGroup.getChatFilterList();
}, gson::toJson);
get("/server/:id", new GETServer(), gson::toJson);
get("/servers", new GETServers(), gson::toJson);
get("/servers", (req, res) -> {
return APIv3.getDatastore().createQuery(Server.class).asList();
}, gson::toJson);
get("/user/:id", new GETUser(), gson::toJson);
get("/users", new GETUsers() gson::toJson);
get("/staff", new GETStaff(), gson::toJson);
get("/users", (req, res) -> {
return APIv3.getDatastore().createQuery(User.class).asList();
}, gson::toJson);
get("/user/create/:name", (req, res) -> {
User u = new User(UUID.randomUUID(), req.params("name"));
APIv3.getDatastore().save(u);
return u;
}, gson::toJson);
get("/staff", (req, res) -> {
Map<String, Rank> staffRanks = new HashMap<>();
APIv3.getDatastore().createQuery(Rank.class).forEach(rank -> {
if (rank.isStaff()) {
staffRanks.put(rank.getId(), rank);
}
});
Map<UUID, String> staffGrants = new HashMap<>();
APIv3.getDatastore().createQuery(Grant.class).field("rank").in(staffRanks.keySet()).forEach(grant -> {
if (grant.isActive()) {
staffGrants.put(grant.getTarget(), grant.getRank());
}
});
Map<Rank, Set<User>> result = new HashMap<>();
staffGrants.forEach((userId, rankId) -> {
User user = User.byId(userId);
Rank rank = staffRanks.get(rankId);
if (!result.containsKey(rank)) {
result.put(rank, new HashSet<>());
}
result.get(rank).add(user);
});
return result;
}, gson::toJson);
get("/grants", (req, res) -> {
int limit = Integer.parseInt(req.queryParams("limit"));
int offset = Integer.parseInt(req.queryParams("offset"));
return APIv3.getDatastore().createQuery(Grant.class).limit(limit).offset(offset).asList();
} ,gson::toJson);
after((req, res) -> {
res.header("content-type", "application/json");
});
after(new ContentTypeFilter());
}
}

View File

@ -1,4 +1,4 @@
package net.frozenorb.apiv3.model;
package net.frozenorb.apiv3.models;
import lombok.Getter;
import org.bson.Document;
@ -15,20 +15,20 @@ public final class AuditLogEntry {
@Id private ObjectId id;
@Getter private UUID performedBy;
@Getter private Date performedAt;
@Getter private String performedFromIp;
@Getter private String performedFrom;
@Getter private String actionType;
@Getter private Document actionData;
public AuditLogEntry() {} // For Morphia
public AuditLogEntry(UUID performedBy, String performedFromIp, String actionType) {
public AuditLogEntry(User performedBy, String performedFromIp, String actionType) {
this(performedBy, performedFromIp, actionType, new Document());
}
public AuditLogEntry(UUID performedBy, String performedFromIp, String actionType, Document actionData) {
this.performedBy = performedBy;
public AuditLogEntry(User performedBy, String performedFrom, String actionType, Document actionData) {
this.performedBy = performedBy.getId();
this.performedAt = new Date();
this.performedFromIp = performedFromIp;
this.performedFrom = performedFrom;
this.actionType = actionType;
this.actionData = actionData;
}

View File

@ -1,15 +1,13 @@
package net.frozenorb.apiv3.model;
package net.frozenorb.apiv3.models;
import com.google.common.collect.Collections2;
import lombok.Getter;
import net.frozenorb.apiv3.APIv3;
import org.bson.types.ObjectId;
import org.mongodb.morphia.annotations.Entity;
import org.mongodb.morphia.annotations.Id;
import java.time.Instant;
import java.util.Date;
import java.util.Set;
import java.util.UUID;
import java.util.*;
@Entity(value = "grants", noClassnameStored = true)
public final class Grant {
@ -28,20 +26,24 @@ public final class Grant {
@Getter private Date removedAt;
@Getter private String removalReason;
public static Grant byId(String id) {
return APIv3.getDatastore().createQuery(Grant.class).field("id").equal(new ObjectId(id)).get();
}
public Grant() {} // For Morphia
public Grant(UUID target, String reason, Set<String> scopes, String rankId, Date expiresAt, UUID addedBy) {
this.target = target;
public Grant(User target, String reason, Set<ServerGroup> scopes, Rank rank, Date expiresAt, User addedBy) {
this.target = target.getId();
this.reason = reason;
this.scopes = scopes;
this.rank = rankId;
this.scopes = new HashSet<>(Collections2.transform(scopes, ServerGroup::getId));
this.rank = rank.getId();
this.expiresAt = expiresAt;
this.addedBy = addedBy;
this.addedBy = addedBy.getId();
this.addedAt = new Date();
}
public void delete(UUID removedBy, String reason) {
this.removedBy = removedBy;
public void delete(User removedBy, String reason) {
this.removedBy = removedBy.getId();
this.removedAt = new Date();
this.removalReason = reason;

View File

@ -1,4 +1,4 @@
package net.frozenorb.apiv3.model;
package net.frozenorb.apiv3.models;
import org.bson.types.ObjectId;
import org.mongodb.morphia.annotations.Entity;

View File

@ -1,4 +1,4 @@
package net.frozenorb.apiv3.model;
package net.frozenorb.apiv3.models;
import lombok.Getter;
import net.frozenorb.apiv3.APIv3;
@ -6,7 +6,6 @@ import org.bson.types.ObjectId;
import org.mongodb.morphia.annotations.Entity;
import org.mongodb.morphia.annotations.Id;
import java.time.Instant;
import java.util.Date;
import java.util.UUID;
@ -22,8 +21,8 @@ public final class IPLogEntry {
public IPLogEntry() {} // For Morphia
public IPLogEntry(UUID user, String ip) {
this.user = user;
public IPLogEntry(User user, String ip) {
this.user = user.getId();
this.ip = ip;
this.firstSeen = new Date();
this.lastSeen = new Date();

View File

@ -1,11 +1,10 @@
package net.frozenorb.apiv3.model;
package net.frozenorb.apiv3.models;
import lombok.Getter;
import org.bson.types.ObjectId;
import org.mongodb.morphia.annotations.Entity;
import org.mongodb.morphia.annotations.Id;
import java.time.Instant;
import java.util.Date;
import java.util.UUID;

View File

@ -1,11 +1,10 @@
package net.frozenorb.apiv3.model;
package net.frozenorb.apiv3.models;
import lombok.Getter;
import net.frozenorb.apiv3.APIv3;
import org.mongodb.morphia.annotations.Entity;
import org.mongodb.morphia.annotations.Id;
import java.time.Instant;
import java.util.Date;
import java.util.Map;
import java.util.UUID;
@ -19,20 +18,24 @@ public final class NotificationTemplate {
@Getter private Date lastUpdatedAt;
@Getter private UUID lastUpdatedBy;
public NotificationTemplate() {} // For Morphia
public NotificationTemplate(String title, String body, UUID creator) {
this.title = title;
this.body = body;
this.lastUpdatedAt = new Date();
this.lastUpdatedBy = creator;
public static NotificationTemplate byId(String id) {
return APIv3.getDatastore().createQuery(NotificationTemplate.class).field("id").equal(id).get();
}
public void update(String title, String body, UUID updatedBy) {
public NotificationTemplate() {} // For Morphia
public NotificationTemplate(String title, String body, User creator) {
this.title = title;
this.body = body;
this.lastUpdatedAt = new Date();
this.lastUpdatedBy = updatedBy;
this.lastUpdatedBy = creator.getId();
}
public void update(String title, String body, User updatedBy) {
this.title = title;
this.body = body;
this.lastUpdatedAt = new Date();
this.lastUpdatedBy = updatedBy.getId();
APIv3.getDatastore().save(this);
}

View File

@ -1,13 +1,11 @@
package net.frozenorb.apiv3.model;
package net.frozenorb.apiv3.models;
import com.mongodb.async.SingleResultCallback;
import lombok.Getter;
import net.frozenorb.apiv3.APIv3;
import org.bson.types.ObjectId;
import org.mongodb.morphia.annotations.Entity;
import org.mongodb.morphia.annotations.Id;
import java.time.Instant;
import java.util.Date;
import java.util.UUID;
@ -28,16 +26,20 @@ public final class Punishment {
@Getter private Date removedAt;
@Getter private String removalReason;
public static Punishment byId(String id) {
return APIv3.getDatastore().createQuery(Punishment.class).field("id").equal(new ObjectId(id)).get();
}
public Punishment() {} // For Morphia
public Punishment(UUID target, String reason, PunishmentType type, Date expiresAt, UUID addedBy, String addedOn) {
this.target = target;
public Punishment(User target, String reason, PunishmentType type, Date expiresAt, User addedBy, Server addedOn) {
this.target = target.getId();
this.reason = reason;
this.type = type;
this.expiresAt = expiresAt;
this.addedBy = addedBy;
this.addedBy = addedBy.getId();
this.addedAt = new Date();
this.addedOn = addedOn;
this.addedOn = addedOn.getId();
}
public void delete(UUID removedBy, String reason) {

View File

@ -1,4 +1,4 @@
package net.frozenorb.apiv3.model;
package net.frozenorb.apiv3.models;
import lombok.Getter;
import net.frozenorb.apiv3.APIv3;
@ -13,17 +13,21 @@ public final class Rank {
@Getter private String displayName;
@Getter private String gameColor;
@Getter private String websiteColor;
@Getter private boolean staff;
@Getter private boolean staffRank;
public static Rank byId(String id) {
return APIv3.getDatastore().createQuery(Rank.class).field("id").equal(id).get();
}
public Rank() {} // For Morphia
public Rank(String id, int weight, String displayName, String gameColor, String websiteColor, boolean staff) {
public Rank(String id, int weight, String displayName, String gameColor, String websiteColor, boolean staffRank) {
this.id = id;
this.weight = weight;
this.displayName = displayName;
this.gameColor = gameColor;
this.websiteColor = websiteColor;
this.staff = staff;
this.staffRank = staffRank;
}
public void delete() {

View File

@ -1,19 +1,16 @@
package net.frozenorb.apiv3.model;
package net.frozenorb.apiv3.models;
import lombok.Getter;
import net.frozenorb.apiv3.APIv3;
import org.bson.Document;
import org.mongodb.morphia.annotations.Entity;
import org.mongodb.morphia.annotations.Id;
import java.lang.annotation.Documented;
import java.time.Instant;
import java.util.*;
@Entity(value = "servers", noClassnameStored = true)
public final class Server {
@Id private String id;
@Getter @Id private String id;
@Getter private String bungeeId;
@Getter private String displayName;
@Getter private String secret;
@ -29,12 +26,12 @@ public final class Server {
public Server() {} // For Morphia
public Server(String id, String bungeeId, String displayName, String secret, String group, String ip) {
public Server(String id, String bungeeId, String displayName, String secret, ServerGroup group, String ip) {
this.id = id;
this.bungeeId = bungeeId;
this.displayName = displayName;
this.secret = secret;
this.group = group;
this.group = group.getId();
this.ip = ip;
this.lastUpdate = new Date();
this.lastTps = 0;

View File

@ -1,4 +1,4 @@
package net.frozenorb.apiv3.model;
package net.frozenorb.apiv3.models;
import lombok.Getter;
import net.frozenorb.apiv3.APIv3;

View File

@ -1,4 +1,4 @@
package net.frozenorb.apiv3.model;
package net.frozenorb.apiv3.models;
import lombok.Getter;
import net.frozenorb.apiv3.APIv3;
@ -6,7 +6,6 @@ import net.frozenorb.apiv3.weirdStuff.ExcludeFromReplies;
import org.mongodb.morphia.annotations.Entity;
import org.mongodb.morphia.annotations.Id;
import java.time.Instant;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@ -31,6 +30,19 @@ public final class User {
return APIv3.getDatastore().createQuery(User.class).field("id").equal(id).get();
}
public static User byIdOrName(String idOrName) {
if (idOrName.length() == 36) {
return byId(UUID.fromString(idOrName));
} else {
return byName(idOrName);
}
}
@Deprecated
public static User byName(String name) {
return APIv3.getDatastore().createQuery(User.class).field("lastName").equal(name).get();
}
public User() {} // For Morphia
public User(UUID id, String lastName) {

View File

@ -0,0 +1,18 @@
package net.frozenorb.apiv3.routes.announcements;
import net.frozenorb.apiv3.models.Server;
import net.frozenorb.apiv3.models.ServerGroup;
import spark.Request;
import spark.Response;
import spark.Route;
public final class GETAnnouncements implements Route {
public Object handle(Request req, Response res) {
Server sender = req.attribute("server");
ServerGroup senderGroup = sender.resolveGroup();
return senderGroup.getAnnouncements();
}
}

View File

@ -0,0 +1,18 @@
package net.frozenorb.apiv3.routes.chatFilterList;
import net.frozenorb.apiv3.models.Server;
import net.frozenorb.apiv3.models.ServerGroup;
import spark.Request;
import spark.Response;
import spark.Route;
public final class GETChatFilterList implements Route {
public Object handle(Request req, Response res) {
Server sender = req.attribute("server");
ServerGroup senderGroup = sender.resolveGroup();
return senderGroup.getChatFilterList();
}
}

View File

@ -0,0 +1,24 @@
package net.frozenorb.apiv3.routes.grants;
import net.frozenorb.apiv3.models.Grant;
import net.frozenorb.apiv3.models.Server;
import net.frozenorb.apiv3.models.ServerGroup;
import net.frozenorb.apiv3.models.User;
import spark.Request;
import spark.Response;
import spark.Route;
import java.util.UUID;
public final class DELETEGrant implements Route {
public Object handle(Request req, Response res) {
Grant grant = Grant.byId(req.params("id"));
User removedBy = User.byId(UUID.fromString(req.queryParams("removedBy")));
String reason = req.queryParams("removalReason");
grant.delete(removedBy.getId(), reason);
return grant;
}
}

View File

@ -0,0 +1,20 @@
package net.frozenorb.apiv3.routes.grants;
import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.models.Grant;
import net.frozenorb.apiv3.models.Server;
import net.frozenorb.apiv3.models.ServerGroup;
import spark.Request;
import spark.Response;
import spark.Route;
public final class GETGrants implements Route {
public Object handle(Request req, Response res) {
int limit = Integer.parseInt(req.queryParams("limit"));
int offset = Integer.parseInt(req.queryParams("offset"));
return APIv3.getDatastore().createQuery(Grant.class).limit(limit).offset(offset).asList();
}
}

View File

@ -0,0 +1,28 @@
package net.frozenorb.apiv3.routes.grants;
import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.models.Grant;
import net.frozenorb.apiv3.models.Rank;
import net.frozenorb.apiv3.models.User;
import spark.Request;
import spark.Response;
import spark.Route;
import java.util.*;
public final class POSTUserGrant implements Route {
public Object handle(Request req, Response res) {
User target = User.byIdOrName(req.params("id"));
String reason = req.queryParams("reason");
Set<String> scopes = new HashSet<>(Arrays.asList(req.queryParams("scopes").split(",")));
Rank rank = Rank.byId(req.queryParams("rank"));
Date expiresAt = new Date(Long.parseLong(req.queryParams("expiresAt")));
User createdBy = User.byId(UUID.fromString(req.queryParams("createdBy")));
Grant grant = new Grant(target.getId(), reason, scopes, rank.getId(), expiresAt, createdBy.getId());
APIv3.getDatastore().save(grant);
return grant;
}
}

View File

@ -0,0 +1,22 @@
package net.frozenorb.apiv3.routes.punishments;
import net.frozenorb.apiv3.models.Punishment;
import net.frozenorb.apiv3.models.User;
import spark.Request;
import spark.Response;
import spark.Route;
import java.util.UUID;
public final class DELETEPunishment implements Route {
public Object handle(Request req, Response res) {
Punishment punishment = Punishment.byId(req.params("id"));
User removedBy = User.byId(UUID.fromString(req.queryParams("removedBy")));
String reason = req.queryParams("removalReason");
punishment.delete(removedBy.getId(), reason);
return punishment;
}
}

View File

@ -0,0 +1,18 @@
package net.frozenorb.apiv3.routes.punishments;
import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.models.Punishment;
import spark.Request;
import spark.Response;
import spark.Route;
public final class GETPunishments implements Route {
public Object handle(Request req, Response res) {
int limit = Integer.parseInt(req.queryParams("limit"));
int offset = Integer.parseInt(req.queryParams("offset"));
return APIv3.getDatastore().createQuery(Punishment.class).limit(limit).offset(offset).asList();
}
}

View File

@ -0,0 +1,29 @@
package net.frozenorb.apiv3.routes.punishments;
import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.models.Punishment;
import net.frozenorb.apiv3.models.Server;
import net.frozenorb.apiv3.models.User;
import spark.Request;
import spark.Response;
import spark.Route;
import java.util.Date;
import java.util.UUID;
public final class POSTUserPunish implements Route {
public Object handle(Request req, Response res) {
User target = User.byIdOrName(req.params("id"));
String reason = req.queryParams("reason");
Punishment.PunishmentType type = Punishment.PunishmentType.valueOf(req.queryParams("type"));
Date expiresAt = new Date(Long.parseLong(req.queryParams("expiresAt")));
User createdBy = User.byId(UUID.fromString(req.queryParams("createdBy")));
Server addedOn = Server.byId(req.queryParams("addedOn"));
Punishment punishment = new Punishment(target.getId(), reason, type, expiresAt, createdBy.getId(), addedOn.getId());
APIv3.getDatastore().save(punishment);
return punishment;
}
}

View File

@ -0,0 +1,14 @@
package net.frozenorb.apiv3.routes.servers;
import net.frozenorb.apiv3.models.Server;
import spark.Request;
import spark.Response;
import spark.Route;
public final class GETServer implements Route {
public Object handle(Request req, Response res) {
return Server.byId(req.params("id"));
}
}

View File

@ -0,0 +1,14 @@
package net.frozenorb.apiv3.routes.servers;
import net.frozenorb.apiv3.models.Server;
import spark.Request;
import spark.Response;
import spark.Route;
public final class GETServers implements Route {
public Object handle(Request req, Response res) {
return APIv3.getDatastore().createQuery(Server.class).asList();
}
}

View File

@ -0,0 +1,45 @@
package net.frozenorb.apiv3.routes.users;
import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.models.Grant;
import net.frozenorb.apiv3.models.Rank;
import net.frozenorb.apiv3.models.User;
import spark.Request;
import spark.Response;
import spark.Route;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public final class GETStaff implements Route {
public Object handle(Request req, Response res) {
Map<String, Rank> staffRanks = new HashMap<>();
APIv3.getDatastore().createQuery(Rank.class).forEach(rank -> {
if (rank.isStaffRank()) {
staffRanks.put(rank.getId(), rank);
}
});
Map<Rank, Set<User>> result = new HashMap<>();
APIv3.getDatastore().createQuery(Grant.class).field("rank").in(staffRanks.keySet()).forEach(grant -> {
if (grant.isActive()) {
User user = User.byId(grant.getTarget());
Rank rank = staffRanks.get(grant.getRank());
if (!result.containsKey(rank)) {
result.put(rank, new HashSet<>());
}
result.get(rank).add(user);
}
});
return result;
}
}

View File

@ -0,0 +1,14 @@
package net.frozenorb.apiv3.routes.users;
import net.frozenorb.apiv3.models.User;
import spark.Request;
import spark.Response;
import spark.Route;
public final class GETUser implements Route {
public Object handle(Request req, Response res) {
return User.byIdOrName(req.params("id"));
}
}

View File

@ -0,0 +1,15 @@
package net.frozenorb.apiv3.routes.users;
import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.models.User;
import spark.Request;
import spark.Response;
import spark.Route;
public final class GETUsers implements Route {
public Object handle(Request req, Response res) {
return APIv3.getDatastore().createQuery(User.class).asList();
}
}

View File

@ -0,0 +1,14 @@
package net.frozenorb.apiv3.weirdStuff;
import net.frozenorb.apiv3.models.Server;
import spark.Filter;
import spark.Request;
import spark.Response;
public final class ActorAttributeFilter implements Filter {
public void handle(Request req, Response res) {
req.attribute("server", Server.byId(req.queryParams("server")));
}
}

View File

@ -0,0 +1,13 @@
package net.frozenorb.apiv3.weirdStuff;
import spark.Filter;
import spark.Request;
import spark.Response;
public final class ContentTypeFilter implements Filter {
public void handle(Request req, Response res) {
res.header("content-type", "application/json");
}
}