SproutCMS

This is the code documentation for the SproutCMS project

source of /sprout/Controllers/Admin/MySettingsAdminController.php

  1. <?php
  2. /*
  3.  * Copyright (C) 2017 Karmabunny Pty Ltd.
  4.  *
  5.  * This file is a part of SproutCMS.
  6.  *
  7.  * SproutCMS is free software: you can redistribute it and/or modify it under the terms
  8.  * of the GNU General Public License as published by the Free Software Foundation, either
  9.  * version 2 of the License, or (at your option) any later version.
  10.  *
  11.  * For more information, visit <http://getsproutcms.com>.
  12.  */
  13.  
  14. namespace Sprout\Controllers\Admin;
  15.  
  16. use Kohana;
  17.  
  18. use Sprout\Helpers\AdminAuth;
  19. use Sprout\Helpers\Csrf;
  20. use Sprout\Helpers\Form;
  21. use Sprout\Helpers\Notification;
  22. use Sprout\Helpers\Pdb;
  23. use Sprout\Helpers\Security;
  24. use Sprout\Helpers\TwoFactor\GoogleAuthenticator;
  25. use Sprout\Helpers\Url;
  26. use Sprout\Helpers\Validator;
  27. use Sprout\Helpers\View;
  28.  
  29.  
  30. /**
  31.  * Changes settings for the currently logged in user
  32.  */
  33. class MySettingsAdminController extends NoRecordsAdminController
  34. {
  35. protected $controller_name = 'my_settings';
  36. protected $friendly_name = 'My settings';
  37.  
  38.  
  39. public function _intro()
  40. {
  41. Url::redirect('admin/extra/my_settings/details');
  42. }
  43.  
  44. public function _getNavigation()
  45. {
  46. return '';
  47. }
  48.  
  49. public function _getTools()
  50. {
  51. $tools = [];
  52. $tools[] = '<li><a href="admin/extra/my_settings/details">Details and password</a></li>';
  53. $tools[] = '<li><a href="admin/extra/my_settings/twoFactor">Setup two-factor auth</a></li>';
  54. return $tools;
  55. }
  56.  
  57.  
  58. /**
  59.   * UI for updating details of the currently logged-in operator
  60.   */
  61. public function _extraDetails()
  62. {
  63. $view = new View('sprout/admin/my_settings/details');
  64.  
  65. $data = Form::loadFromSession('admin_my_settings');
  66. if (!$data) {
  67. Form::setData(AdminAuth::getDetails());
  68. }
  69.  
  70. return $view;
  71. }
  72.  
  73.  
  74. /**
  75.   * Action to update operator details for the currently logged-in operator
  76.   *
  77.   * @return void Redirects
  78.   */
  79. public function detailsAction()
  80. {
  81. Csrf::checkOrDie();
  82. $_SESSION['admin_my_settings']['field_values'] = Validator::trim($_POST);
  83.  
  84. $valid = new Validator($_POST);
  85. $valid->required(['name', 'email']);
  86. $valid->check('name', 'Validity::length', 1, 200);
  87. $valid->check('email', 'Validity::length', 1, 200);
  88. $valid->check('email', 'Validity::email');
  89. $valid->multipleCheck(['password1', 'password2'], 'Validity::allMatch');
  90.  
  91. if (!empty($_POST['password1']) and $_POST['password1'] === $_POST['password2']) {
  92. // Check old password is correct
  93. $result = AdminAuth::checkPassword($_POST['old_password'], AdminAuth::getId());
  94. if ($result === false) {
  95. $valid->addFieldError('old_password', 'Old password is incorrect');
  96. }
  97.  
  98. // Check password is complex enough
  99. $complexity = Security::passwordComplexity($_POST['password1'], 8, 2, true);
  100. if (!empty($complexity)) {
  101. $valid->addFieldError('password1', 'Not complex enough');
  102. $valid->addFieldError('password2', 'Not complex enough');
  103. Notification::error('Password does not meet complexity requirements:');
  104. foreach ($complexity as $c) {
  105. Notification::error(" \xC2\xA0 \xC2\xA0 " . $c);
  106. }
  107. }
  108. }
  109.  
  110. if ($valid->hasErrors()) {
  111. $_SESSION['admin_my_settings']['field_errors'] = $valid->getFieldErrors();
  112. Url::redirect('admin/extra/my_settings/details');
  113. }
  114.  
  115. Pdb::transact();
  116.  
  117. $data = array();
  118. $data['name'] = $_POST['name'];
  119. $data['email'] = $_POST['email'];
  120. $data['date_modified'] = Pdb::now();
  121. Pdb::update('operators', $data, ['id' => AdminAuth::getId()]);
  122.  
  123. if (!empty($_POST['password1'])) {
  124. AdminAuth::changePassword($_POST['password1'], AdminAuth::getId());
  125. }
  126.  
  127. Pdb::commit();
  128.  
  129. unset($_SESSION['admin_my_settings']);
  130. Notification::confirm('Settings have been saved');
  131. Url::redirect('admin/extra/my_settings/details');
  132. }
  133.  
  134.  
  135. /**
  136.   * Show a UI to either setup TFA or to disable TFA
  137.   */
  138. public function _extraTwoFactor()
  139. {
  140. $q = "SELECT tfa_method, username FROM ~operators WHERE id = ?";
  141. $operator = Pdb::query($q, [AdminAuth::getLocalId()], 'row');
  142.  
  143. if ($operator['tfa_method'] == 'none') {
  144. $goog = new GoogleAuthenticator();
  145.  
  146. if (empty($_SESSION['tfa_secret'])) {
  147. $_SESSION['tfa_secret'] = $goog->generateSecret();
  148. }
  149.  
  150. $issuer = Kohana::config('sprout.site_title') . ' admin';
  151. $qr_data = $goog->getQRData(
  152. $issuer, $operator['username'], $_SERVER['HTTP_HOST'], $_SESSION['tfa_secret']
  153. );
  154. $qr_img = $goog->getQRImageUrl($qr_data);
  155.  
  156. $view = new View('sprout/tfa/totp_setup');
  157. $view->action_url = 'admin/call/my_settings/tfaTotpSetupAction';
  158. $view->secret = $_SESSION['tfa_secret'];
  159. $view->qr_img = $qr_img;
  160.  
  161. } else {
  162. $view = new View('sprout/tfa/disable');
  163. $view->action_url = 'admin/call/my_settings/tfaDisableAction';
  164. }
  165.  
  166. return [
  167. 'title' => 'Two factor authentication',
  168. 'content' => $view->render(),
  169. ];
  170. }
  171.  
  172.  
  173. /**
  174.   * Setup TFA using the TOTP method
  175.   */
  176. public function tfaTotpSetupAction()
  177. {
  178. $goog = new GoogleAuthenticator();
  179. $success = $goog->checkCode($_SESSION['tfa_secret'], $_POST['code']);
  180.  
  181. if (!$success) {
  182. unset($_SESSION['tfa_secret']);
  183. Notification::error('Verifiction failed - please re-scan and try again');
  184. Url::redirect('admin/extra/my_settings/twoFactor');
  185. }
  186.  
  187. $data = [];
  188. $data['tfa_method'] = 'totp';
  189. $data['tfa_secret'] = $_SESSION['tfa_secret'];
  190. Pdb::update('operators', $data, ['id' => AdminAuth::getLocalId()]);
  191.  
  192. unset($_SESSION['tfa_secret']);
  193. Notification::confirm('Two factor auth has been enabled');
  194. Url::redirect('admin/extra/my_settings/twoFactor');
  195. }
  196.  
  197.  
  198. /**
  199.   * Disable TFA
  200.   */
  201. public function tfaDisableAction()
  202. {
  203. $data = [];
  204. $data['tfa_method'] = 'none';
  205. $data['tfa_secret'] = '';
  206. Pdb::update('operators', $data, ['id' => AdminAuth::getLocalId()]);
  207.  
  208. Notification::confirm('Two factor auth has been disabled');
  209. Url::redirect('admin/extra/my_settings/twoFactor');
  210. }
  211.  
  212. }
  213.