package io.vertx.ext.web.handler.impl;
import io.vertx.core.AsyncResult;
import io.vertx.core.Future;
import io.vertx.core.Handler;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.RoutingContext;
import io.vertx.ext.web.handler.AuthHandler;
import io.vertx.ext.web.handler.ChainAuthHandler;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public class ChainAuthHandlerImpl extends AuthHandlerImpl implements ChainAuthHandler {
private final List<AuthHandler> handlers = new ArrayList<>();
public ChainAuthHandlerImpl() {
super(null);
}
@Override
public ChainAuthHandler append(AuthHandler other) {
handlers.add(other);
return this;
}
@Override
public boolean remove(AuthHandler other) {
return handlers.remove(other);
}
@Override
public void clear() {
handlers.clear();
}
@Override
public AuthHandler addAuthority(String authority) {
for (AuthHandler h : handlers) {
h.addAuthority(authority);
}
return this;
}
@Override
public AuthHandler addAuthorities(Set<String> authorities) {
for (AuthHandler h : handlers) {
h.addAuthorities(authorities);
}
return this;
}
@Override
public void parseCredentials(RoutingContext context, Handler<AsyncResult<JsonObject>> handler) {
iterate(0, context, null, handler);
}
private void iterate(final int idx, final RoutingContext ctx, HttpStatusException lastException, Handler<AsyncResult<JsonObject>> handler) {
if (idx >= handlers.size()) {
handler.handle(Future.failedFuture(lastException));
return;
}
final AuthHandler authHandler = handlers.get(idx);
authHandler.parseCredentials(ctx, res -> {
if (res.failed()) {
if (res.cause() instanceof HttpStatusException) {
final HttpStatusException exception = (HttpStatusException) res.cause();
switch (exception.getStatusCode()) {
case 302:
case 400:
case 401:
case 403:
iterate(idx + 1, ctx, exception, handler);
return;
}
}
handler.handle(Future.failedFuture(res.cause()));
return;
}
if (authHandler instanceof AuthHandlerImpl) {
ctx.put(AuthHandlerImpl.AUTH_PROVIDER_CONTEXT_KEY, ((AuthHandlerImpl) authHandler).authProvider);
}
handler.handle(Future.succeededFuture(res.result()));
});
}
}