Whoo more permission stuff
This commit is contained in:
parent
1d5d2d198b
commit
583f91b45e
@ -5,4 +5,7 @@ mongo.username=test
|
||||
mongo.password=test
|
||||
http.address=
|
||||
http.port=80
|
||||
http.workerThreads=4
|
||||
mandrill.apiKey=0OYtwymqJP6oqvszeJu0vQ
|
||||
auth.permittedUserRanks=developer,owner
|
||||
auth.websiteApiKey=RVbp4hY6sCFVaf
|
@ -11,9 +11,6 @@ import net.frozenorb.apiv3.filters.ActorAttributeFilter;
|
||||
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;
|
||||
@ -30,21 +27,23 @@ import net.frozenorb.apiv3.routes.serverGroups.GETServerGroup;
|
||||
import net.frozenorb.apiv3.routes.serverGroups.GETServerGroups;
|
||||
import net.frozenorb.apiv3.routes.servers.GETServer;
|
||||
import net.frozenorb.apiv3.routes.servers.GETServers;
|
||||
import net.frozenorb.apiv3.routes.servers.POSTServerHeartbeat;
|
||||
import net.frozenorb.apiv3.routes.users.*;
|
||||
import net.frozenorb.apiv3.serialization.FollowAnnotationExclusionStrategy;
|
||||
import net.frozenorb.apiv3.serialization.ObjectIdTypeAdapter;
|
||||
import net.frozenorb.apiv3.unsorted.LoggingExceptionHandler;
|
||||
import org.bson.types.ObjectId;
|
||||
import org.mongodb.morphia.Datastore;
|
||||
import org.mongodb.morphia.Morphia;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.Properties;
|
||||
|
||||
import static spark.Spark.*;
|
||||
|
||||
public final class APIv3 {
|
||||
|
||||
// TODO: Cleanup main class
|
||||
|
||||
@Getter private static Datastore datastore;
|
||||
@Getter private static Properties config = new Properties();
|
||||
private final Gson gson = new GsonBuilder()
|
||||
@ -53,80 +52,74 @@ public final class APIv3 {
|
||||
.create();
|
||||
|
||||
APIv3() {
|
||||
try {
|
||||
// TODO: Load
|
||||
config.load(APIv3.class.getClassLoader().getResourceAsStream("apiv3.properties"));
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
|
||||
setupConfig();
|
||||
setupDatabase();
|
||||
setupHttp();
|
||||
}
|
||||
|
||||
private void setupConfig() {
|
||||
try (InputStream in = new FileInputStream("apiv3.properties")) {
|
||||
config.load(in);
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void setupDatabase() {
|
||||
MongoClient mongoClient = new MongoClient(new ServerAddress(
|
||||
(String) config.get("mongo.address"),
|
||||
(Integer) config.get("mongo.port")),
|
||||
config.getProperty("mongo.address"),
|
||||
Integer.parseInt(config.getProperty("mongo.port"))),
|
||||
ImmutableList.of(
|
||||
MongoCredential.createCredential(
|
||||
(String) config.get("mongo.username"),
|
||||
(String) config.get("mongo.database"),
|
||||
((String) config.get("mongo.password")).toCharArray())
|
||||
config.getProperty("mongo.username"),
|
||||
config.getProperty("mongo.database"),
|
||||
config.getProperty("mongo.password").toCharArray())
|
||||
));
|
||||
|
||||
Morphia morphia = new Morphia();
|
||||
morphia.mapPackage("net.frozenorb.apiv3.accessor");
|
||||
|
||||
datastore = morphia.createDatastore(mongoClient, (String) config.get("mongo.database"));
|
||||
datastore = morphia.createDatastore(mongoClient, config.getProperty("mongo.database"));
|
||||
datastore.ensureIndexes();
|
||||
}
|
||||
|
||||
private void setupHttp() {
|
||||
ipAddress((String) config.get("http.address"));
|
||||
port((Integer) config.get("http.port"));
|
||||
ipAddress(config.getProperty("http.address"));
|
||||
port(Integer.parseInt(config.getProperty("http.port")));
|
||||
threadPool(Integer.parseInt(config.getProperty("http.workerThreads")));
|
||||
before(new ContentTypeFilter());
|
||||
before(new ActorAttributeFilter());
|
||||
before(new AuthorizationFilter());
|
||||
exception(Exception.class, new LoggingExceptionHandler());
|
||||
|
||||
get("/announcements", new GETAnnouncements(), gson::toJson);
|
||||
|
||||
get("/chatFilterList", new GETChatFilterList(), gson::toJson);
|
||||
|
||||
delete("/grant/:id", new DELETEGrant(), gson::toJson);
|
||||
get("/grants", new GETGrants(), gson::toJson);
|
||||
get("/user/:id/grants", new GETUserGrants(), gson::toJson);
|
||||
post("/user/:id:/grant", new POSTUserGrant(), gson::toJson);
|
||||
|
||||
get("/user/:id/ipLog", new GETUserIPLog(), gson::toJson);
|
||||
|
||||
delete("/punishment/:id", new DELETEPunishment(), gson::toJson);
|
||||
get("/punishment/:id", new GETPunishment(), gson::toJson);
|
||||
get("/punishments", new GETPunishments(), gson::toJson);
|
||||
post("/user/:id:/punish", new POSTUserPunish(), gson::toJson);
|
||||
|
||||
get("/ranks", new GETRanks(), gson::toJson);
|
||||
|
||||
get("/serverGroup/:id", new GETServerGroup(), gson::toJson);
|
||||
get("/serverGroups", new GETServerGroups(), gson::toJson);
|
||||
|
||||
get("/server/:id", new GETServer(), gson::toJson);
|
||||
get("/servers", new GETServers(), gson::toJson);
|
||||
|
||||
post("/server/heartbeat", new POSTServerHeartbeat(), gson::toJson);
|
||||
delete("/user/:id/meta", new DELETEUserMeta(), gson::toJson);
|
||||
get("/staff", new GETStaff(), gson::toJson);
|
||||
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/confirmRegister/:emailToken", new POSTUserConfirmRegister(), 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);
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
package net.frozenorb.apiv3;
|
||||
|
||||
public final class Main {
|
||||
final class Main {
|
||||
|
||||
public static void main(String[] args) {
|
||||
new APIv3();
|
||||
|
@ -1,4 +1,4 @@
|
||||
package net.frozenorb.apiv3.unsorted;
|
||||
package net.frozenorb.apiv3.actors;
|
||||
|
||||
public interface Actor {
|
||||
|
25
src/main/java/net/frozenorb/apiv3/actors/ServerActor.java
Normal file
25
src/main/java/net/frozenorb/apiv3/actors/ServerActor.java
Normal file
@ -0,0 +1,25 @@
|
||||
package net.frozenorb.apiv3.actors;
|
||||
|
||||
import net.frozenorb.apiv3.models.Server;
|
||||
|
||||
public final class ServerActor implements Actor {
|
||||
|
||||
private final Server server;
|
||||
|
||||
public ServerActor(Server server) {
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
public boolean isAuthorized() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return server.getId();
|
||||
}
|
||||
|
||||
public Actor.Type getType() {
|
||||
return Actor.Type.SERVER;
|
||||
}
|
||||
|
||||
}
|
17
src/main/java/net/frozenorb/apiv3/actors/UnknownActor.java
Normal file
17
src/main/java/net/frozenorb/apiv3/actors/UnknownActor.java
Normal file
@ -0,0 +1,17 @@
|
||||
package net.frozenorb.apiv3.actors;
|
||||
|
||||
public final class UnknownActor implements Actor {
|
||||
|
||||
public boolean isAuthorized() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
public Actor.Type getType() {
|
||||
return Actor.Type.UNKNOWN;
|
||||
}
|
||||
|
||||
}
|
39
src/main/java/net/frozenorb/apiv3/actors/UserActor.java
Normal file
39
src/main/java/net/frozenorb/apiv3/actors/UserActor.java
Normal file
@ -0,0 +1,39 @@
|
||||
package net.frozenorb.apiv3.actors;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import net.frozenorb.apiv3.APIv3;
|
||||
import net.frozenorb.apiv3.models.User;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public final class UserActor implements Actor {
|
||||
|
||||
private static final Set<String> authorizedUserGrants = ImmutableSet.copyOf(APIv3.getConfig().getProperty("auth.permittedUserRanks").split(","));
|
||||
|
||||
private final User user;
|
||||
// We use Boolean here so we can have null = not calculated;
|
||||
private Boolean cachedAuthorized = null;
|
||||
|
||||
public UserActor(User user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public boolean isAuthorized() {
|
||||
if (cachedAuthorized != null) {
|
||||
return cachedAuthorized;
|
||||
} else {
|
||||
String highestRankId = user.getHighestRank().getId();
|
||||
cachedAuthorized = authorizedUserGrants.contains(highestRankId);
|
||||
return cachedAuthorized;
|
||||
}
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return user.getLastUsername();
|
||||
}
|
||||
|
||||
public Actor.Type getType() {
|
||||
return Actor.Type.USER;
|
||||
}
|
||||
|
||||
}
|
17
src/main/java/net/frozenorb/apiv3/actors/WebsiteActor.java
Normal file
17
src/main/java/net/frozenorb/apiv3/actors/WebsiteActor.java
Normal file
@ -0,0 +1,17 @@
|
||||
package net.frozenorb.apiv3.actors;
|
||||
|
||||
public final class WebsiteActor implements Actor {
|
||||
|
||||
public boolean isAuthorized() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return "Website";
|
||||
}
|
||||
|
||||
public Actor.Type getType() {
|
||||
return Actor.Type.WEBSITE;
|
||||
}
|
||||
|
||||
}
|
@ -1,33 +1,74 @@
|
||||
package net.frozenorb.apiv3.filters;
|
||||
|
||||
import net.frozenorb.apiv3.unsorted.Actor;
|
||||
import com.sun.xml.internal.messaging.saaj.util.Base64;
|
||||
import net.frozenorb.apiv3.APIv3;
|
||||
import net.frozenorb.apiv3.actors.*;
|
||||
import net.frozenorb.apiv3.models.Server;
|
||||
import net.frozenorb.apiv3.models.User;
|
||||
import spark.Filter;
|
||||
import spark.Request;
|
||||
import spark.Response;
|
||||
|
||||
import static spark.Spark.halt;
|
||||
|
||||
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() {
|
||||
String authHeader = req.headers("Authorization");
|
||||
String mhqAuthHeader = req.headers("MHQ-Authorization");
|
||||
|
||||
@Override
|
||||
public boolean isAuthorized() {
|
||||
return true;
|
||||
if (authHeader != null) {
|
||||
req.attribute("actor", processBasicAuthorization(authHeader));
|
||||
} else if (mhqAuthHeader != null) {
|
||||
req.attribute("actor", processMHQAuthorization(mhqAuthHeader));
|
||||
} else {
|
||||
req.attribute("actor", new UnknownActor());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "HCTeams";
|
||||
private Actor processBasicAuthorization(String authHeader) {
|
||||
String encodedHeader = authHeader.substring("Basic ".length());
|
||||
String[] credentials = Base64.base64Decode(encodedHeader).split(":");
|
||||
|
||||
if (credentials.length == 2) {
|
||||
User user = User.byLastUsername(credentials[0]);
|
||||
char[] password = credentials[1].toCharArray();
|
||||
|
||||
if (user != null && user.checkPassword(password)) {
|
||||
return new UserActor(user);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Actor.Type getType() {
|
||||
return Actor.Type.SERVER;
|
||||
halt(401);
|
||||
return null;
|
||||
}
|
||||
|
||||
});
|
||||
private Actor processMHQAuthorization(String authHeader) {
|
||||
String[] split = authHeader.split(" ");
|
||||
|
||||
if (split.length >= 2) {
|
||||
String type = split[0];
|
||||
|
||||
if (type.equals("Website") && split.length == 2) {
|
||||
String givenKey = split[1];
|
||||
String properKey = APIv3.getConfig().getProperty("auth.websiteApiKey");
|
||||
|
||||
if (givenKey.equals(properKey)) {
|
||||
return new WebsiteActor();
|
||||
}
|
||||
} else if (type.equals("Server") && split.length == 3) {
|
||||
Server server = Server.byId(split[1]);
|
||||
String givenKey = split[2];
|
||||
String properKey = server.getApiKey();
|
||||
|
||||
if (givenKey.equals(properKey)) {
|
||||
return new ServerActor(server);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
halt(401);
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
package net.frozenorb.apiv3.filters;
|
||||
|
||||
import net.frozenorb.apiv3.unsorted.Actor;
|
||||
import net.frozenorb.apiv3.actors.Actor;
|
||||
import net.frozenorb.apiv3.utils.ErrorUtils;
|
||||
import spark.Filter;
|
||||
import spark.Request;
|
||||
@ -10,7 +10,7 @@ import spark.Spark;
|
||||
public final class AuthorizationFilter implements Filter {
|
||||
|
||||
public void handle(Request req, Response res) {
|
||||
Actor actor = req.attribute("actor");
|
||||
Actor actor = req.attribute("actors");
|
||||
|
||||
if (!actor.isAuthorized()) {
|
||||
Spark.halt(ErrorUtils.error("Unauthorized access: Please authenticate as either a server, the website, or an authorized user.").toJson());
|
||||
|
@ -1,7 +1,7 @@
|
||||
package net.frozenorb.apiv3.models;
|
||||
|
||||
import lombok.Getter;
|
||||
import net.frozenorb.apiv3.unsorted.Actor;
|
||||
import net.frozenorb.apiv3.actors.Actor;
|
||||
import org.bson.Document;
|
||||
import org.bson.types.ObjectId;
|
||||
import org.mongodb.morphia.annotations.Entity;
|
||||
@ -27,7 +27,7 @@ public final class AuditLogEntry {
|
||||
this.performedAt = new Date();
|
||||
this.actorName = actor.getName();
|
||||
this.actionType = actionType;
|
||||
this.actionData = actionData;
|
||||
this.actionData = new Document(actionData);
|
||||
}
|
||||
|
||||
}
|
@ -40,7 +40,7 @@ public final class Grant {
|
||||
this.reason = reason;
|
||||
this.scopes = new HashSet<>(Collections2.transform(scopes, ServerGroup::getId));
|
||||
this.rank = rank.getId();
|
||||
this.expiresAt = expiresAt;
|
||||
this.expiresAt = (Date) expiresAt.clone();
|
||||
this.addedBy = addedBy.getId();
|
||||
this.addedAt = new Date();
|
||||
}
|
||||
@ -69,10 +69,6 @@ public final class Grant {
|
||||
return removedBy != null;
|
||||
}
|
||||
|
||||
public boolean appliesOn(Server server) {
|
||||
return isGlobal() || scopes.contains(server.getId());
|
||||
}
|
||||
|
||||
public boolean appliesOn(ServerGroup serverGroup) {
|
||||
return isGlobal() || scopes.contains(serverGroup.getId());
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ public final class Punishment {
|
||||
this.target = target.getId();
|
||||
this.reason = reason;
|
||||
this.type = type;
|
||||
this.expiresAt = expiresAt;
|
||||
this.expiresAt = (Date) expiresAt.clone();
|
||||
this.addedBy = addedBy.getId();
|
||||
this.addedAt = new Date();
|
||||
this.addedOn = addedOn.getId();
|
||||
|
@ -22,7 +22,7 @@ public final class Rank {
|
||||
}
|
||||
|
||||
public static List<Rank> values() {
|
||||
return APIv3.getDatastore().createQuery(Rank.class).asList();
|
||||
return APIv3.getDatastore().createQuery(Rank.class).order("weight").asList();
|
||||
}
|
||||
|
||||
public Rank() {} // For Morphia
|
||||
|
@ -14,7 +14,7 @@ public final class Server {
|
||||
@Getter @Id private String id;
|
||||
@Getter private String bungeeId;
|
||||
@Getter private String displayName;
|
||||
@Getter private String secret;
|
||||
@Getter private String apiKey;
|
||||
@Getter private String group;
|
||||
@Getter private String ip;
|
||||
@Getter @Setter private Date lastUpdate;
|
||||
@ -31,11 +31,11 @@ public final class Server {
|
||||
|
||||
public Server() {} // For Morphia
|
||||
|
||||
public Server(String id, String bungeeId, String displayName, String secret, ServerGroup group, String ip) {
|
||||
public Server(String id, String bungeeId, String displayName, String apiKey, ServerGroup group, String ip) {
|
||||
this.id = id;
|
||||
this.bungeeId = bungeeId;
|
||||
this.displayName = displayName;
|
||||
this.secret = secret;
|
||||
this.apiKey = apiKey;
|
||||
this.group = group.getId();
|
||||
this.ip = ip;
|
||||
this.lastUpdate = new Date();
|
||||
@ -43,8 +43,4 @@ public final class Server {
|
||||
this.players = new HashSet<>();
|
||||
}
|
||||
|
||||
public ServerGroup resolveGroup() {
|
||||
return ServerGroup.byId(group);
|
||||
}
|
||||
|
||||
}
|
@ -1,7 +1,9 @@
|
||||
package net.frozenorb.apiv3.models;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import lombok.Getter;
|
||||
import net.frozenorb.apiv3.APIv3;
|
||||
import net.frozenorb.apiv3.utils.PermissionUtils;
|
||||
import org.mongodb.morphia.annotations.Entity;
|
||||
import org.mongodb.morphia.annotations.Id;
|
||||
|
||||
@ -14,6 +16,7 @@ public final class ServerGroup {
|
||||
@Getter private String displayName;
|
||||
@Getter private Set<String> announcements;
|
||||
@Getter private Set<String> chatFilterList;
|
||||
@Getter private Map<String, List<String>> permissions;
|
||||
|
||||
public static ServerGroup byId(String id) {
|
||||
return APIv3.getDatastore().createQuery(ServerGroup.class).field("id").equalIgnoreCase(id).get();
|
||||
@ -30,41 +33,24 @@ public final class ServerGroup {
|
||||
this.displayName = displayName;
|
||||
this.announcements = new HashSet<>();
|
||||
this.chatFilterList = new HashSet<>();
|
||||
this.permissions = new HashMap<>();
|
||||
}
|
||||
|
||||
public void setAnnouncements(Set<String> announcements) {
|
||||
this.announcements = announcements;
|
||||
this.announcements = ImmutableSet.copyOf(announcements);
|
||||
APIv3.getDatastore().save(this);
|
||||
}
|
||||
|
||||
public void setChatFilterList(Set<String> chatFilterList) {
|
||||
this.chatFilterList = chatFilterList;
|
||||
this.chatFilterList = ImmutableSet.copyOf(chatFilterList);
|
||||
APIv3.getDatastore().save(this);
|
||||
}
|
||||
|
||||
// TODO: DO THIS
|
||||
public Map<String, Boolean> getPermissions(Rank rank) {
|
||||
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;
|
||||
return PermissionUtils.mergePermissions(
|
||||
PermissionUtils.getDefaultPermissions(userRank),
|
||||
PermissionUtils.mergeUpTo(permissions, userRank)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -18,7 +18,7 @@ import java.util.*;
|
||||
public final class User {
|
||||
|
||||
@Getter @Id private UUID id;
|
||||
@Getter private String lastName;
|
||||
@Getter private String lastUsername;
|
||||
@Getter @ExcludeFromReplies private Map<String, Date> aliases;
|
||||
@Getter @ExcludeFromReplies private String otpCode;
|
||||
@Getter @ExcludeFromReplies @Setter private String emailToken;
|
||||
@ -42,31 +42,20 @@ public final class User {
|
||||
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) {
|
||||
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").equalIgnoreCase(name).get();
|
||||
}
|
||||
|
||||
public static User byEmailToken(String name) {
|
||||
return APIv3.getDatastore().createQuery(User.class).field("emailToken").equal(name).get();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static User byLastUsername(String lastUsername) {
|
||||
return APIv3.getDatastore().createQuery(User.class).field("lastUsername").equal(lastUsername).get();
|
||||
}
|
||||
|
||||
public User() {} // For Morphia
|
||||
|
||||
public User(UUID id, String lastName) {
|
||||
public User(UUID id, String lastUsername) {
|
||||
this.id = id;
|
||||
this.lastName = lastName;
|
||||
this.lastUsername = lastUsername;
|
||||
this.aliases = new HashMap<>();
|
||||
this.otpCode = null;
|
||||
this.password = null;
|
||||
@ -76,18 +65,18 @@ public final class User {
|
||||
this.lastSeenAt = new Date();
|
||||
this.firstSeen = new Date();
|
||||
|
||||
aliases.put(lastName, new Date());
|
||||
}
|
||||
|
||||
public boolean hasPermissionAnywhere(String permission) {
|
||||
return hasPermissionScoped(permission, null);
|
||||
aliases.put(lastUsername, new Date());
|
||||
}
|
||||
|
||||
public boolean hasPermissionScoped(String permission, ServerGroup scope) {
|
||||
// TODO: BLAH FIX THIS IF WE DONT REMOVE THEN IDK WHAT TO SAY
|
||||
// Also this is 1 > 0 because 'return true;' means all usages of this
|
||||
// get marked as a warning until we change it.
|
||||
return 1 > 0;
|
||||
Map<String, Boolean> permissions = scope.calculatePermissions(getHighestRank(scope));
|
||||
return permissions.containsKey(permission) && permissions.get(permission);
|
||||
}
|
||||
|
||||
// TODO
|
||||
public boolean hasPermissionAnywhere(String permission) {
|
||||
Map<String, Boolean> permissions = /*scope.calculatePermissions(getHighestRank(scope));*/ ImmutableMap.of();
|
||||
return permissions.containsKey(permission) && permissions.get(permission);
|
||||
}
|
||||
|
||||
public List<Grant> getGrants() {
|
||||
@ -98,6 +87,17 @@ public final class User {
|
||||
return APIv3.getDatastore().createQuery(IPLogEntry.class).field("user").equal(id).asList();
|
||||
}
|
||||
|
||||
public IPLogEntry getIPLogEntry(String ip) {
|
||||
IPLogEntry existing = APIv3.getDatastore().createQuery(IPLogEntry.class).field("user").equal(id).field("ip").equal(ip).get();
|
||||
|
||||
if (existing == null) {
|
||||
existing = new IPLogEntry(this, ip);
|
||||
APIv3.getDatastore().save(existing);
|
||||
}
|
||||
|
||||
return existing;
|
||||
}
|
||||
|
||||
public List<Punishment> getPunishments() {
|
||||
return APIv3.getDatastore().createQuery(Punishment.class).field("target").equal(id).asList();
|
||||
}
|
||||
@ -121,6 +121,11 @@ public final class User {
|
||||
}
|
||||
}
|
||||
|
||||
public void seenOnServer(Server server) {
|
||||
this.lastSeenOn = server.getId();
|
||||
this.lastSeenAt = new Date();
|
||||
}
|
||||
|
||||
public void setPassword(char[] unencrypted) {
|
||||
this.password = BCrypt.hashpw(new String(unencrypted), BCrypt.gensalt());
|
||||
}
|
||||
@ -133,11 +138,7 @@ public final class User {
|
||||
Rank highest = null;
|
||||
|
||||
for (Grant grant : getGrants()) {
|
||||
if (!grant.isActive()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (serverGroup != null && !grant.appliesOn(serverGroup)) {
|
||||
if (!grant.isActive() || (serverGroup != null && !grant.appliesOn(serverGroup))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -155,7 +156,7 @@ public final class User {
|
||||
}
|
||||
}
|
||||
|
||||
public Rank getHighestRankAnywhere() {
|
||||
public Rank getHighestRank() {
|
||||
return getHighestRank(null);
|
||||
}
|
||||
|
||||
@ -184,7 +185,7 @@ public final class User {
|
||||
}
|
||||
|
||||
|
||||
ServerGroup actorGroup = server.resolveGroup();
|
||||
ServerGroup actorGroup = ServerGroup.byId(server.getGroup());
|
||||
Rank rank = getHighestRank(actorGroup);
|
||||
Map<String, Boolean> rankPermissions = actorGroup.calculatePermissions(rank);
|
||||
|
||||
|
@ -23,7 +23,7 @@ public final class UserMetaEntry {
|
||||
public UserMetaEntry(User user, ServerGroup serverGroup, Document data) {
|
||||
this.user = user.getId();
|
||||
this.serverGroup = serverGroup.getId();
|
||||
this.data = data;
|
||||
this.data = new Document(data);
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
|
@ -1,72 +0,0 @@
|
||||
package net.frozenorb.apiv3.routes;
|
||||
|
||||
import spark.Request;
|
||||
import spark.Response;
|
||||
import spark.Route;
|
||||
import spark.Spark;
|
||||
import spark.route.HttpMethod;
|
||||
import spark.route.SimpleRouteMatcher;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
|
||||
import static spark.Spark.halt;
|
||||
|
||||
public final class GETRoutes implements Route {
|
||||
|
||||
private List<Object> routes;
|
||||
private Field httpMethodField;
|
||||
private Field pathField;
|
||||
private Field targetField;
|
||||
|
||||
@SuppressWarnings("unchecked") // Casting List to List<Object>
|
||||
public GETRoutes() {
|
||||
try {
|
||||
Object spark = Spark.getInstance();
|
||||
Field routeMatcherField = spark.getClass().getDeclaredField("routeMatcher");
|
||||
routeMatcherField.setAccessible(true);
|
||||
SimpleRouteMatcher routeMatcher = (SimpleRouteMatcher) routeMatcherField.get(spark);
|
||||
|
||||
Field routesField = routeMatcher.getClass().getDeclaredField("routes");
|
||||
routesField.setAccessible(true);
|
||||
routes = (List<Object>) routesField.get(routeMatcher);
|
||||
|
||||
Class<?> routeEntryClass = Class.forName("spark.route.RouteEntry");
|
||||
|
||||
httpMethodField = routeEntryClass.getDeclaredField("httpMethod");
|
||||
httpMethodField.setAccessible(true);
|
||||
pathField = routeEntryClass.getDeclaredField("path");
|
||||
pathField.setAccessible(true);
|
||||
targetField = routeEntryClass.getDeclaredField("target");
|
||||
targetField.setAccessible(true);
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public Object handle(Request req, Response res) {
|
||||
try {
|
||||
String response = "";
|
||||
|
||||
for (Object route : routes) {
|
||||
HttpMethod httpMethod = (HttpMethod) httpMethodField.get(route);
|
||||
String path = (String) pathField.get(route);
|
||||
Object target = targetField.get(route);
|
||||
|
||||
if (httpMethod == HttpMethod.before || httpMethod == HttpMethod.after) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String append = httpMethod.name().toUpperCase() + " " + path + " (" + target + ")<br />";
|
||||
response += append;
|
||||
}
|
||||
|
||||
halt(response); // We use halt to avoid our content type filter (gson serialization is already avoided because we don't have the filter on this route)
|
||||
return null; // Return is required but will never be reached
|
||||
} catch (IllegalAccessException ex) { // If we use a generic Exception we'd catch the halt() call (it throws an exception)
|
||||
ex.printStackTrace();
|
||||
return ex;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -10,7 +10,7 @@ public final class GETAnnouncements implements Route {
|
||||
|
||||
public Object handle(Request req, Response res) {
|
||||
Server sender = req.attribute("server");
|
||||
ServerGroup senderGroup = sender.resolveGroup();
|
||||
ServerGroup senderGroup = ServerGroup.byId(sender.getGroup());
|
||||
|
||||
return senderGroup.getAnnouncements();
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ public final class GETChatFilterList implements Route {
|
||||
|
||||
public Object handle(Request req, Response res) {
|
||||
Server sender = req.attribute("server");
|
||||
ServerGroup senderGroup = sender.resolveGroup();
|
||||
ServerGroup senderGroup = ServerGroup.byId(sender.getGroup());
|
||||
|
||||
return senderGroup.getChatFilterList();
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ public final class DELETEGrant implements Route {
|
||||
if (grant == null) {
|
||||
return ErrorUtils.notFound("Grant", req.params("id"));
|
||||
} else if (!grant.isActive()) {
|
||||
return ErrorUtils.error("Cannot remove an inactive grant.");
|
||||
return ErrorUtils.invalidInput("Cannot remove an inactive grant.");
|
||||
}
|
||||
|
||||
User removedBy = User.byId(req.queryParams("removedBy"));
|
||||
@ -33,7 +33,7 @@ public final class DELETEGrant implements Route {
|
||||
String reason = req.queryParams("removalReason");
|
||||
|
||||
grant.delete(removedBy, reason);
|
||||
AuditLog.log(removedBy, req.attribute("actor"), "grant.remove", new Document("grantId", grant.getId()));
|
||||
AuditLog.log(removedBy, req.attribute("actors"), "grant.remove", new Document("grantId", grant.getId()));
|
||||
return grant;
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@ import spark.Route;
|
||||
public final class GETUserGrants implements Route {
|
||||
|
||||
public Object handle(Request req, Response res) {
|
||||
User target = User.byIdOrName(req.params("id"));
|
||||
User target = User.byId(req.params("id"));
|
||||
|
||||
if (target == null) {
|
||||
return ErrorUtils.notFound("User", req.params("id"));
|
||||
|
@ -18,7 +18,7 @@ import java.util.Set;
|
||||
public final class POSTUserGrant implements Route {
|
||||
|
||||
public Object handle(Request req, Response res) {
|
||||
User target = User.byIdOrName(req.params("id"));
|
||||
User target = User.byId(req.params("id"));
|
||||
|
||||
if (target == null) {
|
||||
return ErrorUtils.notFound("User", req.params("id"));
|
||||
@ -30,8 +30,17 @@ public final class POSTUserGrant implements Route {
|
||||
return ErrorUtils.invalidInput("A reason must be provided.");
|
||||
}
|
||||
|
||||
Set<ServerGroup> scopes = new HashSet<>(/*Arrays.asList(req.queryParams("scopes").split(","))*/);
|
||||
// TODO
|
||||
Set<ServerGroup> scopes = new HashSet<>();
|
||||
|
||||
for (String serverGroupId : req.queryParams("scopes").split(",")) {
|
||||
ServerGroup serverGroup = ServerGroup.byId(serverGroupId);
|
||||
|
||||
if (serverGroup == null) {
|
||||
return ErrorUtils.notFound("Server group", serverGroupId);
|
||||
}
|
||||
|
||||
scopes.add(serverGroup);
|
||||
}
|
||||
|
||||
Rank rank = Rank.byId(req.queryParams("rank"));
|
||||
|
||||
|
@ -9,7 +9,7 @@ import spark.Route;
|
||||
public final class GETUserIPLog implements Route {
|
||||
|
||||
public Object handle(Request req, Response res) {
|
||||
User target = User.byIdOrName(req.params("id"));
|
||||
User target = User.byId(req.params("id"));
|
||||
|
||||
if (target == null) {
|
||||
return ErrorUtils.notFound("User", req.params("id"));
|
||||
|
@ -18,7 +18,7 @@ public final class DELETEPunishment implements Route {
|
||||
if (punishment == null) {
|
||||
return ErrorUtils.notFound("Punishment", req.params("id"));
|
||||
} else if (!punishment.isActive()) {
|
||||
return ErrorUtils.error("Cannot remove an inactive punishment.");
|
||||
return ErrorUtils.invalidInput("Cannot remove an inactive punishment.");
|
||||
}
|
||||
|
||||
User removedBy = User.byId(req.queryParams("removedBy"));
|
||||
@ -33,7 +33,7 @@ public final class DELETEPunishment implements Route {
|
||||
String reason = req.queryParams("removalReason");
|
||||
|
||||
punishment.delete(removedBy, reason);
|
||||
AuditLog.log(removedBy, req.attribute("actor"), "punishment.remove", new Document("punishmentId", punishment.getId()));
|
||||
AuditLog.log(removedBy, req.attribute("actors"), "punishment.remove", new Document("punishmentId", punishment.getId()));
|
||||
return punishment;
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@ import java.util.Date;
|
||||
public final class POSTUserPunish implements Route {
|
||||
|
||||
public Object handle(Request req, Response res) {
|
||||
User target = User.byIdOrName(req.params("id"));
|
||||
User target = User.byId(req.params("id"));
|
||||
|
||||
if (target == null) {
|
||||
return ErrorUtils.notFound("User", req.params("id"));
|
||||
|
@ -1,10 +1,10 @@
|
||||
package net.frozenorb.apiv3.routes;
|
||||
package net.frozenorb.apiv3.routes.servers;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import net.frozenorb.apiv3.APIv3;
|
||||
import net.frozenorb.apiv3.actors.Actor;
|
||||
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;
|
||||
@ -13,10 +13,11 @@ import spark.Route;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public final class POSTHeartbeat implements Route {
|
||||
public final class POSTServerHeartbeat implements Route {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object handle(Request req, Response res) {
|
||||
Actor actor = req.attribute("actor");
|
||||
Actor actor = req.attribute("actors");
|
||||
|
||||
if (actor.getType() != Actor.Type.SERVER) {
|
||||
return ErrorUtils.error("Heartbeats can only be performed when requested by a server.");
|
||||
@ -27,18 +28,19 @@ public final class POSTHeartbeat implements Route {
|
||||
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) {
|
||||
// Will be saved by the save command a few lines down.
|
||||
user = new User(UUID.fromString(playerJson.getString("uuid")), username);
|
||||
APIv3.getDatastore().save(user);
|
||||
}
|
||||
|
||||
user.seenOnServer(actorServer);
|
||||
APIv3.getDatastore().save(user);
|
||||
|
||||
onlinePlayers.add(user.getId());
|
||||
playersResponse.put(user.getId().toString(), user.getLoginInfo(actorServer));
|
||||
}
|
||||
@ -62,6 +64,7 @@ public final class POSTHeartbeat implements Route {
|
||||
actorServer.setPlayers(onlinePlayers);
|
||||
actorServer.setLastTps(reqJson.getDouble("lastTps"));
|
||||
actorServer.setLastUpdate(new Date());
|
||||
APIv3.getDatastore().save(actorServer);
|
||||
|
||||
return ImmutableMap.of(
|
||||
"players", playersResponse
|
@ -11,7 +11,7 @@ import spark.Route;
|
||||
public final class DELETEUserMeta implements Route {
|
||||
|
||||
public Object handle(Request req, Response res) {
|
||||
User user = User.byIdOrName(req.params("id"));
|
||||
User user = User.byId(req.params("id"));
|
||||
|
||||
if (user == null) {
|
||||
return ErrorUtils.notFound("User", req.params("id"));
|
||||
|
@ -8,7 +8,7 @@ import spark.Route;
|
||||
public final class GETUser implements Route {
|
||||
|
||||
public Object handle(Request req, Response res) {
|
||||
return User.byIdOrName(req.params("id"));
|
||||
return User.byId(req.params("id"));
|
||||
}
|
||||
|
||||
}
|
@ -10,7 +10,7 @@ import spark.Route;
|
||||
public final class GETUserDetails implements Route {
|
||||
|
||||
public Object handle(Request req, Response res) {
|
||||
User user = User.byIdOrName(req.params("id"));
|
||||
User user = User.byId(req.params("id"));
|
||||
|
||||
if (user == null) {
|
||||
return ErrorUtils.notFound("User", req.params("id"));
|
||||
|
@ -11,7 +11,7 @@ import spark.Route;
|
||||
public final class GETUserMeta implements Route {
|
||||
|
||||
public Object handle(Request req, Response res) {
|
||||
User user = User.byIdOrName(req.params("id"));
|
||||
User user = User.byId(req.params("id"));
|
||||
|
||||
if (user == null) {
|
||||
return ErrorUtils.notFound("User", req.params("id"));
|
||||
|
@ -1,4 +1,4 @@
|
||||
package net.frozenorb.apiv3.routes;
|
||||
package net.frozenorb.apiv3.routes.users;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import net.frozenorb.apiv3.APIv3;
|
||||
@ -12,9 +12,9 @@ import spark.Route;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public final class POSTConfirmRegister implements Route {
|
||||
public final class POSTUserConfirmRegister implements Route {
|
||||
|
||||
private List<String> commonPasswords = ImmutableList.copyOf(("123456 password 12345678 qwerty 123456789 12345 1234 111111 1234567 dragon " +
|
||||
private final List<String> commonPasswords = ImmutableList.copyOf(("123456 password 12345678 qwerty 123456789 12345 1234 111111 1234567 dragon " +
|
||||
"123123 baseball abc123 football monkey letmein 696969 shadow master 666666 qwertyuiop 123321 mustang 1234567890 " +
|
||||
"michael 654321 pussy superman 1qaz2wsx 7777777 fuckyou 121212 000000 qazwsx 123qwe killer trustno1 jordan jennifer " +
|
||||
"zxcvbnm asdfgh hunter buster soccer harley batman andrew tigger sunshine iloveyou fuckme 2000 charlie robert thomas " +
|
@ -1,9 +1,9 @@
|
||||
package net.frozenorb.apiv3.routes.users;
|
||||
|
||||
import net.frozenorb.apiv3.APIv3;
|
||||
import net.frozenorb.apiv3.actors.Actor;
|
||||
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;
|
||||
@ -16,20 +16,21 @@ 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");
|
||||
String userIp = req.queryParams("userIp");
|
||||
Actor actor = req.attribute("actors");
|
||||
|
||||
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());
|
||||
|
||||
user.getIPLogEntry(userIp).used();
|
||||
return user.getLoginInfo(actorServer);
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@ import java.util.Map;
|
||||
public final class POSTUserNotify implements Route {
|
||||
|
||||
public Object handle(Request req, Response res) {
|
||||
User user = User.byIdOrName(req.params("id"));
|
||||
User user = User.byId(req.params("id"));
|
||||
|
||||
if (user == null) {
|
||||
return ErrorUtils.notFound("User", req.params("id"));
|
||||
@ -48,6 +48,7 @@ public final class POSTUserNotify implements Route {
|
||||
notification.sendAsEmail(user.getEmail());
|
||||
return new Document("success", true);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
return ErrorUtils.error("Failed to send notification");
|
||||
}
|
||||
}
|
||||
|
@ -20,18 +20,18 @@ import java.util.regex.Pattern;
|
||||
|
||||
public final class POSTUserRegister implements Route {
|
||||
|
||||
public static final Pattern VALID_EMAIL_ADDRESS_REGEX =
|
||||
private static final Pattern VALID_EMAIL_ADDRESS_REGEX =
|
||||
Pattern.compile("^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,6}$", Pattern.CASE_INSENSITIVE);
|
||||
|
||||
public Object handle(Request req, Response res) {
|
||||
User user = User.byIdOrName(req.params("id"));
|
||||
User user = User.byId(req.params("id"));
|
||||
|
||||
if (user == null) {
|
||||
return ErrorUtils.notFound("User", req.params("id"));
|
||||
}
|
||||
|
||||
if (user.getEmail() != null) {
|
||||
return ErrorUtils.error("User provided already has email set.");
|
||||
return ErrorUtils.invalidInput("User provided already has email set.");
|
||||
}
|
||||
|
||||
String email = req.queryParams("email");
|
||||
@ -50,7 +50,7 @@ public final class POSTUserRegister implements Route {
|
||||
APIv3.getDatastore().save(user);
|
||||
|
||||
Map<String, Object> replacements = ImmutableMap.of(
|
||||
"username", user.getLastName(),
|
||||
"username", user.getLastUsername(),
|
||||
"email", user.getEmail(),
|
||||
"emailToken", user.getEmailToken()
|
||||
);
|
||||
@ -61,6 +61,7 @@ public final class POSTUserRegister implements Route {
|
||||
notification.sendAsEmail(user.getEmail());
|
||||
return new Document("success", true).append("message", "User registered");
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
return ErrorUtils.error("Failed to send confirmation email. Please contact a MineHQ staff member.");
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ import spark.Route;
|
||||
public final class PUTUserMeta implements Route {
|
||||
|
||||
public Object handle(Request req, Response res) {
|
||||
User user = User.byIdOrName(req.params("id"));
|
||||
User user = User.byId(req.params("id"));
|
||||
|
||||
if (user == null) {
|
||||
return ErrorUtils.notFound("User", req.params("id"));
|
||||
|
@ -2,6 +2,7 @@ package net.frozenorb.apiv3.unsorted;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
import net.frozenorb.apiv3.APIv3;
|
||||
import net.frozenorb.apiv3.actors.Actor;
|
||||
import net.frozenorb.apiv3.models.AuditLogEntry;
|
||||
import net.frozenorb.apiv3.models.User;
|
||||
import org.bson.Document;
|
||||
|
@ -0,0 +1,20 @@
|
||||
package net.frozenorb.apiv3.unsorted;
|
||||
|
||||
import net.frozenorb.apiv3.utils.ErrorUtils;
|
||||
import org.bson.types.ObjectId;
|
||||
import spark.ExceptionHandler;
|
||||
import spark.Request;
|
||||
import spark.Response;
|
||||
|
||||
public final class LoggingExceptionHandler implements ExceptionHandler {
|
||||
|
||||
public void handle(Exception ex, Request req, Response res) {
|
||||
String code = new ObjectId().toHexString();
|
||||
|
||||
System.out.println(code + ":");
|
||||
ex.printStackTrace();
|
||||
|
||||
res.body(ErrorUtils.error("An unknown error has occurred. Please contact a developer with the code \"" + code + "\".").toJson());
|
||||
}
|
||||
|
||||
}
|
@ -14,10 +14,10 @@ import java.util.Map;
|
||||
|
||||
public final class Notification {
|
||||
|
||||
private static MandrillMessagesRequest messagesRequest = MandrillUtils.createMessagesRequest();
|
||||
private static final MandrillMessagesRequest messagesRequest = MandrillUtils.createMessagesRequest();
|
||||
|
||||
private String subject;
|
||||
private String body;
|
||||
private final String subject;
|
||||
private final String body;
|
||||
|
||||
public Notification(NotificationTemplate template, Map<String, Object> subjectReplacements, Map<String, Object> bodyReplacements) {
|
||||
this.subject = template.fillSubject(subjectReplacements);
|
||||
|
@ -1,22 +1,58 @@
|
||||
package net.frozenorb.apiv3.utils;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import net.frozenorb.apiv3.models.Rank;
|
||||
import net.frozenorb.apiv3.models.ServerGroup;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@UtilityClass
|
||||
public class PermissionUtils {
|
||||
|
||||
public static void mergePermissions(ServerGroup serverGroup, Rank rank, Map<String, Boolean> current) {
|
||||
Map<String, Boolean> groupPermissions = serverGroup.getPermissions(rank);
|
||||
public static Map<String, Boolean> mergePermissions(Map<String, Boolean> current, Map<String, Boolean> merge) {
|
||||
Map<String, Boolean> result = new HashMap<>(current);
|
||||
|
||||
groupPermissions.forEach((permissionNode, grant) -> {
|
||||
if (!current.containsKey(permissionNode) || !current.get(permissionNode)) {
|
||||
current.put(permissionNode, grant);
|
||||
result.putAll(merge);
|
||||
|
||||
return result;
|
||||
}
|
||||
});
|
||||
|
||||
public static Map<String, Boolean> mergeUpTo(Map<String, List<String>> collection, Rank upTo) {
|
||||
Map<String, Boolean> result = new HashMap<>();
|
||||
|
||||
for (Rank rank : Rank.values()) {
|
||||
Map<String, Boolean> rankPermissions = convertToMap(collection.get(rank.getId()));
|
||||
mergePermissions(result, rankPermissions);
|
||||
|
||||
if (upTo.getId().equals(rank.getId())) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// TODO: Fix this
|
||||
public static Map<String, Boolean> getDefaultPermissions(Rank rank) {
|
||||
return ImmutableMap.of();
|
||||
}
|
||||
|
||||
private static Map<String, Boolean> convertToMap(List<String> unconvered) {
|
||||
Map<String, Boolean> result = new HashMap<>();
|
||||
|
||||
for (String permission : unconvered) {
|
||||
boolean negate = permission.startsWith("-");
|
||||
|
||||
if (negate) {
|
||||
result.put(permission.substring(1), false);
|
||||
} else {
|
||||
result.put(permission, true);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
@ -2,14 +2,11 @@ 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";
|
||||
@ -30,10 +27,6 @@ public class TimeUtils {
|
||||
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));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user