Require totp authorization on some actions
This commit is contained in:
parent
ac0865fde7
commit
c742b6d01f
@ -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);
|
||||||
|
@ -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) {
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user