account_sentinel.drush.inc 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. <?php
  2. /**
  3. * @file
  4. * Drush interface of Account Sentinel.
  5. */
  6. /**
  7. * Implements hook_drush_command().
  8. */
  9. function account_sentinel_drush_command() {
  10. $items['account-sentinel-show'] = array(
  11. 'callback' => 'account_sentinel_drush_show',
  12. 'description' => 'Shows the latest events Account Sentinel recorded.',
  13. 'aliases' => array('as-show'),
  14. 'arguments' => array(
  15. 'eid' => 'Optional id of Account Sentinel event to show in detail. If not set, the most recent events will be shown.',
  16. ),
  17. 'options' => array(
  18. 'count' => 'Number of events to show. Defaults to 15.',
  19. 'uid' => "Filter by the subject's UID.",
  20. 'by_uid' => "Filter by the invoker's UID.",
  21. 'origin' => "Filter by the event's origin.",
  22. 'type' => "Filter by the event's type.",
  23. 'ip' => "Filter by the invoker's IP address.",
  24. 'before' => 'Show events occurred before given date. Supports a wide range of date formats (see http://php.net/manual/en/datetime.formats.php).',
  25. 'after' => 'Show events occurred after given date. Supports a wide range of date formats (see http://php.net/manual/en/datetime.formats.php).',
  26. ),
  27. 'outputformat' => array(
  28. 'default' => 'table',
  29. 'pipe-format' => 'var_export',
  30. 'field-labels' => array(
  31. 'eid' => 'ID',
  32. 'uid' => 'UID',
  33. 'origin' => 'Origin',
  34. 'type' => 'Type',
  35. 'data' => 'Raw data',
  36. 'message' => 'Message',
  37. 'by_uid' => 'By UID',
  38. 'ip' => 'IP address',
  39. 'date' => 'Date',
  40. ),
  41. 'fields-default' => array('eid', 'date', 'uid', 'message', 'by_uid', 'ip'),
  42. 'output-data-type' => 'format-table',
  43. ),
  44. );
  45. $items['account-sentinel-audit'] = array(
  46. 'callback' => 'account_sentinel_drush_audit',
  47. 'description' => "Runs Account Sentinel's database audit.",
  48. 'aliases' => array('as-audit'),
  49. );
  50. return $items;
  51. }
  52. /**
  53. * Implements hook_drush_help().
  54. */
  55. function account_sentinel_drush_help($section) {
  56. switch ($section) {
  57. case 'account-sentinel-show':
  58. return dt('');
  59. case 'account-sentinel-audit':
  60. return dt('');
  61. }
  62. }
  63. /**
  64. * Implements the account-sentinel-show Drush command.
  65. *
  66. * @param int|null $eid
  67. * EID of the event, or NULL if multiple events should be shown.
  68. *
  69. * @return array|bool|null
  70. * Output for Drush.
  71. */
  72. function account_sentinel_drush_show($eid = NULL) {
  73. drush_include_engine('drupal', 'environment');
  74. if (is_numeric($eid)) {
  75. return account_sentinel_drush_show_one($eid);
  76. }
  77. else {
  78. return account_sentinel_drush_show_many();
  79. }
  80. }
  81. /**
  82. * Shows a single event's details.
  83. *
  84. * @param int $eid
  85. * EID of the event.
  86. *
  87. * @return array|bool
  88. * Output for Drush.
  89. */
  90. function account_sentinel_drush_show_one($eid) {
  91. // Show a nicer output than a single-row table.
  92. drush_set_default_outputformat('key-value-list');
  93. // Query the event.
  94. $rsc = drush_db_select('account_sentinel_logs', '*', 'eid = :eid', array(':eid' => $eid), 0, 1);
  95. $result = drush_db_fetch_object($rsc);
  96. if (!$result) {
  97. return drush_set_error(dt('Account Sentinel event #!eid not found.', array('!eid' => $eid)));
  98. }
  99. $event = account_sentinel_drush_format_event($result);
  100. return array($event->eid => (array) $event);
  101. }
  102. /**
  103. * Shows multiple events' details.
  104. *
  105. * @return array
  106. * Output for drush.
  107. */
  108. function account_sentinel_drush_show_many() {
  109. $where = account_sentinel_drush_show_many_where();
  110. $count = drush_get_option('count', 15);
  111. $rsc = drush_db_select('account_sentinel_logs', '*', $where['expr'], $where['args'], 0, $count, 'eid', 'DESC');
  112. $table = array();
  113. while ($result = drush_db_fetch_object($rsc)) {
  114. $row = account_sentinel_drush_format_event($result);
  115. $table[$row->eid] = (array) $row;
  116. }
  117. if (empty($table)) {
  118. drush_log(dt('No log events available.'), 'ok');
  119. return array();
  120. }
  121. return $table;
  122. }
  123. /**
  124. * Constructs the WHERE expression for the show command.
  125. *
  126. * @see account_sentinel_drush_show_many()
  127. *
  128. * @return array
  129. * An associative array containing:
  130. * - expr: The WHERE expression.
  131. * - args: Values of the named placeholders.
  132. */
  133. function account_sentinel_drush_show_many_where() {
  134. // Collect filter values from options.
  135. $filters = array(
  136. array('uid', drush_get_option('uid')),
  137. array('by_uid', drush_get_option('by_uid')),
  138. array('origin', drush_get_option('origin')),
  139. array('type', drush_get_option('type')),
  140. array('ip', drush_get_option('ip')),
  141. array('timestamp', drush_get_option('before'), '<='),
  142. array('timestamp', drush_get_option('after'), '>='),
  143. );
  144. // Convert some filter values.
  145. foreach ($filters as $key => $filter) {
  146. // Dates should be converted to UNIX timestamps.
  147. if ($filter[0] == 'timestamp' && $filter[1] !== NULL) {
  148. if (($time = strtotime($filter[1])) !== FALSE) {
  149. $filters[$key][1] = $time;
  150. }
  151. else {
  152. $filters[$key][1] = NULL;
  153. }
  154. }
  155. }
  156. // Build the expression.
  157. $where = array(
  158. 'expr' => array(),
  159. 'args' => array(),
  160. );
  161. $placeholder_cnt = 0;
  162. foreach ($filters as $filter) {
  163. $col = $filter[0];
  164. $val = $filter[1];
  165. $op = isset($filter[2]) ? $filter[2] : '=';
  166. if ($val !== NULL) {
  167. $placeholder_cnt++;
  168. $expr = "($col $op :ph_$placeholder_cnt)";
  169. $where['expr'][] = $expr;
  170. $where['args'][":ph_$placeholder_cnt"] = $val;
  171. }
  172. }
  173. $where['expr'] = implode(' AND ', $where['expr']);
  174. // Return the WHERE expression.
  175. return $where;
  176. }
  177. /**
  178. * Formats an event row for output.
  179. *
  180. * @param object $event
  181. * A row object of account_sentinel_logs.
  182. *
  183. * @return object
  184. * The event with formatted data.
  185. */
  186. function account_sentinel_drush_format_event($event) {
  187. // Collect and construct additional information.
  188. $type = $event->type;
  189. $origin = $event->origin;
  190. $data = unserialize($event->data);
  191. $message = account_sentinel_get_event_message($type, $data);
  192. $message = account_sentinel_drush_html_to_text($message);
  193. // Set formatted information.
  194. $event->date = format_date($event->timestamp, 'short');
  195. $event->data = print_r($data, TRUE);
  196. $event->message = $message;
  197. $event->type = account_sentinel_event_type_get_string($type);
  198. $event->origin = account_sentinel_event_origin_get_string($origin);
  199. // Return formatted event.
  200. return $event;
  201. }
  202. /**
  203. * Converts an HTML message to plain text.
  204. *
  205. * Uses drush_html_to_text(), but also removes some unwanted whitespace that the
  206. * said command leaves in its output.
  207. *
  208. * @param string $message
  209. * The input HTML message.
  210. *
  211. * @see drush_html_to_text()
  212. *
  213. * @return string
  214. * The plaintext message.
  215. */
  216. function account_sentinel_drush_html_to_text($message) {
  217. return str_replace(' .', '.', drush_html_to_text($message));
  218. }
  219. /**
  220. * Implements the account-sentinel-audit Drush command.
  221. */
  222. function account_sentinel_drush_audit() {
  223. watchdog('account_sentinel', 'Invoked database audit from Drush.');
  224. module_load_include('inc', 'account_sentinel', 'account_sentinel.audit');
  225. account_sentinel_audit();
  226. drush_log(dt('Account Sentinel audit run successful.'), 'success');
  227. }