PageRenderTime 40ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 0ms

/web/concrete/controllers/single_page/login.php

https://gitlab.com/minotnepal/concrete5
PHP | 387 lines | 306 code | 42 blank | 39 comment | 65 complexity | bf5c7fb7f04158c2c2c2d60278c155ca MD5 | raw file
  1. <?php
  2. namespace Concrete\Controller\SinglePage;
  3. use Concrete\Core\Authentication\AuthenticationType;
  4. use Concrete\Core\Authentication\AuthenticationTypeFailureException;
  5. use Concrete\Core\Authentication\LoginException;
  6. use Concrete\Core\Routing\RedirectResponse;
  7. use Config;
  8. use Events;
  9. use Loader;
  10. use Localization;
  11. use Page;
  12. use PageController;
  13. use Permissions;
  14. use Session;
  15. use User;
  16. use UserAttributeKey;
  17. use UserInfo;
  18. use View;
  19. class Login extends PageController
  20. {
  21. public $helpers = array('form');
  22. protected $locales = array();
  23. public function on_before_render()
  24. {
  25. if ($this->error->has()) {
  26. $this->set('error', $this->error);
  27. }
  28. }
  29. /* automagically run by the controller once we're done with the current method */
  30. /* method is passed to this method, the method that we were just finished running */
  31. public function account_deactivated()
  32. {
  33. $this->error->add(t('This user is inactive. Please contact us regarding this account.'));
  34. }
  35. public function session_invalidated()
  36. {
  37. $this->error->add(t('Your session has expired. Please sign in again.'));
  38. }
  39. /**
  40. * Concrete5_Controller_Login::callback
  41. * Call an AuthenticationTypeController method throw a uri.
  42. * Use: /login/TYPE/METHOD/PARAM1/.../PARAM10
  43. *
  44. * @param string $type
  45. * @param string $method
  46. * @param null $a
  47. * @param null $b
  48. * @param null $c
  49. * @param null $d
  50. * @param null $e
  51. * @param null $f
  52. * @param null $g
  53. * @param null $h
  54. * @param null $i
  55. * @param null $j
  56. * @throws \Concrete\Core\Authentication\AuthenticationTypeFailureException
  57. * @throws \Exception
  58. */
  59. public function callback($type=null, $method = 'callback', $a = null, $b = null, $c = null, $d = null, $e = null, $f = null, $g = null, $h = null, $i = null, $j = null)
  60. {
  61. if (!$type) {
  62. return $this->view();
  63. }
  64. $at = AuthenticationType::getByHandle($type);
  65. if ($at) {
  66. $this->set('authType', $at);
  67. }
  68. if (!method_exists($at->controller, $method)) {
  69. return $this->view();
  70. }
  71. if ($method != 'callback') {
  72. if (!is_array($at->controller->apiMethods) || !in_array($method, $at->controller->apiMethods)) {
  73. return $this->view();
  74. }
  75. }
  76. try {
  77. $params = func_get_args();
  78. array_shift($params);
  79. array_shift($params);
  80. $this->view();
  81. $this->set('authTypeParams', $params);
  82. $this->set('authTypeElement', $method);
  83. } catch (\exception $e) {
  84. if ($e instanceof AuthenticationTypeFailureException) {
  85. // Throw again if this is a big`n
  86. throw $e;
  87. }
  88. $this->error->add($e->getMessage());
  89. }
  90. }
  91. /**
  92. * Concrete5_Controller_Login::authenticate
  93. * Authenticate the user using a specific authentication type.
  94. *
  95. * @param $type AuthenticationType handle
  96. */
  97. public function authenticate($type = '')
  98. {
  99. $valt = Loader::helper('validation/token');
  100. if (!$valt->validate('login_' . $type)) {
  101. $this->error->add($valt->getErrorMessage());
  102. } else {
  103. try {
  104. $at = AuthenticationType::getByHandle($type);
  105. $user = $at->controller->authenticate();
  106. if ($user && $user->isLoggedIn()) {
  107. $this->finishAuthentication($at);
  108. }
  109. } catch (\exception $e) {
  110. $this->error->add($e->getMessage());
  111. }
  112. }
  113. $this->view();
  114. }
  115. /**
  116. * @param AuthenticationType $type Required
  117. * @throws \Exception
  118. */
  119. public function finishAuthentication(/* AuthenticationType */
  120. $type = null
  121. )
  122. {
  123. if (!$type || !($type instanceof AuthenticationType)) {
  124. return $this->view();
  125. }
  126. $u = new User();
  127. if (Config::get('concrete.i18n.choose_language_login')) {
  128. $userLocale = $this->post('USER_LOCALE');
  129. if (is_string($userLocale) && ($userLocale !== '')) {
  130. if ($userLocale !== 'en_US') {
  131. $availableLocales = Localization::getAvailableInterfaceLanguages();
  132. if (!in_array($userLocale, $availableLocales)) {
  133. $userLocale = '';
  134. }
  135. }
  136. if ($userLocale !== '') {
  137. if (Localization::activeLocale() !== $userLocale) {
  138. Localization::changeLocale($userLocale);
  139. }
  140. $u->setUserDefaultLanguage($userLocale);
  141. }
  142. }
  143. }
  144. $ui = UserInfo::getByID($u->getUserID());
  145. $aks = UserAttributeKey::getRegistrationList();
  146. $unfilled = array_values(
  147. array_filter(
  148. $aks,
  149. function ($ak) use ($ui) {
  150. return $ak->isAttributeKeyRequiredOnRegister() && !is_object($ui->getAttributeValueObject($ak));
  151. }));
  152. if (count($unfilled)) {
  153. $u->logout(false);
  154. if (!$this->error) {
  155. $this->on_start();
  156. }
  157. $this->set('required_attributes', $unfilled);
  158. $this->set('u', $u);
  159. Session::set('uRequiredAttributeUser', $u->getUserID());
  160. Session::set('uRequiredAttributeUserAuthenticationType', $type->getAuthenticationTypeHandle());
  161. $this->view();
  162. echo $this->getViewObject()->render();
  163. exit;
  164. }
  165. $u->setLastAuthType($type);
  166. $ue = new \Concrete\Core\User\Event\User($u);
  167. Events::dispatch('on_user_login', $ue);
  168. $this->chooseRedirect();
  169. }
  170. public function on_start()
  171. {
  172. $this->error = Loader::helper('validation/error');
  173. $this->set('valt', Loader::helper('validation/token'));
  174. if (Config::get('concrete.user.registration.email_registration')) {
  175. $this->set('uNameLabel', t('Email Address'));
  176. } else {
  177. $this->set('uNameLabel', t('Username'));
  178. }
  179. $txt = Loader::helper('text');
  180. if (strlen(
  181. $_GET['uName'])
  182. ) { // pre-populate the username if supplied, if its an email address with special characters the email needs to be urlencoded first,
  183. $this->set("uName", trim($txt->email($_GET['uName'])));
  184. }
  185. $languages = array();
  186. $locales = array();
  187. if (Config::get('concrete.i18n.choose_language_login')) {
  188. $languages = Localization::getAvailableInterfaceLanguages();
  189. if (count($languages) > 0) {
  190. array_unshift($languages, 'en_US');
  191. }
  192. $locales = array();
  193. foreach ($languages as $lang) {
  194. $locales[$lang] = \Punic\Language::getName($lang, $lang);
  195. }
  196. asort($locales);
  197. $locales = array_merge(array('' => tc('Default locale', '** Default')), $locales);
  198. }
  199. $this->locales = $locales;
  200. $this->set('locales', $locales);
  201. }
  202. public function chooseRedirect()
  203. {
  204. if (!$this->error) {
  205. $this->error = Loader::helper('validation/error');
  206. }
  207. $nh = Loader::helper('validation/numbers');
  208. $navigation = Loader::helper('navigation');
  209. $rUrl = false;
  210. $u = new User(); // added for the required registration attribute change above. We recalc the user and make sure they're still logged in
  211. if ($u->isRegistered()) {
  212. if ($u->config('NEWSFLOW_LAST_VIEWED') == 'FIRSTRUN') {
  213. $u->saveConfig('NEWSFLOW_LAST_VIEWED', 0);
  214. }
  215. do {
  216. // redirect to original destination
  217. if (Session::has('rcID')) {
  218. $rcID = Session::get('rcID');
  219. if ($nh->integer($rcID)) {
  220. $rc = Page::getByID($rcID);
  221. } elseif (strlen($rcID)) {
  222. $rcID = trim($rcID, '/');
  223. $rc = Page::getByPath('/' . $rcID);
  224. }
  225. if ($rc instanceof Page && !$rc->isError()) {
  226. $rUrl = $navigation->getLinkToCollection($rc);
  227. break;
  228. }
  229. }
  230. // admin to dashboard?
  231. $dash = Page::getByPath("/dashboard", "RECENT");
  232. $dbp = new Permissions($dash);
  233. //should administrator be redirected to dashboard? defaults to yes if not set.
  234. $adminToDash = intval(Config::get('concrete.misc.login_admin_to_dashboard'));
  235. if ($dbp->canRead() && $adminToDash) {
  236. if(!$rc instanceof Page || $rc->isError()){
  237. $rc = $dash;
  238. }
  239. $rUrl = $navigation->getLinkToCollection($rc);
  240. break;
  241. }
  242. //options set in dashboard/users/registration
  243. $login_redirect_mode = Config::get('concrete.misc.login_redirect');
  244. //redirect to user profile
  245. if ($login_redirect_mode == 'PROFILE' && Config::get('concrete.user.profiles_enabled')) {
  246. $rUrl = View::url('/members/profile/', $u->getUserID());
  247. break;
  248. }
  249. //redirect to custom page
  250. $login_redirect_cid = intval(Config::get('concrete.misc.login_redirect_cid'));
  251. if ($login_redirect_mode == 'CUSTOM' && $login_redirect_cid > 0) {
  252. $rc = Page::getByID($login_redirect_cid);
  253. if ($rc instanceof Page && !$rc->isError()) {
  254. $rUrl = $navigation->getLinkToCollection($rc);
  255. break;
  256. }
  257. }
  258. break;
  259. } while (false);
  260. if ($rUrl) {
  261. $r = new RedirectResponse($rUrl);
  262. $r->send();
  263. exit;
  264. } else {
  265. $this->redirect('/');
  266. }
  267. } else {
  268. $this->error->add(t('User is not registered. Check your authentication controller.'));
  269. $u->logout();
  270. }
  271. }
  272. public function view($type = null, $element = 'form')
  273. {
  274. $this->requireAsset('javascript', 'backstretch');
  275. $this->set('authTypeParams', $this->getSets());
  276. if (strlen($type)) {
  277. $at = AuthenticationType::getByHandle($type);
  278. $this->set('authType', $at);
  279. $this->set('authTypeElement', $element);
  280. }
  281. }
  282. public function fill_attributes()
  283. {
  284. try {
  285. if (!Session::has('uRequiredAttributeUser') ||
  286. intval(Session::get('uRequiredAttributeUser')) < 1 ||
  287. !Session::has('uRequiredAttributeUserAuthenticationType') ||
  288. !Session::get('uRequiredAttributeUserAuthenticationType')
  289. ) {
  290. Session::remove('uRequiredAttributeUser');
  291. Session::remove('uRequiredAttributeUserAuthenticationType');
  292. throw new \Exception(t('Invalid Request, please attempt login again.'));
  293. }
  294. User::loginByUserID(Session::get('uRequiredAttributeUser'));
  295. Session::remove('uRequiredAttributeUser');
  296. $u = new User;
  297. $at = AuthenticationType::getByHandle(Session::get('uRequiredAttributeUserAuthenticationType'));
  298. Session::remove('uRequiredAttributeUserAuthenticationType');
  299. if (!$at) {
  300. throw new \Exception(t("Invalid Authentication Type"));
  301. }
  302. $ui = UserInfo::getByID($u->getUserID());
  303. $aks = UserAttributeKey::getRegistrationList();
  304. $unfilled = array_values(
  305. array_filter(
  306. $aks,
  307. function ($ak) use ($ui) {
  308. return $ak->isAttributeKeyRequiredOnRegister() && !is_object($ui->getAttributeValueObject($ak));
  309. }));
  310. $saveAttributes = array();
  311. foreach ($unfilled as $attribute) {
  312. $err = $attribute->validateAttributeForm();
  313. if ($err == false) {
  314. $this->error->add(t('The field "%s" is required', $attribute->getAttributeKeyDisplayName()));
  315. } elseif ($err instanceof \Concrete\Core\Error\Error) {
  316. $this->error->add($err);
  317. } else {
  318. $saveAttributes[] = $attribute;
  319. }
  320. }
  321. if (count($saveAttributes) > 0) {
  322. $ui->saveUserAttributesForm($saveAttributes);
  323. }
  324. $this->finishAuthentication($at);
  325. } catch (\Exception $e) {
  326. $this->error->add($e->getMessage());
  327. }
  328. }
  329. public function logout($token = false)
  330. {
  331. if (Loader::helper('validation/token')->validate('logout', $token)) {
  332. $u = new User();
  333. $u->logout();
  334. $this->redirect('/');
  335. }
  336. }
  337. public function forward($cID = 0)
  338. {
  339. $nh = Loader::helper('validation/numbers');
  340. if ($nh->integer($cID) && intval($cID) > 0) {
  341. $this->set('rcID', intval($cID));
  342. Session::set('rcID', intval($cID));
  343. }
  344. }
  345. }