Ayy more code

This commit is contained in:
Colin McDonald 2016-04-30 14:03:34 -04:00
parent 3780ead458
commit 1d5d2d198b
11 changed files with 249 additions and 53 deletions

View File

@ -12,6 +12,8 @@ import net.frozenorb.apiv3.filters.AuthorizationFilter;
import net.frozenorb.apiv3.filters.ContentTypeFilter;
import net.frozenorb.apiv3.routes.GETDump;
import net.frozenorb.apiv3.routes.GETRoutes;
import net.frozenorb.apiv3.routes.POSTConfirmRegister;
import net.frozenorb.apiv3.routes.POSTHeartbeat;
import net.frozenorb.apiv3.routes.announcements.GETAnnouncements;
import net.frozenorb.apiv3.routes.chatFilterList.GETChatFilterList;
import net.frozenorb.apiv3.routes.grants.DELETEGrant;
@ -116,13 +118,15 @@ public final class APIv3 {
get("/user/:id", new GETUser(), gson::toJson);
get("/user/:id/details", new GETUserDetails(), gson::toJson);
get("/user/:id/meta/:serverGroup", new GETUserMeta(), gson::toJson);
post("/user/:id/login", new POSTUserLogin(), gson::toJson);
post("/user/:id/loginInfo", new POSTUserLoginInfo(), gson::toJson);
post("/user/:id/notify", new POSTUserNotify(), gson::toJson);
post("/user/:id/register", new POSTUserRegister(), gson::toJson);
put("/user/:id/meta/:serverGroup", new PUTUserMeta(), gson::toJson);
get("/dump/:type", new GETDump(), gson::toJson);
get("/routes", new GETRoutes());
post("/confirmRegister", new POSTConfirmRegister(), gson::toJson);
post("/heartbeat", new POSTHeartbeat(), gson::toJson);
}
}

View File

@ -8,6 +8,7 @@ import spark.Response;
public final class ActorAttributeFilter implements Filter {
public void handle(Request req, Response res) {
// TODO: IF THEYRE A SERVER PERFORM PRE-VALIDATION TO MAKE SURE IT EXISTS
// TODO: Auth!
req.attribute("actor", new Actor() {

View File

@ -70,11 +70,15 @@ public final class Grant {
}
public boolean appliesOn(Server server) {
return scopes.contains(server.getId());
return isGlobal() || scopes.contains(server.getId());
}
public boolean appliesOn(ServerGroup serverGroup) {
return scopes.contains(serverGroup.getId());
return isGlobal() || scopes.contains(serverGroup.getId());
}
public boolean isGlobal() {
return scopes.isEmpty();
}
}

View File

@ -18,7 +18,7 @@ public final class Rank {
@Getter private boolean staffRank;
public static Rank byId(String id) {
return APIv3.getDatastore().createQuery(Rank.class).order("weight").field("id").equalIgnoreCase(id).get();
return APIv3.getDatastore().createQuery(Rank.class).field("id").equalIgnoreCase(id).get();
}
public static List<Rank> values() {

View File

@ -1,6 +1,7 @@
package net.frozenorb.apiv3.models;
import lombok.Getter;
import lombok.Setter;
import net.frozenorb.apiv3.APIv3;
import org.mongodb.morphia.annotations.Entity;
import org.mongodb.morphia.annotations.Id;
@ -16,9 +17,9 @@ public final class Server {
@Getter private String secret;
@Getter private String group;
@Getter private String ip;
@Getter private Date lastUpdate;
@Getter private double lastTps;
@Getter private Set<UUID> players;
@Getter @Setter private Date lastUpdate;
@Getter @Setter private double lastTps;
@Getter @Setter private Set<UUID> players;
public static Server byId(String id) {
return APIv3.getDatastore().createQuery(Server.class).field("id").equalIgnoreCase(id).get();

View File

@ -47,4 +47,24 @@ public final class ServerGroup {
return new HashMap<>();
}
public Map<String, Boolean> calculatePermissions(Rank userRank) {
/*ServerGroup scope = ServerGroup.byId("HCTeams");
Map<ServerGroup, Rank> userRanks = new HashMap<>();
//ServerGroup global = ServerGroup.byId("Global");
Map<String, Boolean> calculatedPermissions = global.getPermissions(userRanks.get(global));
// for global calculations
for (ServerGroup serverGroup : ServerGroup.values()) {
mergePermissions(serverGroup, userRanks.get(serverGroup), calculatedPermissions);
}
// for scoped calculations
mergePermissions(scope, userRanks.get(scope), calculatedPermissions);*/
return null;
}
}

View File

@ -1,9 +1,12 @@
package net.frozenorb.apiv3.models;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import lombok.Getter;
import lombok.Setter;
import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.serialization.ExcludeFromReplies;
import net.frozenorb.apiv3.utils.TimeUtils;
import org.bson.Document;
import org.mindrot.jbcrypt.BCrypt;
import org.mongodb.morphia.annotations.Entity;
@ -91,10 +94,6 @@ public final class User {
return APIv3.getDatastore().createQuery(Grant.class).field("target").equal(id).asList();
}
public List<Grant> getGrants(ServerGroup scope) {
return APIv3.getDatastore().createQuery(Grant.class).field("target").equal(id).field("scopes").equalIgnoreCase(scope.getId()).asList();
}
public List<IPLogEntry> getIPLog() {
return APIv3.getDatastore().createQuery(IPLogEntry.class).field("user").equal(id).asList();
}
@ -130,28 +129,74 @@ public final class User {
return BCrypt.checkpw(new String(unencrypted), password);
}
public Map<String, Boolean> calculateGlobalPermissions() {
return null;
}
public Rank getHighestRank(ServerGroup serverGroup) {
Rank highest = null;
public Map<String, Boolean> calculatePermissions(ServerGroup serverGroup) {
/*ServerGroup scope = ServerGroup.byId("HCTeams");
Map<ServerGroup, Rank> userRanks = new HashMap<>();
for (Grant grant : getGrants()) {
if (!grant.isActive()) {
continue;
}
if (serverGroup != null && !grant.appliesOn(serverGroup)) {
continue;
}
//ServerGroup global = ServerGroup.byId("Global");
Map<String, Boolean> calculatedPermissions = global.getPermissions(userRanks.get(global));
Rank rank = Rank.byId(grant.getRank());
// for global calculations
for (ServerGroup serverGroup : ServerGroup.values()) {
mergePermissions(serverGroup, userRanks.get(serverGroup), calculatedPermissions);
if (highest == null || rank.getWeight() > highest.getWeight()) {
highest = rank;
}
}
// for scoped calculations
if (highest != null) {
return highest;
} else {
return Rank.byId("default");
}
}
mergePermissions(scope, userRanks.get(scope), calculatedPermissions);*/
return null;
public Rank getHighestRankAnywhere() {
return getHighestRank(null);
}
public Map<String, Object> getLoginInfo(Server server) {
String accessDenialReason = null;
for (Punishment punishment : getPunishments(ImmutableSet.of(
Punishment.PunishmentType.BLACKLIST,
Punishment.PunishmentType.BAN
))) {
if (!punishment.isActive()) {
continue;
}
if (punishment.getType() == Punishment.PunishmentType.BLACKLIST) {
accessDenialReason = "Your account has been blacklisted from the MineHQ Network. \n\nThis type of punishment cannot be appealed.";
} else {
accessDenialReason = "Your account has been suspended from the MineHQ Network. \n\n";
if (punishment.getExpiresAt() != null) {
accessDenialReason += "Expires in " + TimeUtils.formatIntoDetailedString(TimeUtils.getSecondsBetween(punishment.getExpiresAt(), new Date()));
} else {
accessDenialReason += "Appeal at MineHQ.com/appeal";
}
}
}
ServerGroup actorGroup = server.resolveGroup();
Rank rank = getHighestRank(actorGroup);
Map<String, Boolean> rankPermissions = actorGroup.calculatePermissions(rank);
return ImmutableMap.of(
"user", this,
"access", ImmutableMap.of(
"allowed", accessDenialReason == null,
"reason", accessDenialReason == null ? "Public server" : accessDenialReason
),
"rank", rank,
"permissions", rankPermissions
);
}
}

View File

@ -0,0 +1,71 @@
package net.frozenorb.apiv3.routes;
import com.google.common.collect.ImmutableMap;
import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.models.Server;
import net.frozenorb.apiv3.models.User;
import net.frozenorb.apiv3.unsorted.Actor;
import net.frozenorb.apiv3.utils.ErrorUtils;
import org.bson.Document;
import spark.Request;
import spark.Response;
import spark.Route;
import java.util.*;
public final class POSTHeartbeat implements Route {
public Object handle(Request req, Response res) {
Actor actor = req.attribute("actor");
if (actor.getType() != Actor.Type.SERVER) {
return ErrorUtils.error("Heartbeats can only be performed when requested by a server.");
}
Server actorServer = Server.byId(actor.getName());
Document reqJson = Document.parse(req.body());
Set<UUID> onlinePlayers = new HashSet<>();
Map<String, Object> playersResponse = new HashMap<>();
// TODO: SAW ON SERVER STUFF
for (Object player : (List<Object>) reqJson.get("players")) {
Document playerJson = (Document) player;
User user = User.byId(playerJson.getString("uuid"));
String username = playerJson.getString("username");
if (user == null) {
user = new User(UUID.fromString(playerJson.getString("uuid")), username);
APIv3.getDatastore().save(user);
}
onlinePlayers.add(user.getId());
playersResponse.put(user.getId().toString(), user.getLoginInfo(actorServer));
}
for (Object event : (List<Object>) reqJson.get("events")) {
Document eventJson = (Document) event;
String type = eventJson.getString("type");
switch (type) {
case "join":
break;
case "leave":
break;
case "metrics":
break;
default:
System.err.println("Recieved event with unknown type " + type + ".");
}
}
actorServer.setPlayers(onlinePlayers);
actorServer.setLastTps(reqJson.getDouble("lastTps"));
actorServer.setLastUpdate(new Date());
return ImmutableMap.of(
"players", playersResponse
);
}
}

View File

@ -1,27 +0,0 @@
package net.frozenorb.apiv3.routes.users;
import com.google.common.collect.ImmutableMap;
import net.frozenorb.apiv3.models.User;
import net.frozenorb.apiv3.utils.ErrorUtils;
import spark.Request;
import spark.Response;
import spark.Route;
public final class POSTUserLogin implements Route {
public Object handle(Request req, Response res) {
User user = User.byIdOrName(req.params("id"));
if (user == null) {
return ErrorUtils.notFound("User", req.params("id"));
}
return ImmutableMap.of(
"user", user,
"access", user.getGrants(),
"rank", user.getIPLog(),
"permissions", user.getPunishments()
);
}
}

View File

@ -0,0 +1,36 @@
package net.frozenorb.apiv3.routes.users;
import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.models.Server;
import net.frozenorb.apiv3.models.User;
import net.frozenorb.apiv3.unsorted.Actor;
import net.frozenorb.apiv3.utils.ErrorUtils;
import spark.Request;
import spark.Response;
import spark.Route;
import java.util.UUID;
public final class POSTUserLoginInfo implements Route {
public Object handle(Request req, Response res) {
User user = User.byId(req.params("id"));
String username = req.queryParams("username");
Actor actor = req.attribute("actor");
if (actor.getType() != Actor.Type.SERVER) {
return ErrorUtils.error("Login info requests can only be performed when requested by a server.");
}
// TODO: IP Logs
if (user == null) {
user = new User(UUID.fromString(req.params("id")), username);
APIv3.getDatastore().save(user);
}
Server actorServer = Server.byId(actor.getName());
return user.getLoginInfo(actorServer);
}
}

View File

@ -0,0 +1,41 @@
package net.frozenorb.apiv3.utils;
import lombok.experimental.UtilityClass;
import java.text.SimpleDateFormat;
import java.util.Date;
@UtilityClass
public class TimeUtils {
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm");
public static String formatIntoDetailedString(int secs) {
if (secs == 0) {
return "0 seconds";
}
int remainder = secs % 86400;
int days = secs / 86400;
int hours = remainder / 3600;
int minutes = (remainder / 60) - (hours * 60);
int seconds = (remainder % 3600) - (minutes * 60);
String fDays = (days > 0 ? " " + days + " day" + (days > 1 ? "s" : "") : "");
String fHours = (hours > 0 ? " " + hours + " hour" + (hours > 1 ? "s" : "") : "");
String fMinutes = (minutes > 0 ? " " + minutes + " minute" + (minutes > 1 ? "s" : "") : "");
String fSeconds = (seconds > 0 ? " " + seconds + " second" + (seconds > 1 ? "s" : "") : "");
return (fDays + fHours + fMinutes + fSeconds).trim();
}
public static String formatIntoCalendarString(Date date) {
return (dateFormat.format(date));
}
public static int getSecondsBetween(Date a, Date b) {
return (Math.abs((int) (a.getTime() - b.getTime()) / 1000));
}
}