Require totp authorization on some actions

This commit is contained in:
Colin McDonald 2016-06-27 21:55:35 -04:00
parent ac0865fde7
commit c742b6d01f
6 changed files with 85 additions and 4 deletions

View File

@ -250,8 +250,8 @@ public final class APIv3 extends AbstractVerticle {
// TODO: The commented out routes // TODO: The commented out routes
http.get("/accessTokens/:id").handler(new GETAccessTokensId()); http.get("/accessTokens/:id").blockingHandler(new GETAccessTokensId());
http.get("/accessTokens").handler(new GETAccessTokens()); http.get("/accessTokens").blockingHandler(new GETAccessTokens());
http.post("/accessTokens").blockingHandler(new POSTAccessTokens(), false); http.post("/accessTokens").blockingHandler(new POSTAccessTokens(), false);
//http.put("/accessTokens/:id").blockingHandler(new PUTAccessTokensId(), false); //http.put("/accessTokens/:id").blockingHandler(new PUTAccessTokensId(), false);
http.delete("/accessTokens/:id").blockingHandler(new DELETEAccessTokensId(), false); http.delete("/accessTokens/:id").blockingHandler(new DELETEAccessTokensId(), false);

View File

@ -31,6 +31,7 @@ public final class Rank {
@Getter private String gameColor; @Getter private String gameColor;
@Getter private String websiteColor; @Getter private String websiteColor;
@Getter private boolean staffRank; @Getter private boolean staffRank;
@Getter private boolean higherStaffRank;
public static List<Rank> findAll() { public static List<Rank> findAll() {
return ImmutableList.copyOf(rankCache); return ImmutableList.copyOf(rankCache);
@ -64,7 +65,7 @@ public final class Rank {
private Rank() {} // For Jackson private Rank() {} // For Jackson
public Rank(String id, String inheritsFromId, int weight, String displayName, String gameColor, String websiteColor, boolean staffRank) { public Rank(String id, String inheritsFromId, int weight, String displayName, String gameColor, String websiteColor, boolean staffRank, boolean higherStaffRank) {
this.id = id; this.id = id;
this.inheritsFromId = inheritsFromId; this.inheritsFromId = inheritsFromId;
this.weight = weight; this.weight = weight;
@ -72,6 +73,7 @@ public final class Rank {
this.gameColor = gameColor; this.gameColor = gameColor;
this.websiteColor = websiteColor; this.websiteColor = websiteColor;
this.staffRank = staffRank; this.staffRank = staffRank;
this.higherStaffRank = higherStaffRank;
} }
public void insert(SingleResultCallback<Void> callback) { public void insert(SingleResultCallback<Void> callback) {

View File

@ -4,11 +4,33 @@ import io.vertx.core.Handler;
import io.vertx.ext.web.RoutingContext; import io.vertx.ext.web.RoutingContext;
import net.frozenorb.apiv3.APIv3; import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.model.AccessToken; import net.frozenorb.apiv3.model.AccessToken;
import net.frozenorb.apiv3.model.User;
import net.frozenorb.apiv3.unsorted.BlockingCallback;
import net.frozenorb.apiv3.unsorted.TotpAuthorizationResult;
import net.frozenorb.apiv3.util.ErrorUtils; import net.frozenorb.apiv3.util.ErrorUtils;
public final class GETAccessTokens implements Handler<RoutingContext> { public final class GETAccessTokens implements Handler<RoutingContext> {
public void handle(RoutingContext ctx) { public void handle(RoutingContext ctx) {
BlockingCallback<User> userCallback = new BlockingCallback<>();
User.findById(ctx.request().getParam("user"), userCallback);
User user = userCallback.get();
if (user == null) {
ErrorUtils.respondNotFound(ctx, "User", ctx.request().getParam("user"));
return;
}
int code = Integer.parseInt(ctx.request().getParam("totpCode"));
BlockingCallback<TotpAuthorizationResult> totpAuthorizationCallback = new BlockingCallback<>();
user.checkTotpAuthorization(code, null, totpAuthorizationCallback);
TotpAuthorizationResult totpAuthorizationResult = totpAuthorizationCallback.get();
if (!totpAuthorizationResult.isAuthorized()) {
ErrorUtils.respondInvalidInput(ctx, "Totp authorization failed: " + totpAuthorizationResult.name());
return;
}
AccessToken.findAll((accessTokens, error) -> { AccessToken.findAll((accessTokens, error) -> {
if (error != null) { if (error != null) {
ErrorUtils.respondInternalError(ctx, error); ErrorUtils.respondInternalError(ctx, error);

View File

@ -4,11 +4,33 @@ import io.vertx.core.Handler;
import io.vertx.ext.web.RoutingContext; import io.vertx.ext.web.RoutingContext;
import net.frozenorb.apiv3.APIv3; import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.model.AccessToken; import net.frozenorb.apiv3.model.AccessToken;
import net.frozenorb.apiv3.model.User;
import net.frozenorb.apiv3.unsorted.BlockingCallback;
import net.frozenorb.apiv3.unsorted.TotpAuthorizationResult;
import net.frozenorb.apiv3.util.ErrorUtils; import net.frozenorb.apiv3.util.ErrorUtils;
public final class GETAccessTokensId implements Handler<RoutingContext> { public final class GETAccessTokensId implements Handler<RoutingContext> {
public void handle(RoutingContext ctx) { public void handle(RoutingContext ctx) {
BlockingCallback<User> userCallback = new BlockingCallback<>();
User.findById(ctx.request().getParam("user"), userCallback);
User user = userCallback.get();
if (user == null) {
ErrorUtils.respondNotFound(ctx, "User", ctx.request().getParam("user"));
return;
}
int code = Integer.parseInt(ctx.request().getParam("totpCode"));
BlockingCallback<TotpAuthorizationResult> totpAuthorizationCallback = new BlockingCallback<>();
user.checkTotpAuthorization(code, null, totpAuthorizationCallback);
TotpAuthorizationResult totpAuthorizationResult = totpAuthorizationCallback.get();
if (!totpAuthorizationResult.isAuthorized()) {
ErrorUtils.respondInvalidInput(ctx, "Totp authorization failed: " + totpAuthorizationResult.name());
return;
}
AccessToken.findById(ctx.request().getParam("id"), (accessToken, error) -> { AccessToken.findById(ctx.request().getParam("id"), (accessToken, error) -> {
if (error != null) { if (error != null) {
ErrorUtils.respondInternalError(ctx, error); ErrorUtils.respondInternalError(ctx, error);

View File

@ -9,7 +9,10 @@ import net.frozenorb.apiv3.actor.ActorType;
import net.frozenorb.apiv3.auditLog.AuditLog; import net.frozenorb.apiv3.auditLog.AuditLog;
import net.frozenorb.apiv3.auditLog.AuditLogActionType; import net.frozenorb.apiv3.auditLog.AuditLogActionType;
import net.frozenorb.apiv3.model.AccessToken; import net.frozenorb.apiv3.model.AccessToken;
import net.frozenorb.apiv3.model.User;
import net.frozenorb.apiv3.unsorted.BlockingCallback; import net.frozenorb.apiv3.unsorted.BlockingCallback;
import net.frozenorb.apiv3.unsorted.RequiresTotpResult;
import net.frozenorb.apiv3.unsorted.TotpAuthorizationResult;
import net.frozenorb.apiv3.util.ErrorUtils; import net.frozenorb.apiv3.util.ErrorUtils;
import java.util.List; import java.util.List;
@ -23,6 +26,25 @@ public final class POSTAccessTokens implements Handler<RoutingContext> {
ActorType actorType = ActorType.valueOf(requestBody.getString("actorType").toUpperCase()); ActorType actorType = ActorType.valueOf(requestBody.getString("actorType").toUpperCase());
List<String> lockedIps = (List<String>) requestBody.getJsonArray("lockedIps").getList(); List<String> lockedIps = (List<String>) requestBody.getJsonArray("lockedIps").getList();
BlockingCallback<User> userCallback = new BlockingCallback<>();
User.findById(requestBody.getString("user"), userCallback);
User user = userCallback.get();
if (user == null) {
ErrorUtils.respondNotFound(ctx, "User", requestBody.getString("user"));
return;
}
int code = requestBody.getInteger("totpCode");
BlockingCallback<TotpAuthorizationResult> totpAuthorizationCallback = new BlockingCallback<>();
user.checkTotpAuthorization(code, null, totpAuthorizationCallback);
TotpAuthorizationResult totpAuthorizationResult = totpAuthorizationCallback.get();
if (!totpAuthorizationResult.isAuthorized()) {
ErrorUtils.respondInvalidInput(ctx, "Totp authorization failed: " + totpAuthorizationResult.name());
return;
}
AccessToken accessToken = new AccessToken(actorName, actorType, lockedIps); AccessToken accessToken = new AccessToken(actorName, actorType, lockedIps);
BlockingCallback<Void> callback = new BlockingCallback<>(); BlockingCallback<Void> callback = new BlockingCallback<>();
accessToken.insert(callback); accessToken.insert(callback);

View File

@ -12,6 +12,7 @@ import net.frozenorb.apiv3.model.Rank;
import net.frozenorb.apiv3.model.ServerGroup; import net.frozenorb.apiv3.model.ServerGroup;
import net.frozenorb.apiv3.model.User; import net.frozenorb.apiv3.model.User;
import net.frozenorb.apiv3.unsorted.BlockingCallback; import net.frozenorb.apiv3.unsorted.BlockingCallback;
import net.frozenorb.apiv3.unsorted.TotpAuthorizationResult;
import net.frozenorb.apiv3.util.ErrorUtils; import net.frozenorb.apiv3.util.ErrorUtils;
import java.time.Instant; import java.time.Instant;
@ -73,11 +74,23 @@ public final class POSTGrants implements Handler<RoutingContext> {
return; return;
} }
// We purposely don't do a null check, grants don't have to have a source. // We purposely don't fail on a null check, grants don't have to have a source.
BlockingCallback<User> addedByCallback = new BlockingCallback<>(); BlockingCallback<User> addedByCallback = new BlockingCallback<>();
User.findById(requestBody.getString("addedBt"), addedByCallback); User.findById(requestBody.getString("addedBt"), addedByCallback);
User addedBy = addedByCallback.get(); User addedBy = addedByCallback.get();
if (addedBy != null && rank.isHigherStaffRank()) {
int code = requestBody.getInteger("totpCode");
BlockingCallback<TotpAuthorizationResult> totpAuthorizationCallback = new BlockingCallback<>();
addedBy.checkTotpAuthorization(code, null, totpAuthorizationCallback);
TotpAuthorizationResult totpAuthorizationResult = totpAuthorizationCallback.get();
if (!totpAuthorizationResult.isAuthorized()) {
ErrorUtils.respondInvalidInput(ctx, "Totp authorization failed: " + totpAuthorizationResult.name());
return;
}
}
Grant grant = new Grant(target, reason, scopes, rank, expiresAt, addedBy); Grant grant = new Grant(target, reason, scopes, rank, expiresAt, addedBy);
BlockingCallback<Void> callback = new BlockingCallback<>(); BlockingCallback<Void> callback = new BlockingCallback<>();
grant.insert(callback); grant.insert(callback);