PageRenderTime 46ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/wa-system/controller/waLoginAction.class.php

http://github.com/webasyst/webasyst-framework
PHP | 283 lines | 227 code | 22 blank | 34 comment | 64 complexity | 0bb40baa70c9197f97371662962e7745 MD5 | raw file
Possible License(s): LGPL-3.0, CC-BY-3.0, BSD-3-Clause, MIT
  1. <?php
  2. abstract class waLoginAction extends waViewAction
  3. {
  4. public function execute()
  5. {
  6. $this->view->setOptions(array('left_delimiter' => '{', 'right_delimiter' => '}'));
  7. // Set locale if specified
  8. if ( ( $locale = waRequest::get('locale')) || ( $locale = wa()->getStorage()->read('locale'))) {
  9. wa()->setLocale($locale);
  10. wa()->getStorage()->write('locale', $locale);
  11. }
  12. // load webasyst locale and make it default for [``] in templates
  13. wa('webasyst')->getConfig()->setLocale(wa()->getLocale(), true);
  14. $title = $this->getTitle();
  15. $title_style = $this->getTitleStyle();
  16. // Password recovery form to enter login/email
  17. if (waRequest::request('forgot')) {
  18. $title .= ' - '._ws('Password recovery');
  19. if (waRequest::method() == 'post' && !waRequest::post('ignore')) {
  20. $this->forgot();
  21. }
  22. $this->view->assign('type', 'forgot');
  23. }
  24. // Password recovery form to enter new password
  25. else if (waRequest::get('password') && waRequest::get('key')) {
  26. $this->recovery();
  27. $this->view->assign('type', 'password');
  28. }
  29. // Voodoo magic: reload page when user performs an AJAX request after session died.
  30. else if (waRequest::isXMLHttpRequest() && waRequest::param('secure')) {
  31. //
  32. // The idea behind this is quite complicated.
  33. //
  34. // When browser expects JSON and gets this response then the error handler is called.
  35. // Default error handler (see wa.core.js) looks for the wa-session-expired header
  36. // and reloads the page when it's found.
  37. //
  38. // On the other hand, when browser expects HTML, it's most likely to insert it to the DOM.
  39. // In this case <script> gets executed and browser reloads the whole layout to show login page.
  40. // (This is also the reason to use 200 HTTP response code here: no error handler required at all.)
  41. //
  42. header('wa-session-expired: 1');
  43. echo _ws('Session has expired. Please reload current page and log in again.').'<script>window.location.reload();</script>';
  44. exit;
  45. }
  46. // Enter login/email and password
  47. else {
  48. // Save referrer to session
  49. $ref = waRequest::server('HTTP_REFERER');
  50. if(waRequest::get('back_to') && $ref) {
  51. wa()->getStorage()->write('login_back_on_cancel', $ref);
  52. } else if (!$ref) {
  53. wa()->getStorage()->remove('login_back_on_cancel');
  54. }
  55. $this->view->assign('type', '');
  56. $this->view->assign('back_on_cancel', wa()->getStorage()->read('login_back_on_cancel'));
  57. $this->view->assign('login', waRequest::post('login', $this->getStorage()->read('auth_login')));
  58. }
  59. $this->view->assign('title', $title);
  60. $this->view->assign('title_style', $title_style);
  61. $app_settings_model = new waAppSettingsModel();
  62. $background = $app_settings_model->get('webasyst', 'auth_form_background');
  63. $stretch = $app_settings_model->get('webasyst', 'auth_form_background_stretch');
  64. if ($background) {
  65. $background = 'wa-data/public/webasyst/'.$background;
  66. }
  67. $this->view->assign('stretch', $stretch);
  68. $this->view->assign('background', $background);
  69. $this->view->assign('remember_enabled', $app_settings_model->get('webasyst', 'rememberme', 1));
  70. if (waRequest::method() == 'get') {
  71. $this->view->assign('remember', waRequest::cookie('remember'));
  72. }
  73. $auth = $this->getAuth();
  74. $authorized = false;
  75. try {
  76. // Already authorized from session?
  77. if ($this->getUser()->isAuth()) {
  78. if (!$auth->getOption('is_user') || $this->getUser()->get('is_user')) {
  79. $authorized = true;
  80. }
  81. }
  82. // Try to authorize from POST or cookies
  83. if (!$authorized && $auth->auth()) {
  84. $authorized = true;
  85. }
  86. if ($authorized) {
  87. // Final check: is user banned?
  88. if (wa()->getUser()->get('is_banned')) {
  89. wa()->getAuth()->clearAuth();
  90. throw new waException(_w('Access denied'));
  91. }
  92. // Proceed with successfull authorization
  93. $this->getStorage()->remove('auth_login');
  94. $this->afterAuth();
  95. exit;
  96. }
  97. } catch (waException $e) {
  98. $this->view->assign('error', $e->getMessage());
  99. }
  100. $this->view->assign('options', $auth->getOptions());
  101. if ($this->template === null) {
  102. if (waRequest::isMobile()) {
  103. $this->template = 'LoginMobile.html';
  104. } else {
  105. $this->template = 'Login.html';
  106. }
  107. $this->template = wa()->getAppPath('templates/actions/login/', 'webasyst').$this->template;
  108. }
  109. }
  110. public function getTitle()
  111. {
  112. if ( ( $title = $this->getConfig()->getOption('login_form_title'))) {
  113. return waLocale::fromArray($title);
  114. }
  115. return wa()->getSetting('name', 'Webasyst', 'webasyst');
  116. }
  117. public function getTitleStyle()
  118. {
  119. return $this->getConfig()->getOption('login_form_title_style');
  120. }
  121. /**
  122. * @return waAuth
  123. */
  124. protected function getAuth()
  125. {
  126. return waSystem::getInstance()->getAuth();
  127. }
  128. protected function forgot()
  129. {
  130. $login = waRequest::post('login');
  131. $contact_model = new waContactModel();
  132. $auth = $this->getAuth();
  133. $is_user = $auth->getOption('is_user');
  134. if (strpos($login, '@')) {
  135. $sql = "SELECT c.* FROM wa_contact c
  136. JOIN wa_contact_emails e ON c.id = e.contact_id
  137. WHERE ".($is_user ? "c.is_user = 1 AND " : "")."e.email LIKE s:email AND e.sort = 0
  138. ORDER BY c.id LIMIT 1";
  139. $contact_info = $contact_model->query($sql, array('email' => $login))->fetch();
  140. $this->view->assign('email', true);
  141. } else {
  142. $contact_info = $contact_model->getByField('login', $login);
  143. }
  144. // if contact found and it is user
  145. if ($contact_info && (!$is_user || $contact_info['is_user'])) {
  146. $contact = new waContact($contact_info['id']);
  147. $contact->setCache($contact_info);
  148. // Is user banned?
  149. if ($contact->get('is_banned')) {
  150. $this->view->assign('error', _w('Password recovery for this email has been banned.'));
  151. } else
  152. // get defaul email to send mail
  153. if ($to = $contact->get('email', 'default')) {
  154. // Send message in user's language
  155. if ($contact['locale']) {
  156. wa()->setLocale($contact['locale']);
  157. waLocale::loadByDomain('webasyst', wa()->getLocale());
  158. }
  159. // generate unique key and save in contact settings
  160. $hash = md5(uniqid(null, true));
  161. $contact_settings_model = new waContactSettingsModel();
  162. $contact_settings_model->set($contact['id'], 'webasyst', 'forgot_password_hash', $hash);
  163. $hash = substr($hash, 0, 16).$contact['id'].substr($hash, -16);
  164. // url to recovery password
  165. if ($this->getApp() === 'webasyst') {
  166. $url = wa()->getAppUrl().'?password=1&key='.$hash;
  167. } else {
  168. $url = $this->getConfig()->getCurrentUrl();
  169. $url = preg_replace('/\?.*$/i', '', $url);
  170. $url .= '?password=1&key='.$hash;
  171. }
  172. $this->view->assign('url', $this->getConfig()->getHostUrl().$url);
  173. // send email
  174. $subject = _ws("Password recovery");
  175. $template_file = $this->getConfig()->getConfigPath('mail/RecoveringPassword.html', true, 'webasyst');
  176. if (file_exists($template_file)) {
  177. $body = $this->view->fetch($template_file);
  178. } else {
  179. $body = $this->view->fetch(wa()->getAppPath('templates/mail/RecoveringPassword.html', 'webasyst'));
  180. }
  181. $this->view->clearAllAssign();
  182. $mail_error = false;
  183. try {
  184. $m = new waMailMessage($subject, $body);
  185. $m->setTo($to);
  186. if ($m->send()) {
  187. $this->view->assign('success', true);
  188. } else {
  189. $mail_error = true;
  190. }
  191. } catch (Exception $e) {
  192. $mail_error = true;
  193. }
  194. if ($mail_error) {
  195. $this->view->assign('error', _ws('Sorry, we can not recover password for this login name or email. Please refer to your system administrator.'));
  196. }
  197. } else {
  198. $this->view->assign('error', _w('Sorry, we can not recover password for this login name or email. Please refer to your system administrator.'));
  199. }
  200. } else {
  201. if ($auth->getOption('login') == 'email') {
  202. $this->view->assign('error', _w('No user with this email has been found.'));
  203. } else {
  204. $this->view->assign('error', _w('No user with this login name or email has been found.'));
  205. }
  206. }
  207. }
  208. protected function recovery()
  209. {
  210. $hash = waRequest::get('key');
  211. $error = true;
  212. if ($hash && strlen($hash) > 32) {
  213. $contact_id = substr($hash, 16, -16);
  214. $contact_settings_model = new waContactSettingsModel();
  215. $contact_hash = $contact_settings_model->getOne($contact_id, 'webasyst', 'forgot_password_hash');
  216. $contact_hash = substr($contact_hash, 0, 16).$contact_id.substr($contact_hash, -16);
  217. $contact_model = new waContactModel();
  218. $contact_info = $contact = $contact_model->getById($contact_id);
  219. if ($contact_info && $hash === $contact_hash)
  220. {
  221. // Show the form in user's language
  222. if ($contact_info['locale']) {
  223. wa()->setLocale($contact_info['locale']);
  224. waLocale::loadByDomain('webasyst', wa()->getLocale());
  225. }
  226. $auth = $this->getAuth();
  227. if ($auth->getOption('login') == 'login') {
  228. $login = $contact_info['login'];
  229. } elseif ($auth->getOption('login') == 'email') {
  230. $email_model = new waContactEmailsModel();
  231. $email = $email_model->getByField(array('contact_id' => $contact_id, 'sort' => 0));
  232. $login = $email['email'];
  233. }
  234. $this->view->assign('login', $login);
  235. if (waRequest::method() == 'post') {
  236. $password = waRequest::post('password');
  237. $password_confirm = waRequest::post('password_confirm');
  238. if ($password === $password_confirm) {
  239. $user = new waUser($contact_id);
  240. $user['password'] = $password;
  241. $user->save();
  242. $contact_settings_model->delete($contact_id, 'webasyst', 'forgot_password_hash');
  243. // auth
  244. $this->getAuth()->auth(array(
  245. 'login' => $login,
  246. 'password' => $password
  247. ));
  248. $this->redirect(wa()->getAppUrl());
  249. } else {
  250. $this->view->assign('error', _w('Passwords do not match'));
  251. }
  252. }
  253. $error = false;
  254. }
  255. }
  256. if ($error) {
  257. $this->redirect($this->getConfig()->getBackendUrl(true));
  258. }
  259. }
  260. abstract protected function afterAuth();
  261. }