com.couchbase.client.java.manager.user.AsyncUserManager Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of java-client Show documentation
Show all versions of java-client Show documentation
The official Couchbase Java SDK
/*
* Copyright 2019 Couchbase, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.couchbase.client.java.manager.user;
import com.couchbase.client.core.Core;
import com.couchbase.client.core.cnc.TracingIdentifiers;
import com.couchbase.client.core.deps.com.fasterxml.jackson.core.type.TypeReference;
import com.couchbase.client.core.endpoint.http.CoreHttpClient;
import com.couchbase.client.core.endpoint.http.CoreHttpPath;
import com.couchbase.client.core.endpoint.http.CoreHttpResponse;
import com.couchbase.client.core.error.GroupNotFoundException;
import com.couchbase.client.core.error.UserNotFoundException;
import com.couchbase.client.core.json.Mapper;
import com.couchbase.client.core.msg.RequestTarget;
import com.couchbase.client.core.msg.ResponseStatus;
import com.couchbase.client.core.util.PreventsGarbageCollection;
import com.couchbase.client.core.util.UrlQueryStringBuilder;
import com.couchbase.client.java.AsyncCluster;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import static com.couchbase.client.core.endpoint.http.CoreHttpPath.path;
import static com.couchbase.client.core.endpoint.http.CoreHttpRequest.Builder.newForm;
import static com.couchbase.client.core.error.HttpStatusCodeException.couchbaseResponseStatus;
import static com.couchbase.client.core.util.CbCollections.mapOf;
import static com.couchbase.client.core.util.CbThrowables.propagate;
import static com.couchbase.client.java.manager.user.ChangePasswordOptions.changePasswordOptions;
import static com.couchbase.client.java.manager.user.DropGroupOptions.dropGroupOptions;
import static com.couchbase.client.java.manager.user.DropUserOptions.dropUserOptions;
import static com.couchbase.client.java.manager.user.GetAllGroupsOptions.getAllGroupsOptions;
import static com.couchbase.client.java.manager.user.GetAllUsersOptions.getAllUsersOptions;
import static com.couchbase.client.java.manager.user.GetGroupOptions.getGroupOptions;
import static com.couchbase.client.java.manager.user.GetRolesOptions.getRolesOptions;
import static com.couchbase.client.java.manager.user.GetUserOptions.getUserOptions;
import static com.couchbase.client.java.manager.user.UpsertGroupOptions.upsertGroupOptions;
import static com.couchbase.client.java.manager.user.UpsertUserOptions.upsertUserOptions;
import static java.util.Objects.requireNonNull;
public class AsyncUserManager {
// https://docs.couchbase.com/server/5.5/rest-api/rbac.html
private final Core core;
private final CoreHttpClient httpClient;
@PreventsGarbageCollection
private final AsyncCluster cluster;
public AsyncUserManager(Core core, AsyncCluster cluster) {
this.core = core;
this.httpClient = core.httpClient(RequestTarget.manager());
this.cluster = requireNonNull(cluster);
}
private static CoreHttpPath pathForUsers() {
return path("/settings/rbac/users");
}
private static CoreHttpPath pathForRoles() {
return path("/settings/rbac/roles");
}
private static CoreHttpPath pathForUser(AuthDomain domain, String username) {
return path("/settings/rbac/users/{domain}/{username}", mapOf(
"username", username,
"domain", domain.alias()
));
}
private static CoreHttpPath pathForGroups() {
return path("/settings/rbac/groups");
}
private static CoreHttpPath pathForGroup(String groupName) {
return path("/settings/rbac/groups/{groupName}", mapOf(
"groupName", groupName
));
}
private static CoreHttpPath pathForPassword() {
return path("/controller/changePassword");
}
public CompletableFuture getUser(AuthDomain domain, String username) {
return getUser(domain, username, getUserOptions());
}
public CompletableFuture getUser(AuthDomain domain, String username, GetUserOptions options) {
return httpClient.get(pathForUser(domain, username), options.build())
.trace(TracingIdentifiers.SPAN_REQUEST_MU_GET_USER)
.exec(core)
.exceptionally(translateNotFound(() -> UserNotFoundException.forUser(domain.alias(), username)))
.thenApply(response -> Mapper.decodeInto(response.content(), UserAndMetadata.class));
}
public CompletableFuture> getAllUsers() {
return getAllUsers(getAllUsersOptions());
}
public CompletableFuture> getAllUsers(GetAllUsersOptions options) {
return httpClient.get(pathForUsers(), options.build())
.trace(TracingIdentifiers.SPAN_REQUEST_MU_GET_ALL_USERS)
.exec(core)
.thenApply(response -> Mapper.decodeInto(response.content(), new TypeReference>() {
}));
}
public CompletableFuture> getRoles() {
return getRoles(getRolesOptions());
}
public CompletableFuture> getRoles(GetRolesOptions options) {
return httpClient.get(pathForRoles(), options.build())
.trace(TracingIdentifiers.SPAN_REQUEST_MU_GET_ROLES)
.exec(core)
.thenApply(response -> Mapper.decodeInto(response.content(), new TypeReference>() {
}));
}
/**
* Changes the password of the currently authenticated user.
* SDK must be re-started and a new connection established after running, as the previous credentials will no longer
* be valid.
* @param newPassword String to replace the previous password with.
*/
public CompletableFuture changePassword(String newPassword){
return changePassword(newPassword, changePasswordOptions());
}
/**
* Changes the password of the currently authenticated user.
* SDK must be re-started and a new connection established after running, as the previous credentials will no longer
* be valid.
* @param newPassword String to replace the previous password with.
* @param options Common options (timeout, retry...)
*/
public CompletableFuture changePassword(String newPassword, ChangePasswordOptions options){
UrlQueryStringBuilder params = newForm()
.add("password", newPassword);
return httpClient.post(pathForPassword(), options.build())
.trace(TracingIdentifiers.SPAN_REQUEST_MU_CHANGE_PASSWORD)
.form(params)
.exec(core)
.thenApply(response -> null);
}
public CompletableFuture upsertUser(User user) {
return upsertUser(user, upsertUserOptions());
}
public CompletableFuture upsertUser(User user, UpsertUserOptions options) {
String username = user.username();
UrlQueryStringBuilder params = newForm()
.add("name", user.displayName())
.add("roles", user.roles().stream()
.map(Role::format)
.collect(Collectors.joining(",")));
// Omit empty group list for compatibility with Couchbase Server versions < 6.5.
// Versions >= 6.5 treat the absent parameter just like an empty list.
if (!user.groups().isEmpty()) {
params.add("groups", String.join(",", user.groups()));
}
// Password is required when creating user, but optional when updating existing user.
user.password().ifPresent(pwd -> params.add("password", pwd));
return httpClient.put(pathForUser(AuthDomain.LOCAL, username), options.build())
.trace(TracingIdentifiers.SPAN_REQUEST_MU_UPSERT_USER)
.form(params)
.exec(core)
.thenApply(response -> null);
}
public CompletableFuture dropUser(String username) {
return dropUser(username, dropUserOptions());
}
public CompletableFuture dropUser(String username, DropUserOptions options) {
AuthDomain domain = AuthDomain.LOCAL;
return httpClient.delete(pathForUser(domain, username), options.build())
.trace(TracingIdentifiers.SPAN_REQUEST_MU_DROP_USER)
.exec(core)
.exceptionally(translateNotFound(() -> UserNotFoundException.forUser(domain.alias(), username)))
.thenApply(response -> null);
}
public CompletableFuture getGroup(String groupName) {
return getGroup(groupName, getGroupOptions());
}
public CompletableFuture getGroup(String groupName, GetGroupOptions options) {
return httpClient.get(pathForGroup(groupName), options.build())
.trace(TracingIdentifiers.SPAN_REQUEST_MU_GET_GROUP)
.exec(core)
.exceptionally(translateNotFound(() -> GroupNotFoundException.forGroup(groupName)))
.thenApply(response -> Mapper.decodeInto(response.content(), Group.class));
}
public CompletableFuture> getAllGroups() {
return getAllGroups(getAllGroupsOptions());
}
public CompletableFuture> getAllGroups(GetAllGroupsOptions options) {
return httpClient.get(pathForGroups(), options.build())
.trace(TracingIdentifiers.SPAN_REQUEST_MU_GET_ALL_GROUPS)
.exec(core)
.thenApply(response -> Mapper.decodeInto(response.content(), new TypeReference>() {
}));
}
public CompletableFuture upsertGroup(Group group) {
return upsertGroup(group, upsertGroupOptions());
}
public CompletableFuture upsertGroup(Group group, UpsertGroupOptions options) {
UrlQueryStringBuilder params = newForm()
.add("description", group.description())
.add("ldap_group_ref", group.ldapGroupReference().orElse(""))
.add("roles", group.roles().stream()
.map(Role::format)
.collect(Collectors.joining(",")));
return httpClient.put(pathForGroup(group.name()), options.build())
.trace(TracingIdentifiers.SPAN_REQUEST_MU_UPSERT_GROUP)
.form(params)
.exec(core)
.thenApply(response -> null);
}
public CompletableFuture dropGroup(String groupName) {
return dropGroup(groupName, dropGroupOptions());
}
public CompletableFuture dropGroup(String groupName, DropGroupOptions options) {
return httpClient.delete(pathForGroup(groupName), options.build())
.trace(TracingIdentifiers.SPAN_REQUEST_MU_DROP_GROUP)
.exec(core)
.exceptionally(translateNotFound(() -> GroupNotFoundException.forGroup(groupName)))
.thenApply(response -> null);
}
private static Function translateNotFound(Supplier extends RuntimeException> exceptionSupplier) {
return t -> {
throw couchbaseResponseStatus(t) == ResponseStatus.NOT_FOUND
? exceptionSupplier.get()
: propagate(t);
};
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy