/*
* This file is part of ReadonlyREST.
*
* ReadonlyREST is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ReadonlyREST is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ReadonlyREST. If not, see http://www.gnu.org/licenses/
*/
package org.elasticsearch.plugin.readonlyrest.acl.definitions.groupsproviders;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Sets;
import com.jayway.jsonpath.JsonPath;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.plugin.readonlyrest.ESContext;
import org.elasticsearch.plugin.readonlyrest.acl.domain.LoggedUser;
import org.elasticsearch.plugin.readonlyrest.httpclient.HttpClient;
import org.elasticsearch.plugin.readonlyrest.httpclient.HttpRequest;
import org.elasticsearch.plugin.readonlyrest.httpclient.HttpResponse;
import org.elasticsearch.plugin.readonlyrest.settings.definitions.UserGroupsProviderSettings;
import java.net.URI;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
public class GroupsProviderServiceHttpClient implements GroupsProviderServiceClient {
private final Logger logger;
private final HttpClient client;
private final String name;
private final URI endpoint;
private final String authTokenName;
private final UserGroupsProviderSettings.TokenPassingMethod passingMethod;
private final String responseGroupsJsonPath;
public GroupsProviderServiceHttpClient(String name,
HttpClient client,
URI endpoint,
String authTokenName,
UserGroupsProviderSettings.TokenPassingMethod passingMethod,
String responseGroupsJsonPath,
ESContext context) {
this.logger = context.logger(getClass());
this.name = name;
this.endpoint = endpoint;
this.authTokenName = authTokenName;
this.passingMethod = passingMethod;
this.responseGroupsJsonPath = responseGroupsJsonPath;
this.client = client;
}
@Override
public CompletableFuture<Set<String>> fetchGroupsFor(LoggedUser user) {
return client.send(HttpRequest.get(endpoint, createParams(user), createHeaders(user)))
.thenApply(groupsFromResponse());
}
private Map<String, String> createParams(LoggedUser user) {
return passingMethod == UserGroupsProviderSettings.TokenPassingMethod.QUERY
? ImmutableMap.of(authTokenName, user.getId())
: ImmutableMap.of();
}
private Map<String, String> createHeaders(LoggedUser user) {
return passingMethod == UserGroupsProviderSettings.TokenPassingMethod.HEADER
? ImmutableMap.of(authTokenName, user.getId())
: ImmutableMap.of();
}
private Function<HttpResponse, Set<String>> groupsFromResponse() {
return response -> {
if (response.getStatusCode() == 200) {
try {
List<String> groups = JsonPath.read(response.getContent().get(), responseGroupsJsonPath);
logger.debug("Groups returned by groups provider '" + name + "': " + Joiner.on(",").join(groups));
return Sets.newHashSet(groups);
} catch (Exception e) {
logger.error("Group based authorization response exception", e);
return Sets.newHashSet();
}
}
return Sets.newHashSet();
};
}
}