The queries offered by the PermissionService provide no means to get all the users that have permissions to an object. You can use getGrantedPermissions except it returns either users or groups not users and users that are members of those groups. It would be very slow to make a second query for each group returned to get the group members. Also with that method you can not properly order the users. A query like the following would be very helpful // This is one nasty query that includes display information about // the grantee. It is similar to ObjectPermissionCollection except // it replaces the group information with the users that are members // of those groups. query ObjectUserPermissionQuery { String privilege; Boolean isInherited; BigDecimal userID; PersonName userPersonName; do { select distinct p.privilege, CASE WHEN p.object_id = :objectID THEN 0 ELSE 1 END as inherited_p, u.user_id, u.name_id, pn.given_name, pn.middle_names, pn.family_name from (select p.* from granted_trans_context_map map, acs_permissions p where map.implied_context_id = p.object_id and map.object_id = :objectID union select * from acs_permissions p where p.object_id = :objectID) p, (select user_id as group_id, user_id as member_id from users union select group_id, member_id from group_member_trans_map) um, users u, person_names pn where p.grantee_id = um.group_id and um.member_id = u.user_id and u.name_id = pn.name_id } map { privilege = p.privilege; isInherited = inherited_p; userID = u.user_id; userPersonName.id = u.name_id; userPersonName.givenName = pn.given_name; userPersonName.familyName = pn.family_name; } }