SENTRY-2281: list_privileges_by_user() fails with a JDODetachedFieldAccessException (Arjun Mishra, reviewed by Sergio Pena, Na Li)
diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/persistent/SentryStore.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/persistent/SentryStore.java
index 29c2176..d8ab1fc 100644
--- a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/persistent/SentryStore.java
+++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/persistent/SentryStore.java
@@ -1907,6 +1907,7 @@
               pm -> {
                 Query query = pm.newQuery(MSentryPrivilege.class);
                 QueryParamBuilder paramBuilder = QueryParamBuilder.newQueryParamBuilder();
+
                 if (entityNames == null || entityNames.isEmpty()) {
                   if (entityType == SentryEntityType.ROLE) {
                     paramBuilder.addString("!roles.isEmpty()");
@@ -1945,9 +1946,17 @@
                   // if no server, then return empty result
                   return Collections.emptyList();
                 }
-                FetchGroup grp = pm.getFetchGroup(MSentryPrivilege.class, "fetchRole");
-                grp.addMember("roles");
-                pm.getFetchPlan().addGroup("fetchRole");
+
+                if (entityType == SentryEntityType.ROLE) {
+                  FetchGroup grp = pm.getFetchGroup(MSentryPrivilege.class, "fetchRole");
+                  grp.addMember("roles");
+                  pm.getFetchPlan().addGroup("fetchRole");
+                } else if(entityType == SentryEntityType.USER) {
+                  FetchGroup grp = pm.getFetchGroup(MSentryPrivilege.class, "fetchUser");
+                  grp.addMember("users");
+                  pm.getFetchPlan().addGroup("fetchUser");
+                }
+
                 query.setFilter(paramBuilder.toString());
                 @SuppressWarnings("unchecked")
                 List<MSentryPrivilege> result = (List<MSentryPrivilege>)query.
diff --git a/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/service/persistent/TestSentryStore.java b/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/service/persistent/TestSentryStore.java
index 5849e7d..52ce72c 100644
--- a/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/service/persistent/TestSentryStore.java
+++ b/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/service/persistent/TestSentryStore.java
@@ -44,6 +44,7 @@
 import org.apache.hadoop.security.alias.CredentialProviderFactory;
 import org.apache.hadoop.security.alias.UserProvider;
 import org.apache.sentry.SentryOwnerInfo;
+import org.apache.sentry.api.service.thrift.TSentryPrivilegeMap;
 import org.apache.sentry.core.common.exception.SentryAccessDeniedException;
 import org.apache.sentry.core.common.exception.SentryInvalidInputException;
 import org.apache.sentry.core.common.utils.SentryConstants;
@@ -4190,6 +4191,33 @@
   }
 
   @Test
+  public void testListSentryPrivilegesByAuthorizableForUser() throws Exception {
+    String userName1 = "list-privs-user1";
+    String grantor = "g1";
+    sentryStore.createSentryUser(userName1);
+
+    TSentryPrivilege privilege1 = new TSentryPrivilege();
+    privilege1.setPrivilegeScope("TABLE");
+    privilege1.setServerName("server1");
+    privilege1.setDbName("db1");
+    privilege1.setTableName("tbl1");
+    privilege1.setAction("SELECT");
+    privilege1.setCreateTime(System.currentTimeMillis());
+    sentryStore.alterSentryGrantPrivilege(grantor, SentryEntityType.USER, userName1, privilege1, null);
+
+    TSentryAuthorizable tSentryAuthorizable = new TSentryAuthorizable();
+    tSentryAuthorizable.setServer("server1");
+    tSentryAuthorizable.setDb("db1");
+    tSentryAuthorizable.setTable("tbl1");
+
+    TSentryPrivilegeMap map = sentryStore.listSentryPrivilegesByAuthorizableForUser(
+        Sets.newHashSet(userName1),
+        tSentryAuthorizable,false);
+    assertEquals(1, map.getPrivilegeMapSize());
+    assertEquals(Sets.newHashSet(userName1), map.getPrivilegeMap().keySet());
+  }
+
+  @Test
   public void testGrantRevokePrivilegeMultipleTimesForRole() throws Exception {
     String roleName = "test-privilege";
     String grantor = "g1";