Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,19 @@ public class PinotAccessControlUserRestletResource {
* {@inheritDoc}
*/
public static final Logger LOGGER = LoggerFactory.getLogger(PinotAccessControlUserRestletResource.class);
private static final String COMPONENT_TYPE_REQUIRED_ERROR = "Component type is required as query parameter";

@Inject
PinotHelixResourceManager _pinotHelixResourceManager;

private static ComponentType validateRequiredComponentType(String componentTypeStr) {
ComponentType componentType = Constants.validateComponentType(componentTypeStr);
if (componentType == null) {
throw new ControllerApplicationException(LOGGER, COMPONENT_TYPE_REQUIRED_ERROR, Response.Status.BAD_REQUEST);
}
return componentType;
}

@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("/users")
Expand All @@ -115,10 +124,11 @@ public String listUsers() {
@Authorize(targetType = TargetType.CLUSTER, action = Actions.Cluster.GET_USER)
@ApiOperation(value = "Get an user in cluster", notes = "Get an user in cluster")
public String getUser(@PathParam("username") String username,
@ApiParam(value = "CONTROLLER|SERVER|BROKER") @QueryParam("component") String componentTypeStr) {
@ApiParam(value = "CONTROLLER|SERVER|BROKER", required = true) @QueryParam("component")
String componentTypeStr) {
ComponentType componentType = validateRequiredComponentType(componentTypeStr);
try {
ZkHelixPropertyStore<ZNRecord> propertyStore = _pinotHelixResourceManager.getPropertyStore();
ComponentType componentType = Constants.validateComponentType(componentTypeStr);
String usernameWithType = username + "_" + componentType.name();

UserConfig userConfig = ZKMetadataProvider.getUserConfig(propertyStore, usernameWithType);
Expand Down Expand Up @@ -168,15 +178,18 @@ public SuccessResponse addUser(String userConfigStr) {
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Delete a user", notes = "Delete a user")
public SuccessResponse deleteUser(@PathParam("username") String username,
@ApiParam(value = "CONTROLLER|SERVER|BROKER") @QueryParam("component") String componentTypeStr) {
@ApiParam(value = "CONTROLLER|SERVER|BROKER", required = true) @QueryParam("component")
String componentTypeStr) {

List<String> usersDeleted = new LinkedList<>();
String usernameWithComponentType = username + "_" + componentTypeStr;
ComponentType componentType = validateRequiredComponentType(componentTypeStr);
String componentTypeName = componentType.name();
String usernameWithComponentType = username + "_" + componentTypeName;

try {

boolean userExist = false;
userExist = _pinotHelixResourceManager.hasUser(username, componentTypeStr);
userExist = _pinotHelixResourceManager.hasUser(username, componentTypeName);

_pinotHelixResourceManager.deleteUser(usernameWithComponentType);
if (userExist) {
Expand All @@ -200,11 +213,14 @@ public SuccessResponse deleteUser(@PathParam("username") String username,
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Update user config for a user", notes = "Update user config for user")
public SuccessResponse updateUserConfig(@PathParam("username") String username,
@ApiParam(value = "CONTROLLER|SERVER|BROKER") @QueryParam("component") String componentTypeStr,
@ApiParam(value = "CONTROLLER|SERVER|BROKER", required = true) @QueryParam("component")
String componentTypeStr,
@QueryParam("passwordChanged") boolean passwordChanged, String userConfigString) {

UserConfig userConfig;
String usernameWithComponentType = username + "_" + componentTypeStr;
ComponentType componentType = validateRequiredComponentType(componentTypeStr);
String componentTypeName = componentType.name();
String usernameWithComponentType = username + "_" + componentTypeName;
try {
userConfig = JsonUtils.stringToObject(userConfigString, UserConfig.class);
if (passwordChanged) {
Expand All @@ -216,7 +232,7 @@ public SuccessResponse updateUserConfig(@PathParam("username") String username,
"Request user " + usernameWithComponentType + " does not match " + usernameWithComponentTypeFromUserConfig
+ " in the Request body", Response.Status.BAD_REQUEST);
}
if (!_pinotHelixResourceManager.hasUser(username, componentTypeStr)) {
if (!_pinotHelixResourceManager.hasUser(username, componentTypeName)) {
throw new ControllerApplicationException(LOGGER,
"Request user " + usernameWithComponentType + " does not exist", Response.Status.NOT_FOUND);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,13 @@
package org.apache.pinot.controller.api;

import com.fasterxml.jackson.databind.JsonNode;
import io.swagger.annotations.ApiParam;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import javax.ws.rs.core.Response;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.pinot.common.utils.BcryptUtils;
import org.apache.pinot.controller.api.resources.PinotAccessControlUserRestletResource;
import org.apache.pinot.controller.helix.ControllerTest;
import org.apache.pinot.spi.config.user.ComponentType;
import org.apache.pinot.spi.config.user.RoleType;
Expand All @@ -30,6 +36,8 @@
import org.testng.annotations.Test;

import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;


Expand All @@ -55,6 +63,47 @@ private UserConfig getUserConfig(String username, String componentType)
UserConfig.class);
}

private static ApiParam getApiParam(Method method, int parameterIndex) {
for (Annotation annotation : method.getParameterAnnotations()[parameterIndex]) {
if (annotation instanceof ApiParam) {
return (ApiParam) annotation;
}
}
return null;
}

@Test
public void testGetUserWithoutComponentReturnsClearBadRequest()
throws Exception {
Pair<Integer, String> response = ControllerTest.sendGetRequestWithStatusCode(
TEST_INSTANCE.getControllerBaseApiUrl() + "/users/testUser", null);
assertEquals(response.getLeft().intValue(), Response.Status.BAD_REQUEST.getStatusCode());
assertTrue(response.getRight().contains("Component type is required"));
assertFalse(response.getRight().contains("Cannot invoke"));
}

@Test
public void testUserComponentQueryParamIsRequiredInSwagger()
throws Exception {
Method getUser = PinotAccessControlUserRestletResource.class.getDeclaredMethod("getUser", String.class,
String.class);
Method deleteUser = PinotAccessControlUserRestletResource.class.getDeclaredMethod("deleteUser", String.class,
String.class);
Method updateUserConfig = PinotAccessControlUserRestletResource.class.getDeclaredMethod("updateUserConfig",
String.class, String.class, boolean.class, String.class);

ApiParam getUserComponent = getApiParam(getUser, 1);
ApiParam deleteUserComponent = getApiParam(deleteUser, 1);
ApiParam updateUserComponent = getApiParam(updateUserConfig, 1);

assertNotNull(getUserComponent);
assertNotNull(deleteUserComponent);
assertNotNull(updateUserComponent);
assertTrue(getUserComponent.required());
assertTrue(deleteUserComponent.required());
assertTrue(updateUserComponent.required());
}

@Test
public void testUpdateUserConfig()
throws Exception {
Expand Down
Loading