Copilot commented on code in PR #17295:
URL: https://github.com/apache/pinot/pull/17295#discussion_r2584025982


##########
pinot-spi/src/test/java/org/apache/pinot/spi/utils/builder/UserConfigBuilderTest.java:
##########
@@ -0,0 +1,261 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.pinot.spi.utils.builder;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.pinot.spi.config.user.AccessType;
+import org.apache.pinot.spi.config.user.ComponentType;
+import org.apache.pinot.spi.config.user.RoleType;
+import org.apache.pinot.spi.config.user.UserConfig;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+
+/**
+ * Tests for {@link UserConfigBuilder}
+ */
+public class UserConfigBuilderTest {
+
+  private static final String TEST_USERNAME = "testUser";
+  private static final String TEST_PASSWORD = "testPassword";
+
+  @Test
+  public void testBasicUserConfigBuild() {
+    UserConfig userConfig = new UserConfigBuilder()
+        .setUsername(TEST_USERNAME)
+        .setPassword(TEST_PASSWORD)
+        .setComponentType(ComponentType.BROKER)
+        .setRoleType(RoleType.USER)
+        .build();
+
+    Assert.assertNotNull(userConfig, "UserConfig should not be null");
+    Assert.assertEquals(userConfig.getUserName(), TEST_USERNAME, "Username 
should match");
+    Assert.assertEquals(userConfig.getPassword(), TEST_PASSWORD, "Password 
should match");
+    Assert.assertEquals(userConfig.getComponentType(), ComponentType.BROKER, 
"Component type should match");
+    Assert.assertEquals(userConfig.getRoleType(), RoleType.USER, "Role type 
should match");
+    Assert.assertNull(userConfig.getTables(), "Tables should be null when not 
set");
+    Assert.assertNull(userConfig.getExcludeTables(), "Exclude tables should be 
null when not set");
+    Assert.assertNull(userConfig.getPermissios(), "Permissions should be null 
when not set");

Review Comment:
   Corrected spelling of 'getPermissios' to 'getPermissions'.
   ```suggestion
       Assert.assertNull(userConfig.getPermissions(), "Permissions should be 
null when not set");
   ```



##########
pinot-spi/src/test/java/org/apache/pinot/spi/utils/builder/UserConfigBuilderTest.java:
##########
@@ -0,0 +1,261 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.pinot.spi.utils.builder;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.pinot.spi.config.user.AccessType;
+import org.apache.pinot.spi.config.user.ComponentType;
+import org.apache.pinot.spi.config.user.RoleType;
+import org.apache.pinot.spi.config.user.UserConfig;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+
+/**
+ * Tests for {@link UserConfigBuilder}
+ */
+public class UserConfigBuilderTest {
+
+  private static final String TEST_USERNAME = "testUser";
+  private static final String TEST_PASSWORD = "testPassword";
+
+  @Test
+  public void testBasicUserConfigBuild() {
+    UserConfig userConfig = new UserConfigBuilder()
+        .setUsername(TEST_USERNAME)
+        .setPassword(TEST_PASSWORD)
+        .setComponentType(ComponentType.BROKER)
+        .setRoleType(RoleType.USER)
+        .build();
+
+    Assert.assertNotNull(userConfig, "UserConfig should not be null");
+    Assert.assertEquals(userConfig.getUserName(), TEST_USERNAME, "Username 
should match");
+    Assert.assertEquals(userConfig.getPassword(), TEST_PASSWORD, "Password 
should match");
+    Assert.assertEquals(userConfig.getComponentType(), ComponentType.BROKER, 
"Component type should match");
+    Assert.assertEquals(userConfig.getRoleType(), RoleType.USER, "Role type 
should match");
+    Assert.assertNull(userConfig.getTables(), "Tables should be null when not 
set");
+    Assert.assertNull(userConfig.getExcludeTables(), "Exclude tables should be 
null when not set");
+    Assert.assertNull(userConfig.getPermissios(), "Permissions should be null 
when not set");
+    Assert.assertNull(userConfig.getRlsFilters(), "RLS filters should be null 
when not set");
+  }
+
+  @Test
+  public void testUserConfigWithTableList() {
+    List<String> tableList = Arrays.asList("table1", "table2", "table3");
+
+    UserConfig userConfig = new UserConfigBuilder()
+        .setUsername(TEST_USERNAME)
+        .setPassword(TEST_PASSWORD)
+        .setComponentType(ComponentType.CONTROLLER)
+        .setRoleType(RoleType.ADMIN)
+        .setTableList(tableList)
+        .build();
+
+    Assert.assertNotNull(userConfig.getTables(), "Tables should not be null");
+    Assert.assertEquals(userConfig.getTables(), tableList, "Table list should 
match");
+    Assert.assertEquals(userConfig.getTables().size(), 3, "Table list size 
should be 3");
+  }
+
+  @Test
+  public void testUserConfigWithExcludeTableList() {
+    List<String> excludeTableList = Arrays.asList("excludeTable1", 
"excludeTable2");
+
+    UserConfig userConfig = new UserConfigBuilder()
+        .setUsername(TEST_USERNAME)
+        .setPassword(TEST_PASSWORD)
+        .setComponentType(ComponentType.SERVER)
+        .setRoleType(RoleType.USER)
+        .setExcludeTableList(excludeTableList)
+        .build();
+
+    Assert.assertNotNull(userConfig.getExcludeTables(), "Exclude tables should 
not be null");
+    Assert.assertEquals(userConfig.getExcludeTables(), excludeTableList, 
"Exclude table list should match");
+    Assert.assertEquals(userConfig.getExcludeTables().size(), 2, "Exclude 
table list size should be 2");
+  }
+
+  @Test
+  public void testUserConfigWithPermissionList() {
+    List<AccessType> permissionList = Arrays.asList(AccessType.READ, 
AccessType.CREATE, AccessType.UPDATE);
+
+    UserConfig userConfig = new UserConfigBuilder()
+        .setUsername(TEST_USERNAME)
+        .setPassword(TEST_PASSWORD)
+        .setComponentType(ComponentType.MINION)
+        .setRoleType(RoleType.ADMIN)
+        .setPermissionList(permissionList)
+        .build();
+
+    Assert.assertNotNull(userConfig.getPermissios(), "Permissions should not 
be null");
+    Assert.assertEquals(userConfig.getPermissios(), permissionList, 
"Permission list should match");
+    Assert.assertEquals(userConfig.getPermissios().size(), 3, "Permission list 
size should be 3");
+    Assert.assertTrue(userConfig.getPermissios().contains(AccessType.READ), 
"Should contain READ permission");
+    Assert.assertTrue(userConfig.getPermissios().contains(AccessType.CREATE), 
"Should contain CREATE permission");
+    Assert.assertTrue(userConfig.getPermissios().contains(AccessType.UPDATE), 
"Should contain UPDATE permission");
+  }
+
+  @Test
+  public void testUserConfigWithRlsFilters() {
+    Map<String, List<String>> rlsFilters = new HashMap<>();
+    rlsFilters.put("table1", Arrays.asList("filter1", "filter2"));
+    rlsFilters.put("table2", Arrays.asList("filter3"));
+
+    UserConfig userConfig = new UserConfigBuilder()
+        .setUsername(TEST_USERNAME)
+        .setPassword(TEST_PASSWORD)
+        .setComponentType(ComponentType.PROXY)
+        .setRoleType(RoleType.USER)
+        .setRlsFilters(rlsFilters)
+        .build();
+
+    Assert.assertNotNull(userConfig.getRlsFilters(), "RLS filters should not 
be null");
+    Assert.assertEquals(userConfig.getRlsFilters(), rlsFilters, "RLS filters 
should match");
+    Assert.assertEquals(userConfig.getRlsFilters().size(), 2, "RLS filters map 
size should be 2");
+    Assert.assertTrue(userConfig.getRlsFilters().containsKey("table1"), 
"Should contain table1 filters");
+    Assert.assertTrue(userConfig.getRlsFilters().containsKey("table2"), 
"Should contain table2 filters");
+    Assert.assertEquals(userConfig.getRlsFilters().get("table1").size(), 2, 
"table1 should have 2 filters");
+    Assert.assertEquals(userConfig.getRlsFilters().get("table2").size(), 1, 
"table2 should have 1 filter");
+  }
+
+  @Test
+  public void testUserConfigWithAllFields() {
+    List<String> tableList = Arrays.asList("table1", "table2");
+    List<String> excludeTableList = Arrays.asList("excludeTable1");
+    List<AccessType> permissionList = Arrays.asList(AccessType.READ, 
AccessType.UPDATE, AccessType.DELETE);
+    Map<String, List<String>> rlsFilters = new HashMap<>();
+    rlsFilters.put("table1", Arrays.asList("country='US'", 
"department='Engineering'"));
+
+    UserConfig userConfig = new UserConfigBuilder()
+        .setUsername("adminUser")
+        .setPassword("adminPass123")
+        .setComponentType(ComponentType.BROKER)
+        .setRoleType(RoleType.ADMIN)
+        .setTableList(tableList)
+        .setExcludeTableList(excludeTableList)
+        .setPermissionList(permissionList)
+        .setRlsFilters(rlsFilters)
+        .build();
+
+    Assert.assertNotNull(userConfig, "UserConfig should not be null");
+    Assert.assertEquals(userConfig.getUserName(), "adminUser", "Username 
should match");
+    Assert.assertEquals(userConfig.getPassword(), "adminPass123", "Password 
should match");
+    Assert.assertEquals(userConfig.getComponentType(), ComponentType.BROKER, 
"Component type should match");
+    Assert.assertEquals(userConfig.getRoleType(), RoleType.ADMIN, "Role type 
should match");
+    Assert.assertEquals(userConfig.getTables(), tableList, "Table list should 
match");
+    Assert.assertEquals(userConfig.getExcludeTables(), excludeTableList, 
"Exclude table list should match");
+    Assert.assertEquals(userConfig.getPermissios(), permissionList, 
"Permission list should match");

Review Comment:
   Corrected spelling of 'getPermissios' to 'getPermissions'.
   ```suggestion
       Assert.assertEquals(userConfig.getPermissions(), permissionList, 
"Permission list should match");
   ```



##########
pinot-spi/src/test/java/org/apache/pinot/spi/utils/builder/UserConfigBuilderTest.java:
##########
@@ -0,0 +1,261 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.pinot.spi.utils.builder;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.pinot.spi.config.user.AccessType;
+import org.apache.pinot.spi.config.user.ComponentType;
+import org.apache.pinot.spi.config.user.RoleType;
+import org.apache.pinot.spi.config.user.UserConfig;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+
+/**
+ * Tests for {@link UserConfigBuilder}
+ */
+public class UserConfigBuilderTest {
+
+  private static final String TEST_USERNAME = "testUser";
+  private static final String TEST_PASSWORD = "testPassword";
+
+  @Test
+  public void testBasicUserConfigBuild() {
+    UserConfig userConfig = new UserConfigBuilder()
+        .setUsername(TEST_USERNAME)
+        .setPassword(TEST_PASSWORD)
+        .setComponentType(ComponentType.BROKER)
+        .setRoleType(RoleType.USER)
+        .build();
+
+    Assert.assertNotNull(userConfig, "UserConfig should not be null");
+    Assert.assertEquals(userConfig.getUserName(), TEST_USERNAME, "Username 
should match");
+    Assert.assertEquals(userConfig.getPassword(), TEST_PASSWORD, "Password 
should match");
+    Assert.assertEquals(userConfig.getComponentType(), ComponentType.BROKER, 
"Component type should match");
+    Assert.assertEquals(userConfig.getRoleType(), RoleType.USER, "Role type 
should match");
+    Assert.assertNull(userConfig.getTables(), "Tables should be null when not 
set");
+    Assert.assertNull(userConfig.getExcludeTables(), "Exclude tables should be 
null when not set");
+    Assert.assertNull(userConfig.getPermissios(), "Permissions should be null 
when not set");
+    Assert.assertNull(userConfig.getRlsFilters(), "RLS filters should be null 
when not set");
+  }
+
+  @Test
+  public void testUserConfigWithTableList() {
+    List<String> tableList = Arrays.asList("table1", "table2", "table3");
+
+    UserConfig userConfig = new UserConfigBuilder()
+        .setUsername(TEST_USERNAME)
+        .setPassword(TEST_PASSWORD)
+        .setComponentType(ComponentType.CONTROLLER)
+        .setRoleType(RoleType.ADMIN)
+        .setTableList(tableList)
+        .build();
+
+    Assert.assertNotNull(userConfig.getTables(), "Tables should not be null");
+    Assert.assertEquals(userConfig.getTables(), tableList, "Table list should 
match");
+    Assert.assertEquals(userConfig.getTables().size(), 3, "Table list size 
should be 3");
+  }
+
+  @Test
+  public void testUserConfigWithExcludeTableList() {
+    List<String> excludeTableList = Arrays.asList("excludeTable1", 
"excludeTable2");
+
+    UserConfig userConfig = new UserConfigBuilder()
+        .setUsername(TEST_USERNAME)
+        .setPassword(TEST_PASSWORD)
+        .setComponentType(ComponentType.SERVER)
+        .setRoleType(RoleType.USER)
+        .setExcludeTableList(excludeTableList)
+        .build();
+
+    Assert.assertNotNull(userConfig.getExcludeTables(), "Exclude tables should 
not be null");
+    Assert.assertEquals(userConfig.getExcludeTables(), excludeTableList, 
"Exclude table list should match");
+    Assert.assertEquals(userConfig.getExcludeTables().size(), 2, "Exclude 
table list size should be 2");
+  }
+
+  @Test
+  public void testUserConfigWithPermissionList() {
+    List<AccessType> permissionList = Arrays.asList(AccessType.READ, 
AccessType.CREATE, AccessType.UPDATE);
+
+    UserConfig userConfig = new UserConfigBuilder()
+        .setUsername(TEST_USERNAME)
+        .setPassword(TEST_PASSWORD)
+        .setComponentType(ComponentType.MINION)
+        .setRoleType(RoleType.ADMIN)
+        .setPermissionList(permissionList)
+        .build();
+
+    Assert.assertNotNull(userConfig.getPermissios(), "Permissions should not 
be null");
+    Assert.assertEquals(userConfig.getPermissios(), permissionList, 
"Permission list should match");
+    Assert.assertEquals(userConfig.getPermissios().size(), 3, "Permission list 
size should be 3");
+    Assert.assertTrue(userConfig.getPermissios().contains(AccessType.READ), 
"Should contain READ permission");
+    Assert.assertTrue(userConfig.getPermissios().contains(AccessType.CREATE), 
"Should contain CREATE permission");
+    Assert.assertTrue(userConfig.getPermissios().contains(AccessType.UPDATE), 
"Should contain UPDATE permission");

Review Comment:
   Multiple occurrences of 'getPermissios' should be corrected to 
'getPermissions'.
   ```suggestion
       Assert.assertNotNull(userConfig.getPermissions(), "Permissions should 
not be null");
       Assert.assertEquals(userConfig.getPermissions(), permissionList, 
"Permission list should match");
       Assert.assertEquals(userConfig.getPermissions().size(), 3, "Permission 
list size should be 3");
       Assert.assertTrue(userConfig.getPermissions().contains(AccessType.READ), 
"Should contain READ permission");
       
Assert.assertTrue(userConfig.getPermissions().contains(AccessType.CREATE), 
"Should contain CREATE permission");
       
Assert.assertTrue(userConfig.getPermissions().contains(AccessType.UPDATE), 
"Should contain UPDATE permission");
   ```



##########
pinot-common/src/test/java/org/apache/pinot/common/utils/config/AccessControlUserConfigUtilsTest.java:
##########
@@ -0,0 +1,559 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.pinot.common.utils.config;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.helix.zookeeper.datamodel.ZNRecord;
+import org.apache.pinot.spi.config.user.AccessType;
+import org.apache.pinot.spi.config.user.ComponentType;
+import org.apache.pinot.spi.config.user.RoleType;
+import org.apache.pinot.spi.config.user.UserConfig;
+import org.apache.pinot.spi.utils.JsonUtils;
+import org.apache.pinot.spi.utils.builder.UserConfigBuilder;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+
+/**
+ * Tests for {@link AccessControlUserConfigUtils}
+ */
+public class AccessControlUserConfigUtilsTest {
+
+  private static final String TEST_USERNAME = "testUser";
+  private static final String TEST_PASSWORD = "testPassword";
+
+  @Test
+  public void testFromZNRecordWithMandatoryFieldsOnly() {
+    // Create ZNRecord with only mandatory fields
+    ZNRecord znRecord = new ZNRecord(TEST_USERNAME);
+    Map<String, String> simpleFields = new HashMap<>();
+    simpleFields.put(UserConfig.USERNAME_KEY, TEST_USERNAME);
+    simpleFields.put(UserConfig.PASSWORD_KEY, TEST_PASSWORD);
+    simpleFields.put(UserConfig.COMPONET_KEY, ComponentType.BROKER.toString());
+    simpleFields.put(UserConfig.ROLE_KEY, RoleType.USER.toString());
+    znRecord.setSimpleFields(simpleFields);
+
+    UserConfig userConfig = 
AccessControlUserConfigUtils.fromZNRecord(znRecord);
+
+    Assert.assertNotNull(userConfig, "UserConfig should not be null");
+    Assert.assertEquals(userConfig.getUserName(), TEST_USERNAME, "Username 
should match");
+    Assert.assertEquals(userConfig.getPassword(), TEST_PASSWORD, "Password 
should match");
+    Assert.assertEquals(userConfig.getComponentType(), ComponentType.BROKER, 
"Component type should match");
+    Assert.assertEquals(userConfig.getRoleType(), RoleType.USER, "Role type 
should match");
+    Assert.assertNull(userConfig.getTables(), "Tables should be null");
+    Assert.assertNull(userConfig.getExcludeTables(), "Exclude tables should be 
null");
+    Assert.assertNull(userConfig.getPermissios(), "Permissions should be 
null");
+    Assert.assertNull(userConfig.getRlsFilters(), "RLS filters should be 
null");
+  }
+
+  @Test
+  public void testFromZNRecordWithTableList() {
+    ZNRecord znRecord = new ZNRecord(TEST_USERNAME);
+    Map<String, String> simpleFields = new HashMap<>();
+    simpleFields.put(UserConfig.USERNAME_KEY, TEST_USERNAME);
+    simpleFields.put(UserConfig.PASSWORD_KEY, TEST_PASSWORD);
+    simpleFields.put(UserConfig.COMPONET_KEY, 
ComponentType.CONTROLLER.toString());
+    simpleFields.put(UserConfig.ROLE_KEY, RoleType.ADMIN.toString());
+    znRecord.setSimpleFields(simpleFields);
+
+    List<String> tableList = Arrays.asList("table1", "table2", "table3");
+    znRecord.setListField(UserConfig.TABLES_KEY, tableList);
+
+    UserConfig userConfig = 
AccessControlUserConfigUtils.fromZNRecord(znRecord);
+
+    Assert.assertNotNull(userConfig.getTables(), "Tables should not be null");
+    Assert.assertEquals(userConfig.getTables(), tableList, "Table list should 
match");
+    Assert.assertEquals(userConfig.getTables().size(), 3, "Table list size 
should be 3");
+  }
+
+  @Test
+  public void testFromZNRecordWithExcludeTableList() {
+    ZNRecord znRecord = new ZNRecord(TEST_USERNAME);
+    Map<String, String> simpleFields = new HashMap<>();
+    simpleFields.put(UserConfig.USERNAME_KEY, TEST_USERNAME);
+    simpleFields.put(UserConfig.PASSWORD_KEY, TEST_PASSWORD);
+    simpleFields.put(UserConfig.COMPONET_KEY, ComponentType.SERVER.toString());
+    simpleFields.put(UserConfig.ROLE_KEY, RoleType.USER.toString());
+    znRecord.setSimpleFields(simpleFields);
+
+    List<String> excludeTableList = Arrays.asList("excludeTable1", 
"excludeTable2");
+    znRecord.setListField(UserConfig.EXCLUDE_TABLES_KEY, excludeTableList);
+
+    UserConfig userConfig = 
AccessControlUserConfigUtils.fromZNRecord(znRecord);
+
+    Assert.assertNotNull(userConfig.getExcludeTables(), "Exclude tables should 
not be null");
+    Assert.assertEquals(userConfig.getExcludeTables(), excludeTableList, 
"Exclude table list should match");
+    Assert.assertEquals(userConfig.getExcludeTables().size(), 2, "Exclude 
table list size should be 2");
+  }
+
+  @Test
+  public void testFromZNRecordWithPermissionList() {
+    ZNRecord znRecord = new ZNRecord(TEST_USERNAME);
+    Map<String, String> simpleFields = new HashMap<>();
+    simpleFields.put(UserConfig.USERNAME_KEY, TEST_USERNAME);
+    simpleFields.put(UserConfig.PASSWORD_KEY, TEST_PASSWORD);
+    simpleFields.put(UserConfig.COMPONET_KEY, ComponentType.MINION.toString());
+    simpleFields.put(UserConfig.ROLE_KEY, RoleType.ADMIN.toString());
+    znRecord.setSimpleFields(simpleFields);
+
+    List<String> permissionListStr = Arrays.asList("READ", "CREATE", "UPDATE");
+    znRecord.setListField(UserConfig.PERMISSIONS_KEY, permissionListStr);
+
+    UserConfig userConfig = 
AccessControlUserConfigUtils.fromZNRecord(znRecord);
+
+    Assert.assertNotNull(userConfig.getPermissios(), "Permissions should not 
be null");
+    Assert.assertEquals(userConfig.getPermissios().size(), 3, "Permission list 
size should be 3");
+    Assert.assertTrue(userConfig.getPermissios().contains(AccessType.READ), 
"Should contain READ permission");
+    Assert.assertTrue(userConfig.getPermissios().contains(AccessType.CREATE), 
"Should contain CREATE permission");
+    Assert.assertTrue(userConfig.getPermissios().contains(AccessType.UPDATE), 
"Should contain UPDATE permission");

Review Comment:
   Multiple occurrences of 'getPermissios' should be corrected to 
'getPermissions'.
   ```suggestion
       Assert.assertNotNull(userConfig.getPermissions(), "Permissions should 
not be null");
       Assert.assertEquals(userConfig.getPermissions().size(), 3, "Permission 
list size should be 3");
       Assert.assertTrue(userConfig.getPermissions().contains(AccessType.READ), 
"Should contain READ permission");
       
Assert.assertTrue(userConfig.getPermissions().contains(AccessType.CREATE), 
"Should contain CREATE permission");
       
Assert.assertTrue(userConfig.getPermissions().contains(AccessType.UPDATE), 
"Should contain UPDATE permission");
   ```



##########
pinot-common/src/test/java/org/apache/pinot/common/utils/config/AccessControlUserConfigUtilsTest.java:
##########
@@ -0,0 +1,559 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.pinot.common.utils.config;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.helix.zookeeper.datamodel.ZNRecord;
+import org.apache.pinot.spi.config.user.AccessType;
+import org.apache.pinot.spi.config.user.ComponentType;
+import org.apache.pinot.spi.config.user.RoleType;
+import org.apache.pinot.spi.config.user.UserConfig;
+import org.apache.pinot.spi.utils.JsonUtils;
+import org.apache.pinot.spi.utils.builder.UserConfigBuilder;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+
+/**
+ * Tests for {@link AccessControlUserConfigUtils}
+ */
+public class AccessControlUserConfigUtilsTest {
+
+  private static final String TEST_USERNAME = "testUser";
+  private static final String TEST_PASSWORD = "testPassword";
+
+  @Test
+  public void testFromZNRecordWithMandatoryFieldsOnly() {
+    // Create ZNRecord with only mandatory fields
+    ZNRecord znRecord = new ZNRecord(TEST_USERNAME);
+    Map<String, String> simpleFields = new HashMap<>();
+    simpleFields.put(UserConfig.USERNAME_KEY, TEST_USERNAME);
+    simpleFields.put(UserConfig.PASSWORD_KEY, TEST_PASSWORD);
+    simpleFields.put(UserConfig.COMPONET_KEY, ComponentType.BROKER.toString());
+    simpleFields.put(UserConfig.ROLE_KEY, RoleType.USER.toString());
+    znRecord.setSimpleFields(simpleFields);
+
+    UserConfig userConfig = 
AccessControlUserConfigUtils.fromZNRecord(znRecord);
+
+    Assert.assertNotNull(userConfig, "UserConfig should not be null");
+    Assert.assertEquals(userConfig.getUserName(), TEST_USERNAME, "Username 
should match");
+    Assert.assertEquals(userConfig.getPassword(), TEST_PASSWORD, "Password 
should match");
+    Assert.assertEquals(userConfig.getComponentType(), ComponentType.BROKER, 
"Component type should match");
+    Assert.assertEquals(userConfig.getRoleType(), RoleType.USER, "Role type 
should match");
+    Assert.assertNull(userConfig.getTables(), "Tables should be null");
+    Assert.assertNull(userConfig.getExcludeTables(), "Exclude tables should be 
null");
+    Assert.assertNull(userConfig.getPermissios(), "Permissions should be 
null");

Review Comment:
   Corrected spelling of 'getPermissios' to 'getPermissions'.
   ```suggestion
       Assert.assertNull(userConfig.getPermissions(), "Permissions should be 
null");
   ```



##########
pinot-spi/src/test/java/org/apache/pinot/spi/utils/builder/UserConfigBuilderTest.java:
##########
@@ -0,0 +1,261 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.pinot.spi.utils.builder;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.pinot.spi.config.user.AccessType;
+import org.apache.pinot.spi.config.user.ComponentType;
+import org.apache.pinot.spi.config.user.RoleType;
+import org.apache.pinot.spi.config.user.UserConfig;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+
+/**
+ * Tests for {@link UserConfigBuilder}
+ */
+public class UserConfigBuilderTest {
+
+  private static final String TEST_USERNAME = "testUser";
+  private static final String TEST_PASSWORD = "testPassword";
+
+  @Test
+  public void testBasicUserConfigBuild() {
+    UserConfig userConfig = new UserConfigBuilder()
+        .setUsername(TEST_USERNAME)
+        .setPassword(TEST_PASSWORD)
+        .setComponentType(ComponentType.BROKER)
+        .setRoleType(RoleType.USER)
+        .build();
+
+    Assert.assertNotNull(userConfig, "UserConfig should not be null");
+    Assert.assertEquals(userConfig.getUserName(), TEST_USERNAME, "Username 
should match");
+    Assert.assertEquals(userConfig.getPassword(), TEST_PASSWORD, "Password 
should match");
+    Assert.assertEquals(userConfig.getComponentType(), ComponentType.BROKER, 
"Component type should match");
+    Assert.assertEquals(userConfig.getRoleType(), RoleType.USER, "Role type 
should match");
+    Assert.assertNull(userConfig.getTables(), "Tables should be null when not 
set");
+    Assert.assertNull(userConfig.getExcludeTables(), "Exclude tables should be 
null when not set");
+    Assert.assertNull(userConfig.getPermissios(), "Permissions should be null 
when not set");
+    Assert.assertNull(userConfig.getRlsFilters(), "RLS filters should be null 
when not set");
+  }
+
+  @Test
+  public void testUserConfigWithTableList() {
+    List<String> tableList = Arrays.asList("table1", "table2", "table3");
+
+    UserConfig userConfig = new UserConfigBuilder()
+        .setUsername(TEST_USERNAME)
+        .setPassword(TEST_PASSWORD)
+        .setComponentType(ComponentType.CONTROLLER)
+        .setRoleType(RoleType.ADMIN)
+        .setTableList(tableList)
+        .build();
+
+    Assert.assertNotNull(userConfig.getTables(), "Tables should not be null");
+    Assert.assertEquals(userConfig.getTables(), tableList, "Table list should 
match");
+    Assert.assertEquals(userConfig.getTables().size(), 3, "Table list size 
should be 3");
+  }
+
+  @Test
+  public void testUserConfigWithExcludeTableList() {
+    List<String> excludeTableList = Arrays.asList("excludeTable1", 
"excludeTable2");
+
+    UserConfig userConfig = new UserConfigBuilder()
+        .setUsername(TEST_USERNAME)
+        .setPassword(TEST_PASSWORD)
+        .setComponentType(ComponentType.SERVER)
+        .setRoleType(RoleType.USER)
+        .setExcludeTableList(excludeTableList)
+        .build();
+
+    Assert.assertNotNull(userConfig.getExcludeTables(), "Exclude tables should 
not be null");
+    Assert.assertEquals(userConfig.getExcludeTables(), excludeTableList, 
"Exclude table list should match");
+    Assert.assertEquals(userConfig.getExcludeTables().size(), 2, "Exclude 
table list size should be 2");
+  }
+
+  @Test
+  public void testUserConfigWithPermissionList() {
+    List<AccessType> permissionList = Arrays.asList(AccessType.READ, 
AccessType.CREATE, AccessType.UPDATE);
+
+    UserConfig userConfig = new UserConfigBuilder()
+        .setUsername(TEST_USERNAME)
+        .setPassword(TEST_PASSWORD)
+        .setComponentType(ComponentType.MINION)
+        .setRoleType(RoleType.ADMIN)
+        .setPermissionList(permissionList)
+        .build();
+
+    Assert.assertNotNull(userConfig.getPermissios(), "Permissions should not 
be null");
+    Assert.assertEquals(userConfig.getPermissios(), permissionList, 
"Permission list should match");
+    Assert.assertEquals(userConfig.getPermissios().size(), 3, "Permission list 
size should be 3");
+    Assert.assertTrue(userConfig.getPermissios().contains(AccessType.READ), 
"Should contain READ permission");
+    Assert.assertTrue(userConfig.getPermissios().contains(AccessType.CREATE), 
"Should contain CREATE permission");
+    Assert.assertTrue(userConfig.getPermissios().contains(AccessType.UPDATE), 
"Should contain UPDATE permission");
+  }
+
+  @Test
+  public void testUserConfigWithRlsFilters() {
+    Map<String, List<String>> rlsFilters = new HashMap<>();
+    rlsFilters.put("table1", Arrays.asList("filter1", "filter2"));
+    rlsFilters.put("table2", Arrays.asList("filter3"));
+
+    UserConfig userConfig = new UserConfigBuilder()
+        .setUsername(TEST_USERNAME)
+        .setPassword(TEST_PASSWORD)
+        .setComponentType(ComponentType.PROXY)
+        .setRoleType(RoleType.USER)
+        .setRlsFilters(rlsFilters)
+        .build();
+
+    Assert.assertNotNull(userConfig.getRlsFilters(), "RLS filters should not 
be null");
+    Assert.assertEquals(userConfig.getRlsFilters(), rlsFilters, "RLS filters 
should match");
+    Assert.assertEquals(userConfig.getRlsFilters().size(), 2, "RLS filters map 
size should be 2");
+    Assert.assertTrue(userConfig.getRlsFilters().containsKey("table1"), 
"Should contain table1 filters");
+    Assert.assertTrue(userConfig.getRlsFilters().containsKey("table2"), 
"Should contain table2 filters");
+    Assert.assertEquals(userConfig.getRlsFilters().get("table1").size(), 2, 
"table1 should have 2 filters");
+    Assert.assertEquals(userConfig.getRlsFilters().get("table2").size(), 1, 
"table2 should have 1 filter");
+  }
+
+  @Test
+  public void testUserConfigWithAllFields() {
+    List<String> tableList = Arrays.asList("table1", "table2");
+    List<String> excludeTableList = Arrays.asList("excludeTable1");
+    List<AccessType> permissionList = Arrays.asList(AccessType.READ, 
AccessType.UPDATE, AccessType.DELETE);
+    Map<String, List<String>> rlsFilters = new HashMap<>();
+    rlsFilters.put("table1", Arrays.asList("country='US'", 
"department='Engineering'"));
+
+    UserConfig userConfig = new UserConfigBuilder()
+        .setUsername("adminUser")
+        .setPassword("adminPass123")
+        .setComponentType(ComponentType.BROKER)
+        .setRoleType(RoleType.ADMIN)
+        .setTableList(tableList)
+        .setExcludeTableList(excludeTableList)
+        .setPermissionList(permissionList)
+        .setRlsFilters(rlsFilters)
+        .build();
+
+    Assert.assertNotNull(userConfig, "UserConfig should not be null");
+    Assert.assertEquals(userConfig.getUserName(), "adminUser", "Username 
should match");
+    Assert.assertEquals(userConfig.getPassword(), "adminPass123", "Password 
should match");
+    Assert.assertEquals(userConfig.getComponentType(), ComponentType.BROKER, 
"Component type should match");
+    Assert.assertEquals(userConfig.getRoleType(), RoleType.ADMIN, "Role type 
should match");
+    Assert.assertEquals(userConfig.getTables(), tableList, "Table list should 
match");
+    Assert.assertEquals(userConfig.getExcludeTables(), excludeTableList, 
"Exclude table list should match");
+    Assert.assertEquals(userConfig.getPermissios(), permissionList, 
"Permission list should match");
+    Assert.assertEquals(userConfig.getRlsFilters(), rlsFilters, "RLS filters 
should match");
+  }
+
+  @Test
+  public void testBuilderChaining() {
+    UserConfigBuilder builder = new UserConfigBuilder();
+
+    // Verify that each setter returns the builder instance for chaining
+    UserConfigBuilder result1 = builder.setUsername(TEST_USERNAME);
+    Assert.assertSame(result1, builder, "setUsername should return the builder 
instance");
+
+    UserConfigBuilder result2 = builder.setPassword(TEST_PASSWORD);
+    Assert.assertSame(result2, builder, "setPassword should return the builder 
instance");
+
+    UserConfigBuilder result3 = builder.setComponentType(ComponentType.BROKER);
+    Assert.assertSame(result3, builder, "setComponentType should return the 
builder instance");
+
+    UserConfigBuilder result4 = builder.setRoleType(RoleType.USER);
+    Assert.assertSame(result4, builder, "setRoleType should return the builder 
instance");
+
+    UserConfigBuilder result5 = builder.setTableList(Arrays.asList("table1"));
+    Assert.assertSame(result5, builder, "setTableList should return the 
builder instance");
+
+    UserConfigBuilder result6 = 
builder.setExcludeTableList(Arrays.asList("excludeTable1"));
+    Assert.assertSame(result6, builder, "setExcludeTableList should return the 
builder instance");
+
+    UserConfigBuilder result7 = 
builder.setPermissionList(Arrays.asList(AccessType.READ));
+    Assert.assertSame(result7, builder, "setPermissionList should return the 
builder instance");
+
+    Map<String, List<String>> rlsFilters = new HashMap<>();
+    rlsFilters.put("table1", Arrays.asList("filter1"));
+    UserConfigBuilder result8 = builder.setRlsFilters(rlsFilters);
+    Assert.assertSame(result8, builder, "setRlsFilters should return the 
builder instance");
+  }
+
+  @Test
+  public void testMultipleComponentTypes() {
+    // Test with different component types
+    ComponentType[] componentTypes = {
+        ComponentType.CONTROLLER, ComponentType.BROKER, ComponentType.SERVER,
+        ComponentType.MINION, ComponentType.PROXY
+    };
+
+    for (ComponentType componentType : componentTypes) {
+      UserConfig userConfig = new UserConfigBuilder()
+          .setUsername(TEST_USERNAME)
+          .setPassword(TEST_PASSWORD)
+          .setComponentType(componentType)
+          .setRoleType(RoleType.USER)
+          .build();
+
+      Assert.assertEquals(userConfig.getComponentType(), componentType,
+          "Component type should match for " + componentType);
+    }
+  }
+
+  @Test
+  public void testMultipleRoleTypes() {
+    // Test with different role types
+    RoleType[] roleTypes = {RoleType.ADMIN, RoleType.USER};
+
+    for (RoleType roleType : roleTypes) {
+      UserConfig userConfig = new UserConfigBuilder()
+          .setUsername(TEST_USERNAME)
+          .setPassword(TEST_PASSWORD)
+          .setComponentType(ComponentType.BROKER)
+          .setRoleType(roleType)
+          .build();
+
+      Assert.assertEquals(userConfig.getRoleType(), roleType,
+          "Role type should match for " + roleType);
+    }
+  }
+
+  @Test
+  public void testAllAccessTypes() {
+    // Test with all access types
+    List<AccessType> allPermissions = Arrays.asList(
+        AccessType.CREATE, AccessType.READ, AccessType.UPDATE, 
AccessType.DELETE
+    );
+
+    UserConfig userConfig = new UserConfigBuilder()
+        .setUsername(TEST_USERNAME)
+        .setPassword(TEST_PASSWORD)
+        .setComponentType(ComponentType.BROKER)
+        .setRoleType(RoleType.ADMIN)
+        .setPermissionList(allPermissions)
+        .build();
+
+    Assert.assertEquals(userConfig.getPermissios().size(), 4, "Should have all 
4 access types");
+    Assert.assertTrue(userConfig.getPermissios().contains(AccessType.CREATE), 
"Should contain CREATE");
+    Assert.assertTrue(userConfig.getPermissios().contains(AccessType.READ), 
"Should contain READ");
+    Assert.assertTrue(userConfig.getPermissios().contains(AccessType.UPDATE), 
"Should contain UPDATE");
+    Assert.assertTrue(userConfig.getPermissios().contains(AccessType.DELETE), 
"Should contain DELETE");

Review Comment:
   Multiple occurrences of 'getPermissios' should be corrected to 
'getPermissions'.
   ```suggestion
       Assert.assertEquals(userConfig.getPermissions().size(), 4, "Should have 
all 4 access types");
       
Assert.assertTrue(userConfig.getPermissions().contains(AccessType.CREATE), 
"Should contain CREATE");
       Assert.assertTrue(userConfig.getPermissions().contains(AccessType.READ), 
"Should contain READ");
       
Assert.assertTrue(userConfig.getPermissions().contains(AccessType.UPDATE), 
"Should contain UPDATE");
       
Assert.assertTrue(userConfig.getPermissions().contains(AccessType.DELETE), 
"Should contain DELETE");
   ```



##########
pinot-common/src/test/java/org/apache/pinot/common/utils/config/AccessControlUserConfigUtilsTest.java:
##########
@@ -0,0 +1,559 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.pinot.common.utils.config;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.helix.zookeeper.datamodel.ZNRecord;
+import org.apache.pinot.spi.config.user.AccessType;
+import org.apache.pinot.spi.config.user.ComponentType;
+import org.apache.pinot.spi.config.user.RoleType;
+import org.apache.pinot.spi.config.user.UserConfig;
+import org.apache.pinot.spi.utils.JsonUtils;
+import org.apache.pinot.spi.utils.builder.UserConfigBuilder;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+
+/**
+ * Tests for {@link AccessControlUserConfigUtils}
+ */
+public class AccessControlUserConfigUtilsTest {
+
+  private static final String TEST_USERNAME = "testUser";
+  private static final String TEST_PASSWORD = "testPassword";
+
+  @Test
+  public void testFromZNRecordWithMandatoryFieldsOnly() {
+    // Create ZNRecord with only mandatory fields
+    ZNRecord znRecord = new ZNRecord(TEST_USERNAME);
+    Map<String, String> simpleFields = new HashMap<>();
+    simpleFields.put(UserConfig.USERNAME_KEY, TEST_USERNAME);
+    simpleFields.put(UserConfig.PASSWORD_KEY, TEST_PASSWORD);
+    simpleFields.put(UserConfig.COMPONET_KEY, ComponentType.BROKER.toString());
+    simpleFields.put(UserConfig.ROLE_KEY, RoleType.USER.toString());
+    znRecord.setSimpleFields(simpleFields);
+
+    UserConfig userConfig = 
AccessControlUserConfigUtils.fromZNRecord(znRecord);
+
+    Assert.assertNotNull(userConfig, "UserConfig should not be null");
+    Assert.assertEquals(userConfig.getUserName(), TEST_USERNAME, "Username 
should match");
+    Assert.assertEquals(userConfig.getPassword(), TEST_PASSWORD, "Password 
should match");
+    Assert.assertEquals(userConfig.getComponentType(), ComponentType.BROKER, 
"Component type should match");
+    Assert.assertEquals(userConfig.getRoleType(), RoleType.USER, "Role type 
should match");
+    Assert.assertNull(userConfig.getTables(), "Tables should be null");
+    Assert.assertNull(userConfig.getExcludeTables(), "Exclude tables should be 
null");
+    Assert.assertNull(userConfig.getPermissios(), "Permissions should be 
null");
+    Assert.assertNull(userConfig.getRlsFilters(), "RLS filters should be 
null");
+  }
+
+  @Test
+  public void testFromZNRecordWithTableList() {
+    ZNRecord znRecord = new ZNRecord(TEST_USERNAME);
+    Map<String, String> simpleFields = new HashMap<>();
+    simpleFields.put(UserConfig.USERNAME_KEY, TEST_USERNAME);
+    simpleFields.put(UserConfig.PASSWORD_KEY, TEST_PASSWORD);
+    simpleFields.put(UserConfig.COMPONET_KEY, 
ComponentType.CONTROLLER.toString());
+    simpleFields.put(UserConfig.ROLE_KEY, RoleType.ADMIN.toString());
+    znRecord.setSimpleFields(simpleFields);
+
+    List<String> tableList = Arrays.asList("table1", "table2", "table3");
+    znRecord.setListField(UserConfig.TABLES_KEY, tableList);
+
+    UserConfig userConfig = 
AccessControlUserConfigUtils.fromZNRecord(znRecord);
+
+    Assert.assertNotNull(userConfig.getTables(), "Tables should not be null");
+    Assert.assertEquals(userConfig.getTables(), tableList, "Table list should 
match");
+    Assert.assertEquals(userConfig.getTables().size(), 3, "Table list size 
should be 3");
+  }
+
+  @Test
+  public void testFromZNRecordWithExcludeTableList() {
+    ZNRecord znRecord = new ZNRecord(TEST_USERNAME);
+    Map<String, String> simpleFields = new HashMap<>();
+    simpleFields.put(UserConfig.USERNAME_KEY, TEST_USERNAME);
+    simpleFields.put(UserConfig.PASSWORD_KEY, TEST_PASSWORD);
+    simpleFields.put(UserConfig.COMPONET_KEY, ComponentType.SERVER.toString());
+    simpleFields.put(UserConfig.ROLE_KEY, RoleType.USER.toString());
+    znRecord.setSimpleFields(simpleFields);
+
+    List<String> excludeTableList = Arrays.asList("excludeTable1", 
"excludeTable2");
+    znRecord.setListField(UserConfig.EXCLUDE_TABLES_KEY, excludeTableList);
+
+    UserConfig userConfig = 
AccessControlUserConfigUtils.fromZNRecord(znRecord);
+
+    Assert.assertNotNull(userConfig.getExcludeTables(), "Exclude tables should 
not be null");
+    Assert.assertEquals(userConfig.getExcludeTables(), excludeTableList, 
"Exclude table list should match");
+    Assert.assertEquals(userConfig.getExcludeTables().size(), 2, "Exclude 
table list size should be 2");
+  }
+
+  @Test
+  public void testFromZNRecordWithPermissionList() {
+    ZNRecord znRecord = new ZNRecord(TEST_USERNAME);
+    Map<String, String> simpleFields = new HashMap<>();
+    simpleFields.put(UserConfig.USERNAME_KEY, TEST_USERNAME);
+    simpleFields.put(UserConfig.PASSWORD_KEY, TEST_PASSWORD);
+    simpleFields.put(UserConfig.COMPONET_KEY, ComponentType.MINION.toString());
+    simpleFields.put(UserConfig.ROLE_KEY, RoleType.ADMIN.toString());
+    znRecord.setSimpleFields(simpleFields);
+
+    List<String> permissionListStr = Arrays.asList("READ", "CREATE", "UPDATE");
+    znRecord.setListField(UserConfig.PERMISSIONS_KEY, permissionListStr);
+
+    UserConfig userConfig = 
AccessControlUserConfigUtils.fromZNRecord(znRecord);
+
+    Assert.assertNotNull(userConfig.getPermissios(), "Permissions should not 
be null");
+    Assert.assertEquals(userConfig.getPermissios().size(), 3, "Permission list 
size should be 3");
+    Assert.assertTrue(userConfig.getPermissios().contains(AccessType.READ), 
"Should contain READ permission");
+    Assert.assertTrue(userConfig.getPermissios().contains(AccessType.CREATE), 
"Should contain CREATE permission");
+    Assert.assertTrue(userConfig.getPermissios().contains(AccessType.UPDATE), 
"Should contain UPDATE permission");
+  }
+
+  @Test
+  public void testFromZNRecordWithRlsFilters() throws JsonProcessingException {
+    ZNRecord znRecord = new ZNRecord(TEST_USERNAME);
+    Map<String, String> simpleFields = new HashMap<>();
+    simpleFields.put(UserConfig.USERNAME_KEY, TEST_USERNAME);
+    simpleFields.put(UserConfig.PASSWORD_KEY, TEST_PASSWORD);
+    simpleFields.put(UserConfig.COMPONET_KEY, ComponentType.BROKER.toString());
+    simpleFields.put(UserConfig.ROLE_KEY, RoleType.USER.toString());
+
+    Map<String, List<String>> rlsFilters = new HashMap<>();
+    rlsFilters.put("table1", Arrays.asList("country='US'", 
"department='Engineering'"));
+    rlsFilters.put("table2", Arrays.asList("region='WEST'"));
+    simpleFields.put(UserConfig.RLS_FILTERS_KEY, 
JsonUtils.objectToString(rlsFilters));
+
+    znRecord.setSimpleFields(simpleFields);
+
+    UserConfig userConfig = 
AccessControlUserConfigUtils.fromZNRecord(znRecord);
+
+    Assert.assertNotNull(userConfig.getRlsFilters(), "RLS filters should not 
be null");
+    Assert.assertEquals(userConfig.getRlsFilters().size(), 2, "RLS filters map 
size should be 2");
+    Assert.assertTrue(userConfig.getRlsFilters().containsKey("table1"), 
"Should contain table1 filters");
+    Assert.assertTrue(userConfig.getRlsFilters().containsKey("table2"), 
"Should contain table2 filters");
+    Assert.assertEquals(userConfig.getRlsFilters().get("table1").size(), 2, 
"table1 should have 2 filters");
+    Assert.assertEquals(userConfig.getRlsFilters().get("table2").size(), 1, 
"table2 should have 1 filter");
+    // Verify actual filter values
+    Assert.assertEquals(userConfig.getRlsFilters().get("table1").get(0), 
"country='US'");
+    Assert.assertEquals(userConfig.getRlsFilters().get("table1").get(1), 
"department='Engineering'");
+    Assert.assertEquals(userConfig.getRlsFilters().get("table2").get(0), 
"region='WEST'");
+  }
+
+  @Test
+  public void testFromZNRecordWithMalformedRlsFilters() {
+    ZNRecord znRecord = new ZNRecord(TEST_USERNAME);
+    Map<String, String> simpleFields = new HashMap<>();
+    simpleFields.put(UserConfig.USERNAME_KEY, TEST_USERNAME);
+    simpleFields.put(UserConfig.PASSWORD_KEY, TEST_PASSWORD);
+    simpleFields.put(UserConfig.COMPONET_KEY, ComponentType.BROKER.toString());
+    simpleFields.put(UserConfig.ROLE_KEY, RoleType.USER.toString());
+    simpleFields.put(UserConfig.RLS_FILTERS_KEY, "invalid-json-{malformed");
+    znRecord.setSimpleFields(simpleFields);
+
+    // Should not throw exception, but log error and continue
+    UserConfig userConfig = 
AccessControlUserConfigUtils.fromZNRecord(znRecord);
+
+    Assert.assertNotNull(userConfig, "UserConfig should not be null");
+    Assert.assertNull(userConfig.getRlsFilters(), "RLS filters should be null 
due to malformed JSON");
+  }
+
+  @Test
+  public void testFromZNRecordWithAllFields() throws JsonProcessingException {
+    ZNRecord znRecord = new ZNRecord(TEST_USERNAME);
+    Map<String, String> simpleFields = new HashMap<>();
+    simpleFields.put(UserConfig.USERNAME_KEY, "adminUser");
+    simpleFields.put(UserConfig.PASSWORD_KEY, "adminPass123");
+    simpleFields.put(UserConfig.COMPONET_KEY, ComponentType.PROXY.toString());
+    simpleFields.put(UserConfig.ROLE_KEY, RoleType.ADMIN.toString());
+
+    Map<String, List<String>> rlsFilters = new HashMap<>();
+    rlsFilters.put("table1", Arrays.asList("filter1", "filter2"));
+    simpleFields.put(UserConfig.RLS_FILTERS_KEY, 
JsonUtils.objectToString(rlsFilters));
+    znRecord.setSimpleFields(simpleFields);
+
+    List<String> tableList = Arrays.asList("table1", "table2");
+    List<String> excludeTableList = Arrays.asList("excludeTable1");
+    List<String> permissionListStr = Arrays.asList("READ", "UPDATE", "DELETE");
+
+    znRecord.setListField(UserConfig.TABLES_KEY, tableList);
+    znRecord.setListField(UserConfig.EXCLUDE_TABLES_KEY, excludeTableList);
+    znRecord.setListField(UserConfig.PERMISSIONS_KEY, permissionListStr);
+
+    UserConfig userConfig = 
AccessControlUserConfigUtils.fromZNRecord(znRecord);
+
+    Assert.assertNotNull(userConfig, "UserConfig should not be null");
+    Assert.assertEquals(userConfig.getUserName(), "adminUser", "Username 
should match");
+    Assert.assertEquals(userConfig.getPassword(), "adminPass123", "Password 
should match");
+    Assert.assertEquals(userConfig.getComponentType(), ComponentType.PROXY, 
"Component type should match");
+    Assert.assertEquals(userConfig.getRoleType(), RoleType.ADMIN, "Role type 
should match");
+    Assert.assertEquals(userConfig.getTables(), tableList, "Table list should 
match");
+    Assert.assertEquals(userConfig.getExcludeTables(), excludeTableList, 
"Exclude table list should match");
+    Assert.assertEquals(userConfig.getPermissios().size(), 3, "Permission list 
size should match");
+    Assert.assertNotNull(userConfig.getRlsFilters(), "RLS filters should not 
be null");
+  }
+
+  @Test
+  public void testToZNRecordWithMandatoryFieldsOnly() throws 
JsonProcessingException {
+    UserConfig userConfig = new UserConfigBuilder()
+        .setUsername(TEST_USERNAME)
+        .setPassword(TEST_PASSWORD)
+        .setComponentType(ComponentType.BROKER)
+        .setRoleType(RoleType.USER)
+        .build();
+
+    ZNRecord znRecord = AccessControlUserConfigUtils.toZNRecord(userConfig);
+
+    Assert.assertNotNull(znRecord, "ZNRecord should not be null");
+    Assert.assertEquals(znRecord.getId(), TEST_USERNAME, "ZNRecord ID should 
match username");
+    Assert.assertEquals(znRecord.getSimpleField(UserConfig.USERNAME_KEY), 
TEST_USERNAME, "Username should match");
+    Assert.assertEquals(znRecord.getSimpleField(UserConfig.PASSWORD_KEY), 
TEST_PASSWORD, "Password should match");
+    Assert.assertEquals(znRecord.getSimpleField(UserConfig.COMPONET_KEY), 
ComponentType.BROKER.toString(),
+        "Component type should match");
+    Assert.assertEquals(znRecord.getSimpleField(UserConfig.ROLE_KEY), 
RoleType.USER.toString(),
+        "Role type should match");
+    Assert.assertNull(znRecord.getListField(UserConfig.TABLES_KEY), "Tables 
should be null");
+    Assert.assertNull(znRecord.getListField(UserConfig.EXCLUDE_TABLES_KEY), 
"Exclude tables should be null");
+    Assert.assertNull(znRecord.getListField(UserConfig.PERMISSIONS_KEY), 
"Permissions should be null");
+    Assert.assertNull(znRecord.getSimpleField(UserConfig.RLS_FILTERS_KEY), 
"RLS filters should be null");
+  }
+
+  @Test
+  public void testToZNRecordWithTableList() throws JsonProcessingException {
+    List<String> tableList = Arrays.asList("table1", "table2", "table3");
+    UserConfig userConfig = new UserConfigBuilder()
+        .setUsername(TEST_USERNAME)
+        .setPassword(TEST_PASSWORD)
+        .setComponentType(ComponentType.CONTROLLER)
+        .setRoleType(RoleType.ADMIN)
+        .setTableList(tableList)
+        .build();
+
+    ZNRecord znRecord = AccessControlUserConfigUtils.toZNRecord(userConfig);
+
+    Assert.assertNotNull(znRecord.getListField(UserConfig.TABLES_KEY), "Tables 
should not be null");
+    Assert.assertEquals(znRecord.getListField(UserConfig.TABLES_KEY), 
tableList, "Table list should match");
+    Assert.assertEquals(znRecord.getListField(UserConfig.TABLES_KEY).size(), 
3, "Table list size should be 3");
+  }
+
+  @Test
+  public void testToZNRecordWithExcludeTableList() throws 
JsonProcessingException {
+    List<String> excludeTableList = Arrays.asList("excludeTable1", 
"excludeTable2");
+    UserConfig userConfig = new UserConfigBuilder()
+        .setUsername(TEST_USERNAME)
+        .setPassword(TEST_PASSWORD)
+        .setComponentType(ComponentType.SERVER)
+        .setRoleType(RoleType.USER)
+        .setExcludeTableList(excludeTableList)
+        .build();
+
+    ZNRecord znRecord = AccessControlUserConfigUtils.toZNRecord(userConfig);
+
+    Assert.assertNotNull(znRecord.getListField(UserConfig.EXCLUDE_TABLES_KEY), 
"Exclude tables should not be null");
+    Assert.assertEquals(znRecord.getListField(UserConfig.EXCLUDE_TABLES_KEY), 
excludeTableList,
+        "Exclude table list should match");
+    
Assert.assertEquals(znRecord.getListField(UserConfig.EXCLUDE_TABLES_KEY).size(),
 2,
+        "Exclude table list size should be 2");
+  }
+
+  @Test
+  public void testToZNRecordWithPermissionList() throws 
JsonProcessingException {
+    List<AccessType> permissionList = Arrays.asList(AccessType.READ, 
AccessType.CREATE, AccessType.UPDATE);
+    UserConfig userConfig = new UserConfigBuilder()
+        .setUsername(TEST_USERNAME)
+        .setPassword(TEST_PASSWORD)
+        .setComponentType(ComponentType.MINION)
+        .setRoleType(RoleType.ADMIN)
+        .setPermissionList(permissionList)
+        .build();
+
+    ZNRecord znRecord = AccessControlUserConfigUtils.toZNRecord(userConfig);
+
+    List<String> permissionListStr = 
znRecord.getListField(UserConfig.PERMISSIONS_KEY);
+    Assert.assertNotNull(permissionListStr, "Permissions should not be null");
+    Assert.assertEquals(permissionListStr.size(), 3, "Permission list size 
should be 3");
+    Assert.assertTrue(permissionListStr.contains("READ"), "Should contain READ 
permission");
+    Assert.assertTrue(permissionListStr.contains("CREATE"), "Should contain 
CREATE permission");
+    Assert.assertTrue(permissionListStr.contains("UPDATE"), "Should contain 
UPDATE permission");
+  }
+
+  @Test
+  public void testToZNRecordWithRlsFilters() throws IOException {
+    Map<String, List<String>> rlsFilters = new HashMap<>();
+    rlsFilters.put("table1", Arrays.asList("country='US'", 
"department='Engineering'"));
+    rlsFilters.put("table2", Arrays.asList("region='WEST'"));
+
+    UserConfig userConfig = new UserConfigBuilder()
+        .setUsername(TEST_USERNAME)
+        .setPassword(TEST_PASSWORD)
+        .setComponentType(ComponentType.BROKER)
+        .setRoleType(RoleType.USER)
+        .setRlsFilters(rlsFilters)
+        .build();
+
+    ZNRecord znRecord = AccessControlUserConfigUtils.toZNRecord(userConfig);
+
+    String rlsFiltersJson = 
znRecord.getSimpleField(UserConfig.RLS_FILTERS_KEY);
+    Assert.assertNotNull(rlsFiltersJson, "RLS filters should not be null");
+
+    // Deserialize and verify
+    Map<String, List<String>> deserializedFilters = JsonUtils.stringToObject(
+        rlsFiltersJson, new 
com.fasterxml.jackson.core.type.TypeReference<Map<String, List<String>>>() {
+        }
+    );
+    Assert.assertEquals(deserializedFilters.size(), 2, "RLS filters map size 
should be 2");
+    Assert.assertTrue(deserializedFilters.containsKey("table1"), "Should 
contain table1 filters");
+    Assert.assertTrue(deserializedFilters.containsKey("table2"), "Should 
contain table2 filters");
+    // Verify actual filter values
+    Assert.assertEquals(deserializedFilters.get("table1").get(0), 
"country='US'");
+    Assert.assertEquals(deserializedFilters.get("table1").get(1), 
"department='Engineering'");
+    Assert.assertEquals(deserializedFilters.get("table2").get(0), 
"region='WEST'");
+  }
+
+  @Test
+  public void testToZNRecordWithAllFields() throws JsonProcessingException {
+    List<String> tableList = Arrays.asList("table1", "table2");
+    List<String> excludeTableList = Arrays.asList("excludeTable1");
+    List<AccessType> permissionList = Arrays.asList(AccessType.READ, 
AccessType.UPDATE, AccessType.DELETE);
+    Map<String, List<String>> rlsFilters = new HashMap<>();
+    rlsFilters.put("table1", Arrays.asList("filter1", "filter2"));
+
+    UserConfig userConfig = new UserConfigBuilder()
+        .setUsername("adminUser")
+        .setPassword("adminPass123")
+        .setComponentType(ComponentType.PROXY)
+        .setRoleType(RoleType.ADMIN)
+        .setTableList(tableList)
+        .setExcludeTableList(excludeTableList)
+        .setPermissionList(permissionList)
+        .setRlsFilters(rlsFilters)
+        .build();
+
+    ZNRecord znRecord = AccessControlUserConfigUtils.toZNRecord(userConfig);
+
+    Assert.assertNotNull(znRecord, "ZNRecord should not be null");
+    Assert.assertEquals(znRecord.getId(), "adminUser", "ZNRecord ID should 
match username");
+    Assert.assertEquals(znRecord.getSimpleField(UserConfig.USERNAME_KEY), 
"adminUser", "Username should match");
+    Assert.assertEquals(znRecord.getSimpleField(UserConfig.PASSWORD_KEY), 
"adminPass123", "Password should match");
+    Assert.assertEquals(znRecord.getSimpleField(UserConfig.COMPONET_KEY), 
ComponentType.PROXY.toString(),
+        "Component type should match");
+    Assert.assertEquals(znRecord.getSimpleField(UserConfig.ROLE_KEY), 
RoleType.ADMIN.toString(),
+        "Role type should match");
+    Assert.assertEquals(znRecord.getListField(UserConfig.TABLES_KEY), 
tableList, "Table list should match");
+    Assert.assertEquals(znRecord.getListField(UserConfig.EXCLUDE_TABLES_KEY), 
excludeTableList,
+        "Exclude table list should match");
+    Assert.assertNotNull(znRecord.getListField(UserConfig.PERMISSIONS_KEY), 
"Permissions should not be null");
+    Assert.assertNotNull(znRecord.getSimpleField(UserConfig.RLS_FILTERS_KEY), 
"RLS filters should not be null");
+  }
+
+  @Test
+  public void testRoundTripConversionWithMandatoryFields() throws 
JsonProcessingException {
+    UserConfig originalConfig = new UserConfigBuilder()
+        .setUsername(TEST_USERNAME)
+        .setPassword(TEST_PASSWORD)
+        .setComponentType(ComponentType.BROKER)
+        .setRoleType(RoleType.USER)
+        .build();
+
+    ZNRecord znRecord = 
AccessControlUserConfigUtils.toZNRecord(originalConfig);
+    UserConfig reconstructedConfig = 
AccessControlUserConfigUtils.fromZNRecord(znRecord);
+
+    Assert.assertEquals(reconstructedConfig.getUserName(), 
originalConfig.getUserName(),
+        "Username should match after round-trip");
+    Assert.assertEquals(reconstructedConfig.getPassword(), 
originalConfig.getPassword(),
+        "Password should match after round-trip");
+    Assert.assertEquals(reconstructedConfig.getComponentType(), 
originalConfig.getComponentType(),
+        "Component type should match after round-trip");
+    Assert.assertEquals(reconstructedConfig.getRoleType(), 
originalConfig.getRoleType(),
+        "Role type should match after round-trip");
+  }
+
+  @Test
+  public void testRoundTripConversionWithAllFields() throws 
JsonProcessingException {
+    List<String> tableList = Arrays.asList("table1", "table2");
+    List<String> excludeTableList = Arrays.asList("excludeTable1");
+    List<AccessType> permissionList = Arrays.asList(AccessType.CREATE, 
AccessType.READ, AccessType.UPDATE,
+        AccessType.DELETE);
+    Map<String, List<String>> rlsFilters = new HashMap<>();
+    rlsFilters.put("table1", Arrays.asList("country='US'", 
"department='Engineering'"));
+    rlsFilters.put("table2", Arrays.asList("region='WEST'"));
+
+    UserConfig originalConfig = new UserConfigBuilder()
+        .setUsername("fullTestUser")
+        .setPassword("fullTestPassword")
+        .setComponentType(ComponentType.CONTROLLER)
+        .setRoleType(RoleType.ADMIN)
+        .setTableList(tableList)
+        .setExcludeTableList(excludeTableList)
+        .setPermissionList(permissionList)
+        .setRlsFilters(rlsFilters)
+        .build();
+
+    ZNRecord znRecord = 
AccessControlUserConfigUtils.toZNRecord(originalConfig);
+    UserConfig reconstructedConfig = 
AccessControlUserConfigUtils.fromZNRecord(znRecord);
+
+    Assert.assertEquals(reconstructedConfig.getUserName(), 
originalConfig.getUserName(),
+        "Username should match after round-trip");
+    Assert.assertEquals(reconstructedConfig.getPassword(), 
originalConfig.getPassword(),
+        "Password should match after round-trip");
+    Assert.assertEquals(reconstructedConfig.getComponentType(), 
originalConfig.getComponentType(),
+        "Component type should match after round-trip");
+    Assert.assertEquals(reconstructedConfig.getRoleType(), 
originalConfig.getRoleType(),
+        "Role type should match after round-trip");
+    Assert.assertEquals(reconstructedConfig.getTables(), 
originalConfig.getTables(),
+        "Tables should match after round-trip");
+    Assert.assertEquals(reconstructedConfig.getExcludeTables(), 
originalConfig.getExcludeTables(),
+        "Exclude tables should match after round-trip");
+    Assert.assertEquals(reconstructedConfig.getPermissios().size(), 
originalConfig.getPermissios().size(),

Review Comment:
   Multiple occurrences of 'getPermissios' should be corrected to 
'getPermissions'.
   ```suggestion
       Assert.assertEquals(reconstructedConfig.getPermissions().size(), 
originalConfig.getPermissions().size(),
   ```



##########
pinot-common/src/test/java/org/apache/pinot/common/utils/config/AccessControlUserConfigUtilsTest.java:
##########
@@ -0,0 +1,559 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.pinot.common.utils.config;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.helix.zookeeper.datamodel.ZNRecord;
+import org.apache.pinot.spi.config.user.AccessType;
+import org.apache.pinot.spi.config.user.ComponentType;
+import org.apache.pinot.spi.config.user.RoleType;
+import org.apache.pinot.spi.config.user.UserConfig;
+import org.apache.pinot.spi.utils.JsonUtils;
+import org.apache.pinot.spi.utils.builder.UserConfigBuilder;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+
+/**
+ * Tests for {@link AccessControlUserConfigUtils}
+ */
+public class AccessControlUserConfigUtilsTest {
+
+  private static final String TEST_USERNAME = "testUser";
+  private static final String TEST_PASSWORD = "testPassword";
+
+  @Test
+  public void testFromZNRecordWithMandatoryFieldsOnly() {
+    // Create ZNRecord with only mandatory fields
+    ZNRecord znRecord = new ZNRecord(TEST_USERNAME);
+    Map<String, String> simpleFields = new HashMap<>();
+    simpleFields.put(UserConfig.USERNAME_KEY, TEST_USERNAME);
+    simpleFields.put(UserConfig.PASSWORD_KEY, TEST_PASSWORD);
+    simpleFields.put(UserConfig.COMPONET_KEY, ComponentType.BROKER.toString());
+    simpleFields.put(UserConfig.ROLE_KEY, RoleType.USER.toString());
+    znRecord.setSimpleFields(simpleFields);
+
+    UserConfig userConfig = 
AccessControlUserConfigUtils.fromZNRecord(znRecord);
+
+    Assert.assertNotNull(userConfig, "UserConfig should not be null");
+    Assert.assertEquals(userConfig.getUserName(), TEST_USERNAME, "Username 
should match");
+    Assert.assertEquals(userConfig.getPassword(), TEST_PASSWORD, "Password 
should match");
+    Assert.assertEquals(userConfig.getComponentType(), ComponentType.BROKER, 
"Component type should match");
+    Assert.assertEquals(userConfig.getRoleType(), RoleType.USER, "Role type 
should match");
+    Assert.assertNull(userConfig.getTables(), "Tables should be null");
+    Assert.assertNull(userConfig.getExcludeTables(), "Exclude tables should be 
null");
+    Assert.assertNull(userConfig.getPermissios(), "Permissions should be 
null");
+    Assert.assertNull(userConfig.getRlsFilters(), "RLS filters should be 
null");
+  }
+
+  @Test
+  public void testFromZNRecordWithTableList() {
+    ZNRecord znRecord = new ZNRecord(TEST_USERNAME);
+    Map<String, String> simpleFields = new HashMap<>();
+    simpleFields.put(UserConfig.USERNAME_KEY, TEST_USERNAME);
+    simpleFields.put(UserConfig.PASSWORD_KEY, TEST_PASSWORD);
+    simpleFields.put(UserConfig.COMPONET_KEY, 
ComponentType.CONTROLLER.toString());
+    simpleFields.put(UserConfig.ROLE_KEY, RoleType.ADMIN.toString());
+    znRecord.setSimpleFields(simpleFields);
+
+    List<String> tableList = Arrays.asList("table1", "table2", "table3");
+    znRecord.setListField(UserConfig.TABLES_KEY, tableList);
+
+    UserConfig userConfig = 
AccessControlUserConfigUtils.fromZNRecord(znRecord);
+
+    Assert.assertNotNull(userConfig.getTables(), "Tables should not be null");
+    Assert.assertEquals(userConfig.getTables(), tableList, "Table list should 
match");
+    Assert.assertEquals(userConfig.getTables().size(), 3, "Table list size 
should be 3");
+  }
+
+  @Test
+  public void testFromZNRecordWithExcludeTableList() {
+    ZNRecord znRecord = new ZNRecord(TEST_USERNAME);
+    Map<String, String> simpleFields = new HashMap<>();
+    simpleFields.put(UserConfig.USERNAME_KEY, TEST_USERNAME);
+    simpleFields.put(UserConfig.PASSWORD_KEY, TEST_PASSWORD);
+    simpleFields.put(UserConfig.COMPONET_KEY, ComponentType.SERVER.toString());
+    simpleFields.put(UserConfig.ROLE_KEY, RoleType.USER.toString());
+    znRecord.setSimpleFields(simpleFields);
+
+    List<String> excludeTableList = Arrays.asList("excludeTable1", 
"excludeTable2");
+    znRecord.setListField(UserConfig.EXCLUDE_TABLES_KEY, excludeTableList);
+
+    UserConfig userConfig = 
AccessControlUserConfigUtils.fromZNRecord(znRecord);
+
+    Assert.assertNotNull(userConfig.getExcludeTables(), "Exclude tables should 
not be null");
+    Assert.assertEquals(userConfig.getExcludeTables(), excludeTableList, 
"Exclude table list should match");
+    Assert.assertEquals(userConfig.getExcludeTables().size(), 2, "Exclude 
table list size should be 2");
+  }
+
+  @Test
+  public void testFromZNRecordWithPermissionList() {
+    ZNRecord znRecord = new ZNRecord(TEST_USERNAME);
+    Map<String, String> simpleFields = new HashMap<>();
+    simpleFields.put(UserConfig.USERNAME_KEY, TEST_USERNAME);
+    simpleFields.put(UserConfig.PASSWORD_KEY, TEST_PASSWORD);
+    simpleFields.put(UserConfig.COMPONET_KEY, ComponentType.MINION.toString());
+    simpleFields.put(UserConfig.ROLE_KEY, RoleType.ADMIN.toString());
+    znRecord.setSimpleFields(simpleFields);
+
+    List<String> permissionListStr = Arrays.asList("READ", "CREATE", "UPDATE");
+    znRecord.setListField(UserConfig.PERMISSIONS_KEY, permissionListStr);
+
+    UserConfig userConfig = 
AccessControlUserConfigUtils.fromZNRecord(znRecord);
+
+    Assert.assertNotNull(userConfig.getPermissios(), "Permissions should not 
be null");
+    Assert.assertEquals(userConfig.getPermissios().size(), 3, "Permission list 
size should be 3");
+    Assert.assertTrue(userConfig.getPermissios().contains(AccessType.READ), 
"Should contain READ permission");
+    Assert.assertTrue(userConfig.getPermissios().contains(AccessType.CREATE), 
"Should contain CREATE permission");
+    Assert.assertTrue(userConfig.getPermissios().contains(AccessType.UPDATE), 
"Should contain UPDATE permission");
+  }
+
+  @Test
+  public void testFromZNRecordWithRlsFilters() throws JsonProcessingException {
+    ZNRecord znRecord = new ZNRecord(TEST_USERNAME);
+    Map<String, String> simpleFields = new HashMap<>();
+    simpleFields.put(UserConfig.USERNAME_KEY, TEST_USERNAME);
+    simpleFields.put(UserConfig.PASSWORD_KEY, TEST_PASSWORD);
+    simpleFields.put(UserConfig.COMPONET_KEY, ComponentType.BROKER.toString());
+    simpleFields.put(UserConfig.ROLE_KEY, RoleType.USER.toString());
+
+    Map<String, List<String>> rlsFilters = new HashMap<>();
+    rlsFilters.put("table1", Arrays.asList("country='US'", 
"department='Engineering'"));
+    rlsFilters.put("table2", Arrays.asList("region='WEST'"));
+    simpleFields.put(UserConfig.RLS_FILTERS_KEY, 
JsonUtils.objectToString(rlsFilters));
+
+    znRecord.setSimpleFields(simpleFields);
+
+    UserConfig userConfig = 
AccessControlUserConfigUtils.fromZNRecord(znRecord);
+
+    Assert.assertNotNull(userConfig.getRlsFilters(), "RLS filters should not 
be null");
+    Assert.assertEquals(userConfig.getRlsFilters().size(), 2, "RLS filters map 
size should be 2");
+    Assert.assertTrue(userConfig.getRlsFilters().containsKey("table1"), 
"Should contain table1 filters");
+    Assert.assertTrue(userConfig.getRlsFilters().containsKey("table2"), 
"Should contain table2 filters");
+    Assert.assertEquals(userConfig.getRlsFilters().get("table1").size(), 2, 
"table1 should have 2 filters");
+    Assert.assertEquals(userConfig.getRlsFilters().get("table2").size(), 1, 
"table2 should have 1 filter");
+    // Verify actual filter values
+    Assert.assertEquals(userConfig.getRlsFilters().get("table1").get(0), 
"country='US'");
+    Assert.assertEquals(userConfig.getRlsFilters().get("table1").get(1), 
"department='Engineering'");
+    Assert.assertEquals(userConfig.getRlsFilters().get("table2").get(0), 
"region='WEST'");
+  }
+
+  @Test
+  public void testFromZNRecordWithMalformedRlsFilters() {
+    ZNRecord znRecord = new ZNRecord(TEST_USERNAME);
+    Map<String, String> simpleFields = new HashMap<>();
+    simpleFields.put(UserConfig.USERNAME_KEY, TEST_USERNAME);
+    simpleFields.put(UserConfig.PASSWORD_KEY, TEST_PASSWORD);
+    simpleFields.put(UserConfig.COMPONET_KEY, ComponentType.BROKER.toString());
+    simpleFields.put(UserConfig.ROLE_KEY, RoleType.USER.toString());
+    simpleFields.put(UserConfig.RLS_FILTERS_KEY, "invalid-json-{malformed");
+    znRecord.setSimpleFields(simpleFields);
+
+    // Should not throw exception, but log error and continue
+    UserConfig userConfig = 
AccessControlUserConfigUtils.fromZNRecord(znRecord);
+
+    Assert.assertNotNull(userConfig, "UserConfig should not be null");
+    Assert.assertNull(userConfig.getRlsFilters(), "RLS filters should be null 
due to malformed JSON");
+  }
+
+  @Test
+  public void testFromZNRecordWithAllFields() throws JsonProcessingException {
+    ZNRecord znRecord = new ZNRecord(TEST_USERNAME);
+    Map<String, String> simpleFields = new HashMap<>();
+    simpleFields.put(UserConfig.USERNAME_KEY, "adminUser");
+    simpleFields.put(UserConfig.PASSWORD_KEY, "adminPass123");
+    simpleFields.put(UserConfig.COMPONET_KEY, ComponentType.PROXY.toString());
+    simpleFields.put(UserConfig.ROLE_KEY, RoleType.ADMIN.toString());
+
+    Map<String, List<String>> rlsFilters = new HashMap<>();
+    rlsFilters.put("table1", Arrays.asList("filter1", "filter2"));
+    simpleFields.put(UserConfig.RLS_FILTERS_KEY, 
JsonUtils.objectToString(rlsFilters));
+    znRecord.setSimpleFields(simpleFields);
+
+    List<String> tableList = Arrays.asList("table1", "table2");
+    List<String> excludeTableList = Arrays.asList("excludeTable1");
+    List<String> permissionListStr = Arrays.asList("READ", "UPDATE", "DELETE");
+
+    znRecord.setListField(UserConfig.TABLES_KEY, tableList);
+    znRecord.setListField(UserConfig.EXCLUDE_TABLES_KEY, excludeTableList);
+    znRecord.setListField(UserConfig.PERMISSIONS_KEY, permissionListStr);
+
+    UserConfig userConfig = 
AccessControlUserConfigUtils.fromZNRecord(znRecord);
+
+    Assert.assertNotNull(userConfig, "UserConfig should not be null");
+    Assert.assertEquals(userConfig.getUserName(), "adminUser", "Username 
should match");
+    Assert.assertEquals(userConfig.getPassword(), "adminPass123", "Password 
should match");
+    Assert.assertEquals(userConfig.getComponentType(), ComponentType.PROXY, 
"Component type should match");
+    Assert.assertEquals(userConfig.getRoleType(), RoleType.ADMIN, "Role type 
should match");
+    Assert.assertEquals(userConfig.getTables(), tableList, "Table list should 
match");
+    Assert.assertEquals(userConfig.getExcludeTables(), excludeTableList, 
"Exclude table list should match");
+    Assert.assertEquals(userConfig.getPermissios().size(), 3, "Permission list 
size should match");
+    Assert.assertNotNull(userConfig.getRlsFilters(), "RLS filters should not 
be null");
+  }
+
+  @Test
+  public void testToZNRecordWithMandatoryFieldsOnly() throws 
JsonProcessingException {
+    UserConfig userConfig = new UserConfigBuilder()
+        .setUsername(TEST_USERNAME)
+        .setPassword(TEST_PASSWORD)
+        .setComponentType(ComponentType.BROKER)
+        .setRoleType(RoleType.USER)
+        .build();
+
+    ZNRecord znRecord = AccessControlUserConfigUtils.toZNRecord(userConfig);
+
+    Assert.assertNotNull(znRecord, "ZNRecord should not be null");
+    Assert.assertEquals(znRecord.getId(), TEST_USERNAME, "ZNRecord ID should 
match username");
+    Assert.assertEquals(znRecord.getSimpleField(UserConfig.USERNAME_KEY), 
TEST_USERNAME, "Username should match");
+    Assert.assertEquals(znRecord.getSimpleField(UserConfig.PASSWORD_KEY), 
TEST_PASSWORD, "Password should match");
+    Assert.assertEquals(znRecord.getSimpleField(UserConfig.COMPONET_KEY), 
ComponentType.BROKER.toString(),
+        "Component type should match");
+    Assert.assertEquals(znRecord.getSimpleField(UserConfig.ROLE_KEY), 
RoleType.USER.toString(),
+        "Role type should match");
+    Assert.assertNull(znRecord.getListField(UserConfig.TABLES_KEY), "Tables 
should be null");
+    Assert.assertNull(znRecord.getListField(UserConfig.EXCLUDE_TABLES_KEY), 
"Exclude tables should be null");
+    Assert.assertNull(znRecord.getListField(UserConfig.PERMISSIONS_KEY), 
"Permissions should be null");
+    Assert.assertNull(znRecord.getSimpleField(UserConfig.RLS_FILTERS_KEY), 
"RLS filters should be null");
+  }
+
+  @Test
+  public void testToZNRecordWithTableList() throws JsonProcessingException {
+    List<String> tableList = Arrays.asList("table1", "table2", "table3");
+    UserConfig userConfig = new UserConfigBuilder()
+        .setUsername(TEST_USERNAME)
+        .setPassword(TEST_PASSWORD)
+        .setComponentType(ComponentType.CONTROLLER)
+        .setRoleType(RoleType.ADMIN)
+        .setTableList(tableList)
+        .build();
+
+    ZNRecord znRecord = AccessControlUserConfigUtils.toZNRecord(userConfig);
+
+    Assert.assertNotNull(znRecord.getListField(UserConfig.TABLES_KEY), "Tables 
should not be null");
+    Assert.assertEquals(znRecord.getListField(UserConfig.TABLES_KEY), 
tableList, "Table list should match");
+    Assert.assertEquals(znRecord.getListField(UserConfig.TABLES_KEY).size(), 
3, "Table list size should be 3");
+  }
+
+  @Test
+  public void testToZNRecordWithExcludeTableList() throws 
JsonProcessingException {
+    List<String> excludeTableList = Arrays.asList("excludeTable1", 
"excludeTable2");
+    UserConfig userConfig = new UserConfigBuilder()
+        .setUsername(TEST_USERNAME)
+        .setPassword(TEST_PASSWORD)
+        .setComponentType(ComponentType.SERVER)
+        .setRoleType(RoleType.USER)
+        .setExcludeTableList(excludeTableList)
+        .build();
+
+    ZNRecord znRecord = AccessControlUserConfigUtils.toZNRecord(userConfig);
+
+    Assert.assertNotNull(znRecord.getListField(UserConfig.EXCLUDE_TABLES_KEY), 
"Exclude tables should not be null");
+    Assert.assertEquals(znRecord.getListField(UserConfig.EXCLUDE_TABLES_KEY), 
excludeTableList,
+        "Exclude table list should match");
+    
Assert.assertEquals(znRecord.getListField(UserConfig.EXCLUDE_TABLES_KEY).size(),
 2,
+        "Exclude table list size should be 2");
+  }
+
+  @Test
+  public void testToZNRecordWithPermissionList() throws 
JsonProcessingException {
+    List<AccessType> permissionList = Arrays.asList(AccessType.READ, 
AccessType.CREATE, AccessType.UPDATE);
+    UserConfig userConfig = new UserConfigBuilder()
+        .setUsername(TEST_USERNAME)
+        .setPassword(TEST_PASSWORD)
+        .setComponentType(ComponentType.MINION)
+        .setRoleType(RoleType.ADMIN)
+        .setPermissionList(permissionList)
+        .build();
+
+    ZNRecord znRecord = AccessControlUserConfigUtils.toZNRecord(userConfig);
+
+    List<String> permissionListStr = 
znRecord.getListField(UserConfig.PERMISSIONS_KEY);
+    Assert.assertNotNull(permissionListStr, "Permissions should not be null");
+    Assert.assertEquals(permissionListStr.size(), 3, "Permission list size 
should be 3");
+    Assert.assertTrue(permissionListStr.contains("READ"), "Should contain READ 
permission");
+    Assert.assertTrue(permissionListStr.contains("CREATE"), "Should contain 
CREATE permission");
+    Assert.assertTrue(permissionListStr.contains("UPDATE"), "Should contain 
UPDATE permission");
+  }
+
+  @Test
+  public void testToZNRecordWithRlsFilters() throws IOException {
+    Map<String, List<String>> rlsFilters = new HashMap<>();
+    rlsFilters.put("table1", Arrays.asList("country='US'", 
"department='Engineering'"));
+    rlsFilters.put("table2", Arrays.asList("region='WEST'"));
+
+    UserConfig userConfig = new UserConfigBuilder()
+        .setUsername(TEST_USERNAME)
+        .setPassword(TEST_PASSWORD)
+        .setComponentType(ComponentType.BROKER)
+        .setRoleType(RoleType.USER)
+        .setRlsFilters(rlsFilters)
+        .build();
+
+    ZNRecord znRecord = AccessControlUserConfigUtils.toZNRecord(userConfig);
+
+    String rlsFiltersJson = 
znRecord.getSimpleField(UserConfig.RLS_FILTERS_KEY);
+    Assert.assertNotNull(rlsFiltersJson, "RLS filters should not be null");
+
+    // Deserialize and verify
+    Map<String, List<String>> deserializedFilters = JsonUtils.stringToObject(
+        rlsFiltersJson, new 
com.fasterxml.jackson.core.type.TypeReference<Map<String, List<String>>>() {
+        }
+    );
+    Assert.assertEquals(deserializedFilters.size(), 2, "RLS filters map size 
should be 2");
+    Assert.assertTrue(deserializedFilters.containsKey("table1"), "Should 
contain table1 filters");
+    Assert.assertTrue(deserializedFilters.containsKey("table2"), "Should 
contain table2 filters");
+    // Verify actual filter values
+    Assert.assertEquals(deserializedFilters.get("table1").get(0), 
"country='US'");
+    Assert.assertEquals(deserializedFilters.get("table1").get(1), 
"department='Engineering'");
+    Assert.assertEquals(deserializedFilters.get("table2").get(0), 
"region='WEST'");
+  }
+
+  @Test
+  public void testToZNRecordWithAllFields() throws JsonProcessingException {
+    List<String> tableList = Arrays.asList("table1", "table2");
+    List<String> excludeTableList = Arrays.asList("excludeTable1");
+    List<AccessType> permissionList = Arrays.asList(AccessType.READ, 
AccessType.UPDATE, AccessType.DELETE);
+    Map<String, List<String>> rlsFilters = new HashMap<>();
+    rlsFilters.put("table1", Arrays.asList("filter1", "filter2"));
+
+    UserConfig userConfig = new UserConfigBuilder()
+        .setUsername("adminUser")
+        .setPassword("adminPass123")
+        .setComponentType(ComponentType.PROXY)
+        .setRoleType(RoleType.ADMIN)
+        .setTableList(tableList)
+        .setExcludeTableList(excludeTableList)
+        .setPermissionList(permissionList)
+        .setRlsFilters(rlsFilters)
+        .build();
+
+    ZNRecord znRecord = AccessControlUserConfigUtils.toZNRecord(userConfig);
+
+    Assert.assertNotNull(znRecord, "ZNRecord should not be null");
+    Assert.assertEquals(znRecord.getId(), "adminUser", "ZNRecord ID should 
match username");
+    Assert.assertEquals(znRecord.getSimpleField(UserConfig.USERNAME_KEY), 
"adminUser", "Username should match");
+    Assert.assertEquals(znRecord.getSimpleField(UserConfig.PASSWORD_KEY), 
"adminPass123", "Password should match");
+    Assert.assertEquals(znRecord.getSimpleField(UserConfig.COMPONET_KEY), 
ComponentType.PROXY.toString(),
+        "Component type should match");
+    Assert.assertEquals(znRecord.getSimpleField(UserConfig.ROLE_KEY), 
RoleType.ADMIN.toString(),
+        "Role type should match");
+    Assert.assertEquals(znRecord.getListField(UserConfig.TABLES_KEY), 
tableList, "Table list should match");
+    Assert.assertEquals(znRecord.getListField(UserConfig.EXCLUDE_TABLES_KEY), 
excludeTableList,
+        "Exclude table list should match");
+    Assert.assertNotNull(znRecord.getListField(UserConfig.PERMISSIONS_KEY), 
"Permissions should not be null");
+    Assert.assertNotNull(znRecord.getSimpleField(UserConfig.RLS_FILTERS_KEY), 
"RLS filters should not be null");
+  }
+
+  @Test
+  public void testRoundTripConversionWithMandatoryFields() throws 
JsonProcessingException {
+    UserConfig originalConfig = new UserConfigBuilder()
+        .setUsername(TEST_USERNAME)
+        .setPassword(TEST_PASSWORD)
+        .setComponentType(ComponentType.BROKER)
+        .setRoleType(RoleType.USER)
+        .build();
+
+    ZNRecord znRecord = 
AccessControlUserConfigUtils.toZNRecord(originalConfig);
+    UserConfig reconstructedConfig = 
AccessControlUserConfigUtils.fromZNRecord(znRecord);
+
+    Assert.assertEquals(reconstructedConfig.getUserName(), 
originalConfig.getUserName(),
+        "Username should match after round-trip");
+    Assert.assertEquals(reconstructedConfig.getPassword(), 
originalConfig.getPassword(),
+        "Password should match after round-trip");
+    Assert.assertEquals(reconstructedConfig.getComponentType(), 
originalConfig.getComponentType(),
+        "Component type should match after round-trip");
+    Assert.assertEquals(reconstructedConfig.getRoleType(), 
originalConfig.getRoleType(),
+        "Role type should match after round-trip");
+  }
+
+  @Test
+  public void testRoundTripConversionWithAllFields() throws 
JsonProcessingException {
+    List<String> tableList = Arrays.asList("table1", "table2");
+    List<String> excludeTableList = Arrays.asList("excludeTable1");
+    List<AccessType> permissionList = Arrays.asList(AccessType.CREATE, 
AccessType.READ, AccessType.UPDATE,
+        AccessType.DELETE);
+    Map<String, List<String>> rlsFilters = new HashMap<>();
+    rlsFilters.put("table1", Arrays.asList("country='US'", 
"department='Engineering'"));
+    rlsFilters.put("table2", Arrays.asList("region='WEST'"));
+
+    UserConfig originalConfig = new UserConfigBuilder()
+        .setUsername("fullTestUser")
+        .setPassword("fullTestPassword")
+        .setComponentType(ComponentType.CONTROLLER)
+        .setRoleType(RoleType.ADMIN)
+        .setTableList(tableList)
+        .setExcludeTableList(excludeTableList)
+        .setPermissionList(permissionList)
+        .setRlsFilters(rlsFilters)
+        .build();
+
+    ZNRecord znRecord = 
AccessControlUserConfigUtils.toZNRecord(originalConfig);
+    UserConfig reconstructedConfig = 
AccessControlUserConfigUtils.fromZNRecord(znRecord);
+
+    Assert.assertEquals(reconstructedConfig.getUserName(), 
originalConfig.getUserName(),
+        "Username should match after round-trip");
+    Assert.assertEquals(reconstructedConfig.getPassword(), 
originalConfig.getPassword(),
+        "Password should match after round-trip");
+    Assert.assertEquals(reconstructedConfig.getComponentType(), 
originalConfig.getComponentType(),
+        "Component type should match after round-trip");
+    Assert.assertEquals(reconstructedConfig.getRoleType(), 
originalConfig.getRoleType(),
+        "Role type should match after round-trip");
+    Assert.assertEquals(reconstructedConfig.getTables(), 
originalConfig.getTables(),
+        "Tables should match after round-trip");
+    Assert.assertEquals(reconstructedConfig.getExcludeTables(), 
originalConfig.getExcludeTables(),
+        "Exclude tables should match after round-trip");
+    Assert.assertEquals(reconstructedConfig.getPermissios().size(), 
originalConfig.getPermissios().size(),
+        "Permissions size should match after round-trip");
+    Assert.assertEquals(reconstructedConfig.getRlsFilters().size(), 
originalConfig.getRlsFilters().size(),
+        "RLS filters size should match after round-trip");
+    Assert.assertEquals(reconstructedConfig.getRlsFilters().get("table1"),
+        originalConfig.getRlsFilters().get("table1"), "RLS filters for table1 
should match after round-trip");
+    Assert.assertEquals(reconstructedConfig.getRlsFilters().get("table2"),
+        originalConfig.getRlsFilters().get("table2"), "RLS filters for table2 
should match after round-trip");
+    // Verify actual filter values
+    
Assert.assertEquals(reconstructedConfig.getRlsFilters().get("table1").get(0), 
"country='US'");
+    
Assert.assertEquals(reconstructedConfig.getRlsFilters().get("table1").get(1), 
"department='Engineering'");
+    
Assert.assertEquals(reconstructedConfig.getRlsFilters().get("table2").get(0), 
"region='WEST'");
+  }
+
+  @Test
+  public void testDifferentComponentTypes() throws JsonProcessingException {
+    ComponentType[] componentTypes = {
+        ComponentType.CONTROLLER, ComponentType.BROKER, ComponentType.SERVER,
+        ComponentType.MINION, ComponentType.PROXY
+    };
+
+    for (ComponentType componentType : componentTypes) {
+      UserConfig userConfig = new UserConfigBuilder()
+          .setUsername(TEST_USERNAME)
+          .setPassword(TEST_PASSWORD)
+          .setComponentType(componentType)
+          .setRoleType(RoleType.USER)
+          .build();
+
+      ZNRecord znRecord = AccessControlUserConfigUtils.toZNRecord(userConfig);
+      UserConfig reconstructedConfig = 
AccessControlUserConfigUtils.fromZNRecord(znRecord);
+
+      Assert.assertEquals(reconstructedConfig.getComponentType(), 
componentType,
+          "Component type should match for " + componentType);
+    }
+  }
+
+  @Test
+  public void testDifferentRoleTypes() throws JsonProcessingException {
+    RoleType[] roleTypes = {RoleType.ADMIN, RoleType.USER};
+
+    for (RoleType roleType : roleTypes) {
+      UserConfig userConfig = new UserConfigBuilder()
+          .setUsername(TEST_USERNAME)
+          .setPassword(TEST_PASSWORD)
+          .setComponentType(ComponentType.BROKER)
+          .setRoleType(roleType)
+          .build();
+
+      ZNRecord znRecord = AccessControlUserConfigUtils.toZNRecord(userConfig);
+      UserConfig reconstructedConfig = 
AccessControlUserConfigUtils.fromZNRecord(znRecord);
+
+      Assert.assertEquals(reconstructedConfig.getRoleType(), roleType, "Role 
type should match for " + roleType);
+    }
+  }
+
+  @Test
+  public void testAllAccessTypes() throws JsonProcessingException {
+    List<AccessType> allPermissions = Arrays.asList(
+        AccessType.CREATE, AccessType.READ, AccessType.UPDATE, 
AccessType.DELETE
+    );
+
+    UserConfig userConfig = new UserConfigBuilder()
+        .setUsername(TEST_USERNAME)
+        .setPassword(TEST_PASSWORD)
+        .setComponentType(ComponentType.BROKER)
+        .setRoleType(RoleType.ADMIN)
+        .setPermissionList(allPermissions)
+        .build();
+
+    ZNRecord znRecord = AccessControlUserConfigUtils.toZNRecord(userConfig);
+    UserConfig reconstructedConfig = 
AccessControlUserConfigUtils.fromZNRecord(znRecord);
+
+    Assert.assertEquals(reconstructedConfig.getPermissios().size(), 4, "Should 
have all 4 access types");
+    
Assert.assertTrue(reconstructedConfig.getPermissios().contains(AccessType.CREATE),
 "Should contain CREATE");
+    
Assert.assertTrue(reconstructedConfig.getPermissios().contains(AccessType.READ),
 "Should contain READ");
+    
Assert.assertTrue(reconstructedConfig.getPermissios().contains(AccessType.UPDATE),
 "Should contain UPDATE");
+    
Assert.assertTrue(reconstructedConfig.getPermissios().contains(AccessType.DELETE),
 "Should contain DELETE");

Review Comment:
   Multiple occurrences of 'getPermissios' should be corrected to 
'getPermissions'.
   ```suggestion
       Assert.assertEquals(reconstructedConfig.getPermissions().size(), 4, 
"Should have all 4 access types");
       
Assert.assertTrue(reconstructedConfig.getPermissions().contains(AccessType.CREATE),
 "Should contain CREATE");
       
Assert.assertTrue(reconstructedConfig.getPermissions().contains(AccessType.READ),
 "Should contain READ");
       
Assert.assertTrue(reconstructedConfig.getPermissions().contains(AccessType.UPDATE),
 "Should contain UPDATE");
       
Assert.assertTrue(reconstructedConfig.getPermissions().contains(AccessType.DELETE),
 "Should contain DELETE");
   ```



##########
pinot-common/src/test/java/org/apache/pinot/common/utils/config/AccessControlUserConfigUtilsTest.java:
##########
@@ -0,0 +1,559 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.pinot.common.utils.config;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.helix.zookeeper.datamodel.ZNRecord;
+import org.apache.pinot.spi.config.user.AccessType;
+import org.apache.pinot.spi.config.user.ComponentType;
+import org.apache.pinot.spi.config.user.RoleType;
+import org.apache.pinot.spi.config.user.UserConfig;
+import org.apache.pinot.spi.utils.JsonUtils;
+import org.apache.pinot.spi.utils.builder.UserConfigBuilder;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+
+/**
+ * Tests for {@link AccessControlUserConfigUtils}
+ */
+public class AccessControlUserConfigUtilsTest {
+
+  private static final String TEST_USERNAME = "testUser";
+  private static final String TEST_PASSWORD = "testPassword";
+
+  @Test
+  public void testFromZNRecordWithMandatoryFieldsOnly() {
+    // Create ZNRecord with only mandatory fields
+    ZNRecord znRecord = new ZNRecord(TEST_USERNAME);
+    Map<String, String> simpleFields = new HashMap<>();
+    simpleFields.put(UserConfig.USERNAME_KEY, TEST_USERNAME);
+    simpleFields.put(UserConfig.PASSWORD_KEY, TEST_PASSWORD);
+    simpleFields.put(UserConfig.COMPONET_KEY, ComponentType.BROKER.toString());
+    simpleFields.put(UserConfig.ROLE_KEY, RoleType.USER.toString());
+    znRecord.setSimpleFields(simpleFields);
+
+    UserConfig userConfig = 
AccessControlUserConfigUtils.fromZNRecord(znRecord);
+
+    Assert.assertNotNull(userConfig, "UserConfig should not be null");
+    Assert.assertEquals(userConfig.getUserName(), TEST_USERNAME, "Username 
should match");
+    Assert.assertEquals(userConfig.getPassword(), TEST_PASSWORD, "Password 
should match");
+    Assert.assertEquals(userConfig.getComponentType(), ComponentType.BROKER, 
"Component type should match");
+    Assert.assertEquals(userConfig.getRoleType(), RoleType.USER, "Role type 
should match");
+    Assert.assertNull(userConfig.getTables(), "Tables should be null");
+    Assert.assertNull(userConfig.getExcludeTables(), "Exclude tables should be 
null");
+    Assert.assertNull(userConfig.getPermissios(), "Permissions should be 
null");
+    Assert.assertNull(userConfig.getRlsFilters(), "RLS filters should be 
null");
+  }
+
+  @Test
+  public void testFromZNRecordWithTableList() {
+    ZNRecord znRecord = new ZNRecord(TEST_USERNAME);
+    Map<String, String> simpleFields = new HashMap<>();
+    simpleFields.put(UserConfig.USERNAME_KEY, TEST_USERNAME);
+    simpleFields.put(UserConfig.PASSWORD_KEY, TEST_PASSWORD);
+    simpleFields.put(UserConfig.COMPONET_KEY, 
ComponentType.CONTROLLER.toString());
+    simpleFields.put(UserConfig.ROLE_KEY, RoleType.ADMIN.toString());
+    znRecord.setSimpleFields(simpleFields);
+
+    List<String> tableList = Arrays.asList("table1", "table2", "table3");
+    znRecord.setListField(UserConfig.TABLES_KEY, tableList);
+
+    UserConfig userConfig = 
AccessControlUserConfigUtils.fromZNRecord(znRecord);
+
+    Assert.assertNotNull(userConfig.getTables(), "Tables should not be null");
+    Assert.assertEquals(userConfig.getTables(), tableList, "Table list should 
match");
+    Assert.assertEquals(userConfig.getTables().size(), 3, "Table list size 
should be 3");
+  }
+
+  @Test
+  public void testFromZNRecordWithExcludeTableList() {
+    ZNRecord znRecord = new ZNRecord(TEST_USERNAME);
+    Map<String, String> simpleFields = new HashMap<>();
+    simpleFields.put(UserConfig.USERNAME_KEY, TEST_USERNAME);
+    simpleFields.put(UserConfig.PASSWORD_KEY, TEST_PASSWORD);
+    simpleFields.put(UserConfig.COMPONET_KEY, ComponentType.SERVER.toString());
+    simpleFields.put(UserConfig.ROLE_KEY, RoleType.USER.toString());
+    znRecord.setSimpleFields(simpleFields);
+
+    List<String> excludeTableList = Arrays.asList("excludeTable1", 
"excludeTable2");
+    znRecord.setListField(UserConfig.EXCLUDE_TABLES_KEY, excludeTableList);
+
+    UserConfig userConfig = 
AccessControlUserConfigUtils.fromZNRecord(znRecord);
+
+    Assert.assertNotNull(userConfig.getExcludeTables(), "Exclude tables should 
not be null");
+    Assert.assertEquals(userConfig.getExcludeTables(), excludeTableList, 
"Exclude table list should match");
+    Assert.assertEquals(userConfig.getExcludeTables().size(), 2, "Exclude 
table list size should be 2");
+  }
+
+  @Test
+  public void testFromZNRecordWithPermissionList() {
+    ZNRecord znRecord = new ZNRecord(TEST_USERNAME);
+    Map<String, String> simpleFields = new HashMap<>();
+    simpleFields.put(UserConfig.USERNAME_KEY, TEST_USERNAME);
+    simpleFields.put(UserConfig.PASSWORD_KEY, TEST_PASSWORD);
+    simpleFields.put(UserConfig.COMPONET_KEY, ComponentType.MINION.toString());
+    simpleFields.put(UserConfig.ROLE_KEY, RoleType.ADMIN.toString());
+    znRecord.setSimpleFields(simpleFields);
+
+    List<String> permissionListStr = Arrays.asList("READ", "CREATE", "UPDATE");
+    znRecord.setListField(UserConfig.PERMISSIONS_KEY, permissionListStr);
+
+    UserConfig userConfig = 
AccessControlUserConfigUtils.fromZNRecord(znRecord);
+
+    Assert.assertNotNull(userConfig.getPermissios(), "Permissions should not 
be null");
+    Assert.assertEquals(userConfig.getPermissios().size(), 3, "Permission list 
size should be 3");
+    Assert.assertTrue(userConfig.getPermissios().contains(AccessType.READ), 
"Should contain READ permission");
+    Assert.assertTrue(userConfig.getPermissios().contains(AccessType.CREATE), 
"Should contain CREATE permission");
+    Assert.assertTrue(userConfig.getPermissios().contains(AccessType.UPDATE), 
"Should contain UPDATE permission");
+  }
+
+  @Test
+  public void testFromZNRecordWithRlsFilters() throws JsonProcessingException {
+    ZNRecord znRecord = new ZNRecord(TEST_USERNAME);
+    Map<String, String> simpleFields = new HashMap<>();
+    simpleFields.put(UserConfig.USERNAME_KEY, TEST_USERNAME);
+    simpleFields.put(UserConfig.PASSWORD_KEY, TEST_PASSWORD);
+    simpleFields.put(UserConfig.COMPONET_KEY, ComponentType.BROKER.toString());
+    simpleFields.put(UserConfig.ROLE_KEY, RoleType.USER.toString());
+
+    Map<String, List<String>> rlsFilters = new HashMap<>();
+    rlsFilters.put("table1", Arrays.asList("country='US'", 
"department='Engineering'"));
+    rlsFilters.put("table2", Arrays.asList("region='WEST'"));
+    simpleFields.put(UserConfig.RLS_FILTERS_KEY, 
JsonUtils.objectToString(rlsFilters));
+
+    znRecord.setSimpleFields(simpleFields);
+
+    UserConfig userConfig = 
AccessControlUserConfigUtils.fromZNRecord(znRecord);
+
+    Assert.assertNotNull(userConfig.getRlsFilters(), "RLS filters should not 
be null");
+    Assert.assertEquals(userConfig.getRlsFilters().size(), 2, "RLS filters map 
size should be 2");
+    Assert.assertTrue(userConfig.getRlsFilters().containsKey("table1"), 
"Should contain table1 filters");
+    Assert.assertTrue(userConfig.getRlsFilters().containsKey("table2"), 
"Should contain table2 filters");
+    Assert.assertEquals(userConfig.getRlsFilters().get("table1").size(), 2, 
"table1 should have 2 filters");
+    Assert.assertEquals(userConfig.getRlsFilters().get("table2").size(), 1, 
"table2 should have 1 filter");
+    // Verify actual filter values
+    Assert.assertEquals(userConfig.getRlsFilters().get("table1").get(0), 
"country='US'");
+    Assert.assertEquals(userConfig.getRlsFilters().get("table1").get(1), 
"department='Engineering'");
+    Assert.assertEquals(userConfig.getRlsFilters().get("table2").get(0), 
"region='WEST'");
+  }
+
+  @Test
+  public void testFromZNRecordWithMalformedRlsFilters() {
+    ZNRecord znRecord = new ZNRecord(TEST_USERNAME);
+    Map<String, String> simpleFields = new HashMap<>();
+    simpleFields.put(UserConfig.USERNAME_KEY, TEST_USERNAME);
+    simpleFields.put(UserConfig.PASSWORD_KEY, TEST_PASSWORD);
+    simpleFields.put(UserConfig.COMPONET_KEY, ComponentType.BROKER.toString());
+    simpleFields.put(UserConfig.ROLE_KEY, RoleType.USER.toString());
+    simpleFields.put(UserConfig.RLS_FILTERS_KEY, "invalid-json-{malformed");
+    znRecord.setSimpleFields(simpleFields);
+
+    // Should not throw exception, but log error and continue
+    UserConfig userConfig = 
AccessControlUserConfigUtils.fromZNRecord(znRecord);
+
+    Assert.assertNotNull(userConfig, "UserConfig should not be null");
+    Assert.assertNull(userConfig.getRlsFilters(), "RLS filters should be null 
due to malformed JSON");
+  }
+
+  @Test
+  public void testFromZNRecordWithAllFields() throws JsonProcessingException {
+    ZNRecord znRecord = new ZNRecord(TEST_USERNAME);
+    Map<String, String> simpleFields = new HashMap<>();
+    simpleFields.put(UserConfig.USERNAME_KEY, "adminUser");
+    simpleFields.put(UserConfig.PASSWORD_KEY, "adminPass123");
+    simpleFields.put(UserConfig.COMPONET_KEY, ComponentType.PROXY.toString());
+    simpleFields.put(UserConfig.ROLE_KEY, RoleType.ADMIN.toString());
+
+    Map<String, List<String>> rlsFilters = new HashMap<>();
+    rlsFilters.put("table1", Arrays.asList("filter1", "filter2"));
+    simpleFields.put(UserConfig.RLS_FILTERS_KEY, 
JsonUtils.objectToString(rlsFilters));
+    znRecord.setSimpleFields(simpleFields);
+
+    List<String> tableList = Arrays.asList("table1", "table2");
+    List<String> excludeTableList = Arrays.asList("excludeTable1");
+    List<String> permissionListStr = Arrays.asList("READ", "UPDATE", "DELETE");
+
+    znRecord.setListField(UserConfig.TABLES_KEY, tableList);
+    znRecord.setListField(UserConfig.EXCLUDE_TABLES_KEY, excludeTableList);
+    znRecord.setListField(UserConfig.PERMISSIONS_KEY, permissionListStr);
+
+    UserConfig userConfig = 
AccessControlUserConfigUtils.fromZNRecord(znRecord);
+
+    Assert.assertNotNull(userConfig, "UserConfig should not be null");
+    Assert.assertEquals(userConfig.getUserName(), "adminUser", "Username 
should match");
+    Assert.assertEquals(userConfig.getPassword(), "adminPass123", "Password 
should match");
+    Assert.assertEquals(userConfig.getComponentType(), ComponentType.PROXY, 
"Component type should match");
+    Assert.assertEquals(userConfig.getRoleType(), RoleType.ADMIN, "Role type 
should match");
+    Assert.assertEquals(userConfig.getTables(), tableList, "Table list should 
match");
+    Assert.assertEquals(userConfig.getExcludeTables(), excludeTableList, 
"Exclude table list should match");
+    Assert.assertEquals(userConfig.getPermissios().size(), 3, "Permission list 
size should match");

Review Comment:
   Corrected spelling of 'getPermissios' to 'getPermissions'.
   ```suggestion
       Assert.assertEquals(userConfig.getPermissions().size(), 3, "Permission 
list size should match");
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to