PageRenderTime 27ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/tine20/Tinebase/Controller.php

https://github.com/testruby/Tine-2.0-Open-Source-Groupware-and-CRM
PHP | 353 lines | 170 code | 47 blank | 136 comment | 42 complexity | 0bf308e19244ba4e075dead1e5bae909 MD5 | raw file
  1. <?php
  2. /**
  3. * Tine 2.0
  4. *
  5. * @package Tinebase
  6. * @subpackage Server
  7. * @license http://www.gnu.org/licenses/agpl.html AGPL Version 3
  8. * @copyright Copyright (c) 2007-2011 Metaways Infosystems GmbH (http://www.metaways.de)
  9. * @author Lars Kneschke <l.kneschke@metaways.de>
  10. *
  11. */
  12. /**
  13. * the class provides functions to handle applications
  14. *
  15. * @package Tinebase
  16. * @subpackage Server
  17. */
  18. class Tinebase_Controller extends Tinebase_Controller_Abstract
  19. {
  20. /**
  21. * holds the instance of the singleton
  22. *
  23. * @var Tinebase_Controller
  24. */
  25. private static $_instance = NULL;
  26. /**
  27. * application name
  28. *
  29. * @var string
  30. */
  31. protected $_applicationName = 'Tinebase';
  32. /**
  33. * the constructor
  34. *
  35. */
  36. private function __construct()
  37. {
  38. }
  39. /**
  40. * don't clone. Use the singleton.
  41. *
  42. */
  43. private function __clone() {}
  44. /**
  45. * the singleton pattern
  46. *
  47. * @return Tinebase_Controller
  48. */
  49. public static function getInstance()
  50. {
  51. if (self::$_instance === NULL) {
  52. self::$_instance = new Tinebase_Controller;
  53. }
  54. return self::$_instance;
  55. }
  56. /**
  57. * create new user session
  58. *
  59. * @param string $_loginname
  60. * @param string $_password
  61. * @param string $_ipAddress
  62. * @param string $_clientIdString
  63. * @return bool
  64. */
  65. public function login($_loginname, $_password, $_ipAddress, $_clientIdString = NULL)
  66. {
  67. $authResult = Tinebase_Auth::getInstance()->authenticate($_loginname, $_password);
  68. $accessLog = new Tinebase_Model_AccessLog(array(
  69. 'sessionid' => session_id(),
  70. 'ip' => $_ipAddress,
  71. 'li' => Tinebase_DateTime::now()->get(Tinebase_Record_Abstract::ISO8601LONG),
  72. 'result' => $authResult->getCode(),
  73. 'clienttype' => $_clientIdString,
  74. ), TRUE);
  75. $user = NULL;
  76. if ($accessLog->result == Tinebase_Auth::SUCCESS) {
  77. $user = $this->_getLoginUser($authResult->getIdentity(), $accessLog);
  78. if ($user !== NULL) {
  79. $this->_checkUserStatus($user, $accessLog);
  80. }
  81. }
  82. if ($accessLog->result === Tinebase_Auth::SUCCESS && $user !== NULL && $user->accountStatus === Tinebase_User::STATUS_ENABLED) {
  83. $this->_initUser($user, $accessLog, $_password);
  84. $result = true;
  85. } else {
  86. $this->_loginFailed($_loginname, $accessLog);
  87. $result = false;
  88. }
  89. Tinebase_AccessLog::getInstance()->create($accessLog);
  90. return $result;
  91. }
  92. /**
  93. * get login user
  94. *
  95. * @param string $_username
  96. * @param Tinebase_Model_AccessLog $_accessLog
  97. * @return Tinebase_Model_FullUser|NULL
  98. */
  99. protected function _getLoginUser($_username, Tinebase_Model_AccessLog $_accessLog)
  100. {
  101. $accountsController = Tinebase_User::getInstance();
  102. $user = NULL;
  103. try {
  104. // does the user exist in the user database?
  105. if ($accountsController instanceof Tinebase_User_Interface_SyncAble) {
  106. /**
  107. * catch all exceptions during user data sync
  108. * either it's the first sync and no user data get synchronized or
  109. * we can work with the data synced during previous login
  110. */
  111. try {
  112. Tinebase_User::syncUser($_username);
  113. } catch (Exception $e) {
  114. Tinebase_Core::getLogger()->crit(__METHOD__ . '::' . __LINE__ . ' Failed to sync user data for: ' . $_username . ' reason: ' . $e->getMessage());
  115. if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' ' . $e->getTraceAsString());
  116. }
  117. }
  118. $user = $accountsController->getFullUserByLoginName($_username);
  119. } catch (Tinebase_Exception_NotFound $e) {
  120. if (Tinebase_Core::isLogLevel(Zend_Log::CRIT)) Tinebase_Core::getLogger()->crit(__METHOD__ . '::' . __LINE__ . ' Account ' . $_username . ' not found in account storage.');
  121. $_accessLog->result = Tinebase_Auth::FAILURE_IDENTITY_NOT_FOUND;
  122. } catch (Zend_Db_Adapter_Exception $zdae) {
  123. if (Tinebase_Core::isLogLevel(Zend_Log::CRIT)) Tinebase_Core::getLogger()->crit(__METHOD__ . '::' . __LINE__ . ' Some database connection failed: ' . $zdae->getMessage());
  124. $_accessLog->result = Tinebase_Auth::FAILURE_DATABASE_CONNECTION;
  125. }
  126. return $user;
  127. }
  128. /**
  129. * check user status
  130. *
  131. * @param Tinebase_Model_FullUser $_user
  132. * @param Tinebase_Model_AccessLog $_accessLog
  133. */
  134. protected function _checkUserStatus(Tinebase_Model_FullUser $_user, Tinebase_Model_AccessLog $_accessLog)
  135. {
  136. // is the user enabled?
  137. if ($_accessLog->result == Tinebase_Auth::SUCCESS && $_user->accountStatus !== Tinebase_User::STATUS_ENABLED) {
  138. // is the account enabled?
  139. if ($_user->accountStatus == Tinebase_User::STATUS_DISABLED) {
  140. if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' Account: '. $_user->accountLoginName . ' is disabled');
  141. $_accessLog->result = Tinebase_Auth::FAILURE_DISABLED;
  142. }
  143. // is the account expired?
  144. else if ($_user->accountStatus == Tinebase_User::STATUS_EXPIRED) {
  145. if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' Account: '. $_user->accountLoginName . ' password is expired');
  146. $_accessLog->result = Tinebase_Auth::FAILURE_PASSWORD_EXPIRED;
  147. }
  148. // too many login failures?
  149. else if ($_user->accountStatus == Tinebase_User::STATUS_BLOCKED) {
  150. if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' Account: '. $_user->accountLoginName . ' is blocked');
  151. $_accessLog->result = Tinebase_Auth::FAILURE_BLOCKED;
  152. }
  153. }
  154. }
  155. /**
  156. * init user session
  157. *
  158. * @param Tinebase_Model_FullUser $_user
  159. * @param Tinebase_Model_AccessLog $_accessLog
  160. * @param string $_password
  161. */
  162. protected function _initUser(Tinebase_Model_FullUser $_user, Tinebase_Model_AccessLog $_accessLog, $_password)
  163. {
  164. if ($_accessLog->result === Tinebase_Auth::SUCCESS && $_user->accountStatus === Tinebase_User::STATUS_ENABLED) {
  165. $this->_initUserSession($_user);
  166. Tinebase_Core::set(Tinebase_Core::USER, $_user);
  167. $credentialCache = Tinebase_Auth_CredentialCache::getInstance()->cacheCredentials($_user->accountLoginName, $_password);
  168. Tinebase_Core::set(Tinebase_Core::USERCREDENTIALCACHE, $credentialCache);
  169. // need to set locale again if user preference is available because locale might not be set correctly during loginFromPost
  170. $userPrefLocaleString = Tinebase_Core::getPreference()->{Tinebase_Preference::LOCALE};
  171. if ($userPrefLocaleString !== 'auto') {
  172. Tinebase_Core::setupUserLocale($userPrefLocaleString);
  173. }
  174. $_user->setLoginTime($_accessLog->ip);
  175. $_accessLog->sessionid = session_id();
  176. $_accessLog->login_name = $_user->accountLoginName;
  177. $_accessLog->account_id = $_user->getId();
  178. }
  179. }
  180. /**
  181. * init session after successful login
  182. *
  183. * @param Tinebase_Model_FullUser $_user
  184. */
  185. protected function _initUserSession(Tinebase_Model_FullUser $_user)
  186. {
  187. if (Tinebase_Config::getInstance()->getConfig(Tinebase_Config::SESSIONUSERAGENTVALIDATION, NULL, TRUE)->value) {
  188. Zend_Session::registerValidator(new Zend_Session_Validator_HttpUserAgent());
  189. } else {
  190. Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' User agent validation disabled.');
  191. }
  192. if (Tinebase_Config::getInstance()->getConfig(Tinebase_Config::SESSIONIPVALIDATION, NULL, TRUE)->value) {
  193. Zend_Session::registerValidator(new Zend_Session_Validator_IpAddress());
  194. } else {
  195. Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' Session ip validation disabled.');
  196. }
  197. Zend_Session::regenerateId();
  198. Tinebase_Core::getSession()->currentAccount = $_user;
  199. }
  200. /**
  201. * login failed
  202. *
  203. * @param unknown_type $_loginname
  204. * @param Tinebase_Model_AccessLog $_accessLog
  205. */
  206. protected function _loginFailed($_loginname, Tinebase_Model_AccessLog $_accessLog)
  207. {
  208. Tinebase_User::getInstance()->setLastLoginFailure($_loginname);
  209. $_accessLog->login_name = $_loginname;
  210. $_accessLog->lo = Tinebase_DateTime::now()->get(Tinebase_Record_Abstract::ISO8601LONG);
  211. Zend_Session::destroy();
  212. sleep(mt_rand(2,5));
  213. }
  214. /**
  215. * authenticate user but don't log in
  216. *
  217. * @param string $_loginname
  218. * @param string $_password
  219. * @param string $_ipAddress
  220. * @param string $_clientIdString
  221. * @return bool
  222. */
  223. public function authenticate($_loginname, $_password, $_ipAddress, $_clientIdString = NULL)
  224. {
  225. $result = $this->login($_loginname, $_password, $_ipAddress, $_clientIdString);
  226. /**
  227. * we unset the Zend_Auth session variable. This way we keep the session,
  228. * but the user is not logged into Tine 2.0
  229. * we use this to validate passwords for OpenId for example
  230. */
  231. unset($_SESSION['Zend_Auth']);
  232. unset(Tinebase_Core::getSession()->currentAccount);
  233. return $result;
  234. }
  235. /**
  236. * change user password
  237. *
  238. * @param string $_oldPassword
  239. * @param string $_newPassword
  240. * @throws Tinebase_Exception_AccessDenied
  241. * @throws Tinebase_Exception_InvalidArgument
  242. */
  243. public function changePassword($_oldPassword, $_newPassword)
  244. {
  245. //error_log(print_r(Tinebase_Core::getUser()->toArray(), true));
  246. // check config setting
  247. if (!Tinebase_User::getBackendConfiguration('changepw', true)) {
  248. throw new Tinebase_Exception_AccessDenied('Password change not allowed.');
  249. }
  250. $loginName = Tinebase_Core::getUser()->accountLoginName;
  251. if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " change password for $loginName");
  252. if (!Tinebase_Auth::getInstance()->isValidPassword($loginName, $_oldPassword)) {
  253. throw new Tinebase_Exception_InvalidArgument('Old password is wrong.');
  254. }
  255. Tinebase_User::getInstance()->setPassword(Tinebase_Core::getUser(), $_newPassword, true, false);
  256. }
  257. /**
  258. * destroy session
  259. *
  260. * @return void
  261. */
  262. public function logout($_ipAddress)
  263. {
  264. if (Tinebase_Core::isRegistered(Tinebase_Core::USER)) {
  265. $currentAccount = Tinebase_Core::getUser();
  266. if (is_object($currentAccount)) {
  267. Tinebase_AccessLog::getInstance()->setLogout(session_id(), $_ipAddress);
  268. }
  269. }
  270. Zend_Session::destroy();
  271. }
  272. /**
  273. * gets image info and data
  274. *
  275. * @param string $_application application which manages the image
  276. * @param string $_identifier identifier of image/record
  277. * @param string $_location optional additional identifier
  278. * @return Tinebase_Model_Image
  279. * @throws Tinebase_Exception_NotFound
  280. * @throws Tinebase_Exception_UnexpectedValue
  281. */
  282. public function getImage($_application, $_identifier, $_location = '')
  283. {
  284. $appController = Tinebase_Core::getApplicationInstance($_application);
  285. if (!method_exists($appController, 'getImage')) {
  286. throw new Tinebase_Exception_NotFound("$_application has no getImage function.");
  287. }
  288. $image = $appController->getImage($_identifier, $_location);
  289. if (!$image instanceof Tinebase_Model_Image) {
  290. throw new Tinebase_Exception_UnexpectedValue("$_application returned invalid image.");
  291. }
  292. return $image;
  293. }
  294. /**
  295. * remove obsolete/outdated stuff from cache
  296. * notes: CLEANING_MODE_OLD -> removes obsolete cache entries (files for file cache)
  297. * CLEANING_MODE_ALL -> removes complete cache structure (directories for file cache) + cache entries
  298. *
  299. * @param string $_mode
  300. */
  301. public function cleanupCache($_mode = Zend_Cache::CLEANING_MODE_OLD)
  302. {
  303. if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' Cleaning up the cache (mode: ' . $_mode . ')');
  304. Tinebase_Core::getCache()->clean($_mode);
  305. }
  306. }