oauth_common.admin.inc 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574
  1. <?php
  2. function _oauth_common_admin() {
  3. $form = array();
  4. $form['oauth_common_enable_provider'] = array(
  5. '#type' => 'checkbox',
  6. '#title' => t('Enable the oauth provider'),
  7. '#default_value' => variable_get('oauth_common_enable_provider', TRUE),
  8. '#description' => t('This option controls whether this site should act as a OAuth provider or not'),
  9. );
  10. $form['oauth_common_request_token_lifetime'] = array(
  11. '#type' => 'textfield',
  12. '#title' => t('Request token lifetime (in seconds)'),
  13. '#default_value' => variable_get('oauth_common_request_token_lifetime', 7200),
  14. );
  15. $form['#validate'][] = '_oauth_common_admin_settings_validate';
  16. return system_settings_form($form);
  17. }
  18. function _oauth_common_admin_settings_validate($form, $form_state) {
  19. $values = $form_state['values'];
  20. $lifetime = intval($values['oauth_common_request_token_lifetime'], 10);
  21. if (!$lifetime) {
  22. form_set_error('oauth_common_request_token_lifetime', t('The request token lifetime must be a non-zero integer value.'));
  23. }
  24. }
  25. /**
  26. * Output a list of contexts.
  27. */
  28. function oauth_common_list_context($js = NULL) {
  29. $header = array(
  30. array('data' => t('Title'), 'class' => array('oauth-common-contexts-title')),
  31. array('data' => t('Storage'), 'class' => array('oauth-common-contexts-storage')),
  32. array('data' => t('Operations'), 'class' => array('oauth-common-contexts-operations')),
  33. );
  34. $contexts = oauth_common_context_load_all();
  35. $rows = array();
  36. if (!$contexts) {
  37. $contexts = array();
  38. }
  39. foreach ($contexts as $context) {
  40. $operations = array();
  41. if (empty($context->disabled)) {
  42. $operations[] = array(
  43. 'title' => t('Edit'),
  44. 'href' => 'admin/config/services/oauth/' . $context->name . '/edit',
  45. );
  46. $operations[] = array(
  47. 'title' => t('Export'),
  48. 'href' => 'admin/config/services/oauth/' . $context->name . '/export',
  49. );
  50. }
  51. if ($context->export_type == (EXPORT_IN_CODE | EXPORT_IN_DATABASE)) {
  52. $operations[] = array(
  53. 'title' => t('Revert'),
  54. 'href' => 'admin/config/services/oauth/' . $context->name . '/delete',
  55. );
  56. }
  57. elseif ($context->export_type != EXPORT_IN_CODE) {
  58. $operations[] = array(
  59. 'title' => t('Delete'),
  60. 'href' => 'admin/config/services/oauth/' . $context->name . '/delete',
  61. );
  62. }
  63. elseif (empty($context->disabled)) {
  64. $operations[] = array(
  65. 'title' => t('Disable'),
  66. 'href' => 'admin/config/services/oauth/' . $context->name . '/disable',
  67. 'query' => drupal_get_destination(),
  68. );
  69. }
  70. else {
  71. $operations[] = array(
  72. 'title' => t('Enable'),
  73. 'href' => 'admin/config/services/oauth/' . $context->name . '/enable',
  74. 'query' => drupal_get_destination(),
  75. );
  76. }
  77. $rows[$context->name] = array(
  78. 'data' => array(
  79. 'title' => array(
  80. 'data' => check_plain($context->title),
  81. 'class' => array('oauth-common-contexts-title'),
  82. ),
  83. 'storage' => array(
  84. 'data' => ($context->export_type == EXPORT_IN_CODE) ? t('In code') : t('In database'),
  85. 'class' => array('oauth-common-contexts-storage'),
  86. ),
  87. 'operations' => array(
  88. 'data' => theme('links', array('links' => $operations)),
  89. 'class' => array('oauth-common-contexts-operations'),
  90. ),
  91. ),
  92. 'class' => array('oauth-common-contexts-' . $context->name)
  93. );
  94. if (!empty($context->disabled)) {
  95. $rows[$context->name]['class'][] = 'oauth-common-contexts-disabled';
  96. }
  97. }
  98. $table = theme('table', array(
  99. 'header' => $header,
  100. 'rows' => $rows,
  101. 'attributes' => array('id' => 'oauth-common-list-contexts')
  102. ));
  103. return $table;
  104. }
  105. /**
  106. * Handle the add context page.
  107. */
  108. function oauth_common_add_context() {
  109. $context = oauth_common_context_new();
  110. drupal_set_title(t('Add context'));
  111. if (!$context) {
  112. drupal_set_message(t("Can't create contexts, check that you've installed !ctools.", array(
  113. '!ctools' => l('Chaos tool suite', 'http://drupal.org/project/ctools'),
  114. )), 'error');
  115. $result = '';
  116. }
  117. else {
  118. $result = oauth_common_edit_context($context);
  119. }
  120. return $result;
  121. }
  122. /**
  123. * Edit an context.
  124. *
  125. * Called from both the add and edit points to provide for common flow.
  126. */
  127. function oauth_common_edit_context($context) {
  128. if (!is_object($context)) {
  129. $context = oauth_common_context_load($context);
  130. }
  131. if ($context && !empty($context->title)) {
  132. drupal_set_title($context->title);
  133. }
  134. return drupal_get_form('oauth_common_edit_form_context', $context);
  135. }
  136. /**
  137. * Form to edit the settings of an context.
  138. */
  139. function oauth_common_edit_form_context($form, &$form_state, $context) {
  140. $form['#attached']['css'] = array(
  141. drupal_get_path('module', 'oauth_common') . '/css/admin.css'
  142. );
  143. $form['cid'] = array(
  144. '#type' => 'value',
  145. '#value' => isset($context->cid) ? $context->cid : '',
  146. );
  147. $form['context_object'] = array(
  148. '#type' => 'value',
  149. '#value' => $context,
  150. );
  151. $form['title'] = array(
  152. '#type' => 'textfield',
  153. '#size' => 24,
  154. '#maxlength' => 100,
  155. '#default_value' => $context->title,
  156. '#title' => t('Context title'),
  157. '#required' => TRUE,
  158. );
  159. $form['name'] = array(
  160. '#type' => 'machine_name',
  161. '#size' => 24,
  162. '#maxlength' => 32,
  163. '#default_value' => $context->name,
  164. '#title' => t('Context name'),
  165. '#description' => t('A unique name used to identify this preset internally. It must be only be alpha characters and underscores. No spaces, numbers or uppercase characters.'),
  166. '#machine_name' => array(
  167. 'source' => array('title'),
  168. 'exists' => 'oauth_common_edit_form_context_exists',
  169. ),
  170. '#required' => TRUE,
  171. );
  172. $sign_methods = array(
  173. 'PLAINTEXT' => t('Plaintext'),
  174. );
  175. foreach (hash_algos() as $algo) {
  176. $sign_methods['HMAC-' . strtoupper($algo)] = 'HMAC-' . strtoupper($algo);
  177. }
  178. $form['signature_methods'] = array(
  179. '#type' => 'fieldset',
  180. '#title' => t('Signature methods'),
  181. '#collapsible' => TRUE,
  182. '#collapsed' => TRUE,
  183. '#tree' => TRUE,
  184. 'selected' => array(
  185. '#type' => 'checkboxes',
  186. '#title' => t('Supported signature methods'),
  187. '#options' => $sign_methods,
  188. '#default_value' => !empty($context->authorization_options['signature_methods']) ?
  189. $context->authorization_options['signature_methods'] :
  190. array('HMAC-SHA1', 'HMAC-SHA256', 'HMAC-SHA384', 'HMAC-SHA512'),
  191. )
  192. );
  193. $form['authorization_options'] = array(
  194. '#type' => 'fieldset',
  195. '#title' => t('Authorization options'),
  196. '#tree' => TRUE,
  197. '#collapsible' => TRUE,
  198. '#collapsed' => TRUE,
  199. );
  200. $form['authorization_options']['page_title'] = array(
  201. '#type' => 'textfield',
  202. '#title' => t('Page title'),
  203. '#description' => t('The title of the authorization page.'),
  204. '#size' => 40,
  205. '#maxlength' => 255,
  206. '#default_value' => empty($context->authorization_options['page_title']) ? '' : $context->authorization_options['page_title'],
  207. );
  208. $form['authorization_options']['message'] = array(
  209. '#type' => 'textarea',
  210. '#title' => t('Message'),
  211. '#description' => t('The message shown to the user when authorizing.'),
  212. '#default_value' => empty($context->authorization_options['message']) ? '' : $context->authorization_options['message'],
  213. );
  214. $form['authorization_options']['warning'] = array(
  215. '#type' => 'textarea',
  216. '#title' => t('Warning'),
  217. '#description' => t('The warning shown to the user when authorizing.'),
  218. '#default_value' => empty($context->authorization_options['warning']) ? '' : $context->authorization_options['warning'],
  219. );
  220. $form['authorization_options']['deny_access_title'] = array(
  221. '#type' => 'textfield',
  222. '#title' => t('Deny access title'),
  223. '#description' => t('The title of deny access link.'),
  224. '#size' => 40,
  225. '#maxlength' => 255,
  226. '#default_value' => empty($context->authorization_options['deny_access_title']) ? '' : $context->authorization_options['deny_access_title'],
  227. );
  228. $form['authorization_options']['grant_access_title'] = array(
  229. '#type' => 'textfield',
  230. '#title' => t('Grant access title'),
  231. '#description' => t('The title of grant access button.'),
  232. '#size' => 40,
  233. '#maxlength' => 255,
  234. '#default_value' => empty($context->authorization_options['grant_access_title']) ? '' : $context->authorization_options['grant_access_title'],
  235. );
  236. $form['authorization_options']['access_token_lifetime'] = array(
  237. '#type' => 'textfield',
  238. '#title' => t('Access token lifetime'),
  239. '#description' => t('The time, in seconds, for which an access token should be valid, use 0 to never expire access tokens.'),
  240. '#size' => 10,
  241. '#maxlength' => 255,
  242. '#default_value' => empty($context->authorization_options['access_token_lifetime']) ? 0 : $context->authorization_options['access_token_lifetime'],
  243. );
  244. $form['authorization_options']['disable_auth_level_selection'] = array(
  245. '#type' => 'checkbox',
  246. '#title' => t('Disable authorization level selection'),
  247. '#description' => t('If this is checked the user won\'t be able to choose the authorization level, and the default authorization level(s) will be used.'),
  248. '#default_value' => !empty($context->authorization_options['disable_auth_level_selection']),
  249. );
  250. $form['authorization_levels'] = array(
  251. '#type' => 'fieldset',
  252. '#title' => t('Authorization levels'),
  253. '#tree' => TRUE,
  254. '#prefix' => '<div id="auth-level-wrapper">',
  255. '#suffix' => '</div>',
  256. 'add_authorization_level' => array(
  257. '#type' => 'submit',
  258. '#value' => t('Add authorization level'),
  259. '#weight' => 10,
  260. '#submit' => array('oauth_common_edit_form_auth_level_ajax_add'),
  261. '#limit_validation_errors' => array(),
  262. '#ajax' => array(
  263. 'callback' => 'oauth_common_edit_form_auth_level_ajax_callback',
  264. 'wrapper' => 'auth-level-wrapper',
  265. )
  266. ),
  267. );
  268. foreach ($context->authorization_levels as $name => $level) {
  269. $title = !empty($name) ? check_plain($name) : t('New level');
  270. if ($title == '*') {
  271. $title = t('Full access');
  272. }
  273. $l = oauth_common_edit_form_auth_level($context, $title, $name, $level);
  274. $form['authorization_levels'][] = $l;
  275. }
  276. if (!isset($form_state['authorization_level_new'])) {
  277. $form_state['authorization_level_new'] = 0;
  278. }
  279. for ($i = 0; $i < $form_state['authorization_level_new']; $i++) {
  280. $form['authorization_levels'][] = oauth_common_edit_form_auth_level($context, t('Authorization level'));
  281. }
  282. $form['actions'] = array('#type' => 'actions');
  283. $form['actions']['submit'] = array(
  284. '#type' => 'submit',
  285. '#value' => t('Save'),
  286. );
  287. return $form;
  288. }
  289. /**
  290. * Helper function for constructing a auth level fieldset.
  291. *
  292. * @param object $context
  293. * @param int $idx
  294. * @param string $title
  295. * @param string $name
  296. * @param array $level
  297. * @return array.
  298. */
  299. function oauth_common_edit_form_auth_level($context, $title, $name = '', $level = array()) {
  300. $level = $level + array(
  301. 'title' => '',
  302. 'description' => '',
  303. );
  304. $element = array(
  305. "name" => array(
  306. '#type' => 'textfield',
  307. '#title' => t('Name'),
  308. '#description' => t('The name of the authorization level.'),
  309. '#size' => 40,
  310. '#maxlength' => 32,
  311. '#default_value' => $name,
  312. ),
  313. "title" => array(
  314. '#type' => 'textfield',
  315. '#title' => t('Title'),
  316. '#description' => t('The title of the authorization level.'),
  317. '#size' => 40,
  318. '#maxlength' => 100,
  319. '#default_value' => $level['title'],
  320. ),
  321. "default" => array(
  322. '#type' => 'checkbox',
  323. '#title' => t('Selected by default'),
  324. '#description' => t('Whether the authentication level should be checked by default.'),
  325. '#default_value' => is_array($context->authorization_options['default_authorization_levels']) && in_array($name, $context->authorization_options['default_authorization_levels']),
  326. ),
  327. "delete" => array(
  328. '#type' => 'checkbox',
  329. '#title' => t('Delete'),
  330. '#description' => t('Check this to delete the authorization level.'),
  331. '#default_value' => FALSE,
  332. ),
  333. "description" => array(
  334. '#type' => 'textarea',
  335. '#title' => t('Description'),
  336. '#description' => t('The description of the authorization level.'),
  337. '#default_value' => $level['description'],
  338. ),
  339. );
  340. return $element;
  341. }
  342. /**
  343. * Submit handler for adding auth levels
  344. *
  345. * @return void
  346. */
  347. function oauth_common_edit_form_auth_level_ajax_add($form, &$form_state) {
  348. $form_state['authorization_level_new']++;
  349. $form_state['rebuild'] = TRUE;
  350. }
  351. /**
  352. * AJAX callback for dealing with auth levels
  353. *
  354. * @return void
  355. */
  356. function oauth_common_edit_form_auth_level_ajax_callback($form, $form_state) {
  357. return $form['authorization_levels'];
  358. }
  359. /**
  360. * Check whether a given context exists.
  361. *
  362. * @param $name the name parameter for the context.
  363. * @return boolean
  364. */
  365. function oauth_common_edit_form_context_exists($name) {
  366. $exists = FALSE;
  367. if (!empty($name)) {
  368. $result = db_query('SELECT cid FROM {oauth_common_context} WHERE name = :name', array(
  369. ':name' => $name
  370. ))->fetchField();
  371. $exists = $result ? TRUE : FALSE;
  372. }
  373. return $exists;
  374. }
  375. /**
  376. * Validate submission of the preset edit form.
  377. */
  378. function oauth_common_edit_form_context_validate(&$form, &$form_state) {
  379. $values = $form_state['values'];
  380. // Check that the authorization level names are unique within the context
  381. $levels = array();
  382. $default_exists = FALSE;
  383. foreach ($values['authorization_levels'] as $key => $level) {
  384. if (is_numeric($key) && !empty($level['name']) && !$level['delete']) {
  385. if (!empty($levels[$level['name']])) {
  386. form_error($form['authorization_levels'][$key]['name'], t('Authorization level name must be unique.'));
  387. }
  388. else if (preg_match("/[^A-Za-z0-9_\*]/", $level['name'])) {
  389. form_error($form['authorization_levels'][$key]['name'], t('Authorization level name must be alphanumeric or underscores only.'));
  390. }
  391. if (empty($level['title'])) {
  392. form_error($form['authorization_levels'][$key]['title'], t('Authorization levels must have a title.'));
  393. }
  394. $default_exists = $default_exists || $level['default'];
  395. $levels[$level['name']] = TRUE;
  396. }
  397. }
  398. // Check that we actually got a number as access token lifetime
  399. if (!is_numeric($values['authorization_options']['access_token_lifetime'])) {
  400. form_error($form['authorization_options']['access_token_lifetime'], t('The access token lifetime must be numeric.'));
  401. }
  402. // Check that at least one default authorization level is checked when
  403. // authorization level selection is disabled.
  404. if (!$default_exists && $values['authorization_options']['disable_auth_level_selection']) {
  405. form_error($form['authorization_options']['disable_auth_level_selection'], t('You must select at least one default authorirization level if level selection is disabled.'));
  406. }
  407. }
  408. /**
  409. * Process submission of the mini panel edit form.
  410. */
  411. function oauth_common_edit_form_context_submit($form, &$form_state) {
  412. $context = $form_state['values']['context_object'];
  413. $values = $form_state['values'];
  414. $context->name = $values['name'];
  415. $context->title = $values['title'];
  416. $auth_options = array(
  417. 'access_token_lifetime' => 0,
  418. );
  419. foreach ($values['authorization_options'] as $key => $value) {
  420. $auth_options[$key] = empty($value) ? null : $value;
  421. }
  422. $context->authorization_options = $auth_options;
  423. // Collect the names of the selected signature methods.
  424. $sig_options = array();
  425. foreach ($values['signature_methods']['selected'] as $name => $selected) {
  426. if ($selected) {
  427. $sig_options[] = $name;
  428. }
  429. }
  430. $context->authorization_options['signature_methods'] = $sig_options;
  431. // Set the auth levels and default levels for the context
  432. $levels = array();
  433. $default_levels = array();
  434. foreach ($values['authorization_levels'] as $key => $level) {
  435. if (is_numeric($key) && !empty($level['name']) && !$level['delete']) {
  436. $name = $level['name'];
  437. if ($level['default']) {
  438. $default_levels[] = $name;
  439. }
  440. $levels[$name] = $level;
  441. }
  442. }
  443. $context->authorization_levels = $levels;
  444. $context->authorization_options['default_authorization_levels'] = $default_levels;
  445. oauth_common_context_save($context);
  446. if (empty($context->cid)) {
  447. drupal_set_message(t('Your new context %title has been saved.', array('%title' => $context->title)));
  448. $form_state['values']['cid'] = $context->cid;
  449. }
  450. else {
  451. drupal_set_message(t('Your changes have been saved.'));
  452. }
  453. $form_state['redirect'] = 'admin/config/services/oauth';
  454. }
  455. /**
  456. * Provide a form to confirm deletion of a context.
  457. */
  458. function oauth_common_delete_confirm_context($form, &$form_state, $context) {
  459. if (!is_object($context)) {
  460. $context = oauth_common_context_load($context);
  461. }
  462. if ($context->export_type == (EXPORT_IN_CODE | EXPORT_IN_DATABASE)) {
  463. $title = t('Are you sure you want to revert the context "@title"?', array('@title' => $context->title));
  464. $submit = t('Revert');
  465. }
  466. elseif ($context->export_type != EXPORT_IN_CODE) {
  467. $title = t('Are you sure you want to delete the context "@title"?', array('@title' => $context->title));
  468. $submit = t('Delete');
  469. }
  470. else {
  471. drupal_not_found();
  472. die;
  473. }
  474. $form['context'] = array('#type' => 'value', '#value' => $context->name);
  475. $form['cid'] = array('#type' => 'value', '#value' => $context->cid);
  476. return confirm_form($form,
  477. $title,
  478. !empty($_GET['destination']) ? $_GET['destination'] : 'admin/config/services/oauth',
  479. t('This action cannot be undone.'),
  480. $submit, t('Cancel')
  481. );
  482. }
  483. /**
  484. * Handle the submit button to delete a context.
  485. */
  486. function oauth_common_delete_confirm_context_submit($form, &$form_state) {
  487. $context = oauth_common_context_load($form_state['values']['context']);
  488. if ($context->cid == $form_state['values']['cid']) {
  489. oauth_common_context_delete($context);
  490. $form_state['redirect'] = 'admin/config/services/oauth';
  491. }
  492. }
  493. /**
  494. * Page callback to export a context to PHP code.
  495. */
  496. function oauth_common_export_context($form, &$form_state, $context) {
  497. if (!is_object($context)) {
  498. $context = oauth_common_context_load($context);
  499. }
  500. drupal_set_title($context->title);
  501. $code = oauth_common_context_export($context);
  502. $lines = substr_count($code, "\n") + 4;
  503. $form['code'] = array(
  504. '#type' => 'textarea',
  505. '#title' => $context->title,
  506. '#default_value' => $code,
  507. '#rows' => $lines,
  508. );
  509. return $form;
  510. }