permission_report.module 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. <?php
  2. /**
  3. * Drupal module to calculate the resultant set of permissions for a user.
  4. *
  5. * @author Nicholas Vahalik <nick@nickvahalik.com>
  6. * @copyright Nicholas Vahalik 2013
  7. * @package permission_report
  8. **/
  9. /**
  10. * Implements hook_menu().
  11. */
  12. function permission_report_menu() {
  13. $items = array();
  14. $items['admin/reports/permissions'] = array(
  15. 'title' => 'Permissions (role report)',
  16. 'page callback' => 'permission_report_role_list',
  17. 'access arguments' => array('view permission report'),
  18. 'description' => 'View roles and the users in them.',
  19. );
  20. $items['admin/reports/permissions/roles'] = array(
  21. 'title' => 'Roles',
  22. 'page callback' => 'permission_report_role_list',
  23. 'type' => MENU_DEFAULT_LOCAL_TASK,
  24. 'access arguments' => array('view permission report'),
  25. 'weight' => -5,
  26. );
  27. $items['admin/reports/permissions/perms'] = array(
  28. 'title' => 'Permissions',
  29. 'page callback' => 'permission_report_permission_list',
  30. 'type' => MENU_LOCAL_TASK,
  31. 'access arguments' => array('view permission report'),
  32. );
  33. $items['admin/reports/permissions/perms/%'] = array(
  34. 'title' => 'Permissions',
  35. 'type' => MENU_CALLBACK,
  36. 'page arguments' => array(4),
  37. 'page callback' => 'permission_report_user_having_perm',
  38. 'access arguments' => array('view permission report'),
  39. );
  40. $items['admin/reports/permissions/roles/%'] = array(
  41. 'title' => 'Roles',
  42. 'type' => MENU_CALLBACK,
  43. 'page callback' => 'permission_report_users_having_role',
  44. 'page arguments' => array(4),
  45. 'access arguments' => array('view permission report'),
  46. );
  47. $items['user/%user/permission_report'] = array(
  48. 'title' => 'Permission Report',
  49. 'page callback' => 'permission_report_user_report',
  50. 'page arguments' => array(1),
  51. 'type' => MENU_LOCAL_TASK,
  52. 'access arguments' => array('view permission report'),
  53. 'weight' => 2,
  54. );
  55. return $items;
  56. }
  57. /**
  58. * Implements hook_admin_paths().
  59. */
  60. function permission_report_admin_paths() {
  61. $paths = array(
  62. 'user/*/permission_report' => TRUE,
  63. );
  64. return $paths;
  65. }
  66. /**
  67. * Implements hook_user_view().
  68. */
  69. function permission_report_user_view($account, $view_mode, $langcode) {
  70. if (user_access('view permission report', $account)) {
  71. $account->content['summary']['rsop'] = array(
  72. '#type' => 'user_profile_item',
  73. '#title' => t('Resultant Set of Permissions'),
  74. '#markup' => l(t('View permission report report for !s', array('!s' => $account->name)), "user/$account->uid/permission_report"),
  75. '#attributes' => array('class' => 'permission_report'),
  76. );
  77. }
  78. }
  79. /**
  80. * Displays a permission report for a given user.
  81. *
  82. * @param $user User object.
  83. *
  84. * @return string
  85. */
  86. function permission_report_user_report($user) {
  87. // Render role/permission overview:
  88. $options = array();
  89. $row = array();
  90. $can_admin_access = user_access('administer access control');
  91. foreach (module_implements('permission') as $module) {
  92. if ($permissions = module_invoke($module, 'permission')) {
  93. $rows[] = array(array(
  94. 'data' => t('@module module', array('@module' => $module)),
  95. 'class' => 'module',
  96. 'id' => 'module-' . $module,
  97. 'colspan' => 3,
  98. ));
  99. asort($permissions);
  100. foreach ($permissions as $perm => $meta) {
  101. $options = array();
  102. $display_roles = array();
  103. $roles = _permission_report_roles_having_perm($perm, $user);
  104. if (array_key_exists('description', $meta)) {
  105. $options = array('attributes' => array('alt' => $meta['description']));
  106. }
  107. foreach ($roles as $rid => $name) {
  108. $display_roles[] = $can_admin_access ? l($name, "admin/reports/permissions/roles/$rid") : t($name);
  109. }
  110. $rows[] = array(
  111. array('data' => l(strip_tags($meta['title']), "admin/reports/permissions/perms/$perm", $options)),
  112. array('data' => user_access($perm, $user) ? 'Yes' : 'No'),
  113. array('data' => implode(', ', $display_roles)),
  114. );
  115. }
  116. }
  117. }
  118. return theme('table', array('header' => array('Permission', 'Access', 'Roles'), 'rows' => $rows, 'attributes' => array('id' => 'permissions')));
  119. }
  120. /**
  121. * Return an array of users keyed by IDs that have access to a specific permission.
  122. *
  123. * @param $permission Permission string.
  124. *
  125. * @return array
  126. **/
  127. function _permission_report_users_having_perm($permission) {
  128. $roles = _permission_report_roles_having_perm($permission);
  129. if (count($roles) > 0) {
  130. $query = db_select('users', 'u');
  131. $query->innerJoin('users_roles', 'ur', 'ur.uid = u.uid');
  132. $query->addField('u', 'uid');
  133. $query->addField('u', 'name');
  134. $query->condition('ur.rid', array_keys($roles), 'IN');
  135. $users = $query->execute()->fetchAllKeyed();
  136. return $users;
  137. }
  138. return array();
  139. }
  140. /**
  141. * Gets a list of roles that have a permission, optionally limited
  142. * to a specific role.
  143. */
  144. function _permission_report_roles_having_perm($permission, $user = NULL) {
  145. $query = db_select('role', 'r');
  146. $query->addField('r', 'rid');
  147. $query->addField('r', 'name');
  148. $query->innerJoin('role_permission', 'p', 'r.rid = p.rid');
  149. $query->condition('p.permission', $permission);
  150. if ($user) {
  151. $query->innerJoin('users_roles', 'ur', 'r.rid = ur.rid');
  152. $query->condition('ur.uid', $user->uid);
  153. }
  154. return $query->execute()->fetchAllKeyed();
  155. }
  156. /**
  157. * Generates a report of users having a particular role.
  158. **/
  159. function permission_report_users_having_role($rid) {
  160. $users_having_roles = $rows = array();
  161. $query = db_select('users', 'u');
  162. $query->addField('u', 'uid');
  163. $query->addField('u', 'name');
  164. $query->innerJoin('users_roles', 'ur', 'ur.uid = u.uid');
  165. $query->condition('ur.rid', $rid);
  166. $query->condition('u.status', 1);
  167. $users_having_role = $query->execute()->fetchAll();
  168. $query = db_select('role', 'r');
  169. $query->addField('r', 'name');
  170. $query->condition('rid', $rid);
  171. $role_name = $query->execute()->fetchField();
  172. $view_users = user_access('access user profiles');
  173. drupal_set_title(t('Users in "!name" role', array('!name' => $role_name)));
  174. $users_header = array(array(
  175. 'data' => 'User',
  176. 'colspan' => 2,
  177. ));
  178. foreach ($users_having_role as $user) {
  179. $rows[] = array(
  180. array('data' => ($user->uid !== 0) ? ($view_users ? l($user->name, "user/$user->uid") : $user->name) : variable_get('anonymous', t('Anonymous')))
  181. ,
  182. array('data' => l('Permission report', "user/$user->uid/permission_report")),
  183. );
  184. }
  185. return theme('table', array('header' => $users_header, 'rows' => $rows));
  186. }
  187. /**
  188. * List of roles with the number of users in each role.
  189. */
  190. function permission_report_role_list() {
  191. $user_in_roles = db_query('SELECT r.rid rid, r.name name, COUNT(ur.uid) as user_count FROM {role} r INNER JOIN {users_roles} ur USING (rid) INNER JOIN {users} u USING(uid) WHERE u.status = :u_status GROUP BY r.rid ORDER BY r.name', array(':u_status' => 1))->fetchAllAssoc('rid');
  192. $can_admin_access = user_access('administer access control');
  193. $all_users = user_roles();
  194. // Remove 'authenticated user' and 'anonymous user'.
  195. unset($all_users[1], $all_users[2]);
  196. $rows = array();
  197. foreach ($all_users as $rid => $name) {
  198. $count = (isset($user_in_roles[$rid])) ? $user_in_roles[$rid]->user_count : 0;
  199. $rows[] = array(
  200. $can_admin_access ? l($name, "admin/people/permissions/$rid") : t($name),
  201. l(format_plural($count, '1 user', '@count users'), "admin/reports/permissions/roles/$rid"),
  202. );
  203. }
  204. $roles_header = array(
  205. array(
  206. 'data' => 'Role',
  207. 'colspan' => 2,
  208. ),
  209. );
  210. return theme('table', array('header' => $roles_header, 'rows' => $rows));
  211. }
  212. /**
  213. * Creates a report showing which users have a specific permission.
  214. */
  215. function permission_report_user_having_perm($permission) {
  216. $view_users = user_access('access user profiles');
  217. $can_admin_access = user_access('administer access control');
  218. $output = '';
  219. drupal_set_title(t('Permissions report for "!permission"', array('!permission' => $permission)));
  220. foreach (_permission_report_users_having_perm($permission) as $uid => $name) {
  221. $users_rows[] = array(
  222. array('data' => ($uid !== 0) ? ($view_users ? l($name, "user/$uid") : $name) : variable_get('anonymous', t('Anonymous'))),
  223. array('data' => l('Permission report', 'user/' . $uid . '/permission_report')),
  224. );
  225. }
  226. $users_header = array(
  227. array(
  228. 'data' => 'User',
  229. 'colspan' => 2,
  230. ),
  231. );
  232. foreach (_permission_report_roles_having_perm($permission) as $rid => $name) {
  233. $roles_rows[] = array(
  234. array('data' => $can_admin_access ? l($name, "admin/reports/permissions/roles/$rid") : t($name)),
  235. array('data' => l('Permission report', "admin/reports/permissions/roles/$rid")),
  236. );
  237. }
  238. $roles_header = array(
  239. array(
  240. 'data' => 'Role',
  241. 'colspan' => 2,
  242. ),
  243. );
  244. $output .= '<h2 class="title"><a name="permission-report-users">Users</a></h2>';
  245. $output .= theme('table', array('header' => $users_header, 'rows' => $users_rows));
  246. $output .= '<h2 class="title"><a name="permission-report-roles">Roles</a></h2>';
  247. $output .= theme('table', array('header' => $roles_header, 'rows' => $roles_rows));
  248. return $output;
  249. }
  250. /**
  251. * Creates a report which lists all permissions and the number of users which
  252. * have those permissions.
  253. */
  254. function permission_report_permission_list() {
  255. $can_admin_access = user_access('administer access control');
  256. foreach (module_implements('permission') as $module) {
  257. if ($permissions = module_invoke($module, 'permission')) {
  258. $rows[] = array(array(
  259. 'data' => t('@module module', array('@module' => $module)),
  260. 'class' => 'module',
  261. 'id' => 'module-' . $module,
  262. 'colspan' => 3,
  263. ));
  264. asort($permissions);
  265. foreach ($permissions as $perm => $meta) {
  266. $display_roles = array();
  267. $roles = _permission_report_roles_having_perm($perm);
  268. foreach ($roles as $rid => $name) {
  269. $display_roles[] = $can_admin_access ? l($name, "admin/reports/permissions/roles/$rid") : t($name);
  270. }
  271. $rows[] = array(
  272. array('data' => $meta['title']),
  273. array('data' => l(format_plural(count(_permission_report_users_having_perm($perm)), '1 user', '@count users'), "admin/reports/permissions/perms/$perm")),
  274. );
  275. }
  276. }
  277. }
  278. return theme('table', array('header' => array('Permission', 'Users'), 'rows' => $rows, 'attributes' => array('id' => 'permissions', 'sticky' => TRUE)));
  279. }
  280. /**
  281. * Implements hook_permission().
  282. */
  283. function permission_report_permission() {
  284. return array(
  285. 'view permission report' => array(
  286. 'title' => t('View permission report'),
  287. 'description' => t('Allows a user to view permission reports.'),
  288. ),
  289. );
  290. }