package io.vertx.ext.auth.jdbc.impl;

import java.util.Collections;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

import io.vertx.core.AsyncResult;
import io.vertx.core.Future;
import io.vertx.core.Handler;
import io.vertx.core.json.JsonArray;
import io.vertx.ext.auth.authorization.Authorization;
import io.vertx.ext.auth.authorization.PermissionBasedAuthorization;
import io.vertx.ext.auth.authorization.RoleBasedAuthorization;
import io.vertx.ext.auth.User;
import io.vertx.ext.auth.jdbc.JDBCAuthorization;
import io.vertx.ext.auth.jdbc.JDBCAuthorizationOptions;
import io.vertx.ext.jdbc.JDBCClient;
import io.vertx.ext.sql.ResultSet;
import io.vertx.ext.sql.SQLConnection;

public class JDBCAuthorizationImpl implements JDBCAuthorization {

  
The default key representing the username in the principal
/** * The default key representing the username in the principal */
private final static String DEFAULT_USERNAME_KEY = "username"; private String providerId; private JDBCAuthorizationOptions options; private JDBCClient client; private String usernameKey; public JDBCAuthorizationImpl(String providerId, JDBCClient client, JDBCAuthorizationOptions options) { this.providerId = Objects.requireNonNull(providerId); this.client = Objects.requireNonNull(client); this.options = Objects.requireNonNull(options); this.usernameKey = DEFAULT_USERNAME_KEY; } @Override public String getId() { return providerId; } private void getRoles(SQLConnection sqlConnection, JsonArray params, Handler<AsyncResult<Set<Authorization>>> resultHandler) { if (options.getRolesQuery() != null) { sqlConnection.queryWithParams(options.getRolesQuery(), params, queryResponse -> { if (queryResponse.succeeded()) { Set<Authorization> authorizations = new HashSet<>(); ResultSet resultSet = queryResponse.result(); for (JsonArray result : resultSet.getResults()) { String role = result.getString(0); authorizations.add(RoleBasedAuthorization.create(role)); } resultHandler.handle(Future.succeededFuture(authorizations)); } else { resultHandler.handle(Future.failedFuture(queryResponse.cause())); } }); } else { resultHandler.handle(Future.succeededFuture(Collections.emptySet())); } } private void getPermissions(SQLConnection sqlConnection, JsonArray params, Handler<AsyncResult<Set<Authorization>>> resultHandler) { if (options.getPermissionsQuery() != null) { sqlConnection.queryWithParams(options.getPermissionsQuery(), params, queryResponse -> { if (queryResponse.succeeded()) { Set<Authorization> authorizations = new HashSet<>(); ResultSet resultSet = queryResponse.result(); for (JsonArray result : resultSet.getResults()) { String permission = result.getString(0); authorizations.add(PermissionBasedAuthorization.create(permission)); } resultHandler.handle(Future.succeededFuture(authorizations)); } else { resultHandler.handle(Future.failedFuture(queryResponse.cause())); } }); } else { resultHandler.handle(Future.succeededFuture(Collections.emptySet())); } } @Override public void getAuthorizations(User user, Handler<AsyncResult<Void>> resultHandler) { client.getConnection(connectionResponse -> { if (connectionResponse.succeeded()) { String username = user.principal().getString(usernameKey); if (username != null) { JsonArray params = new JsonArray().add(username); SQLConnection connection = connectionResponse.result(); getRoles(connection, params, roleResponse -> { if (roleResponse.succeeded()) { Set<Authorization> authorizations = new HashSet<>(roleResponse.result()); getPermissions(connection, params, permissionResponse -> { if (permissionResponse.succeeded()) { authorizations.addAll(permissionResponse.result()); user.authorizations().add(getId(), authorizations); resultHandler.handle(Future.succeededFuture()); } else { resultHandler.handle(Future.failedFuture(permissionResponse.cause())); } connection.close(); }); } else { resultHandler.handle(Future.failedFuture(roleResponse.cause())); connection.close(); } }); } else { resultHandler.handle(Future.failedFuture("Couldn't get the username")); connectionResponse.result().close(); } } else { resultHandler.handle(Future.failedFuture(connectionResponse.cause())); } }); } }