PageRenderTime 55ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/zabbix-2.0.1/frontends/php/api/classes/CUser.php

#
PHP | 1223 lines | 861 code | 175 blank | 187 comment | 187 complexity | 0f086e2bbcb4642ab8023f65271c761a MD5 | raw file
Possible License(s): GPL-2.0, AGPL-1.0
  1. <?php
  2. /*
  3. ** Zabbix
  4. ** Copyright (C) 2000-2012 Zabbix SIA
  5. **
  6. ** This program is free software; you can redistribute it and/or modify
  7. ** it under the terms of the GNU General Public License as published by
  8. ** the Free Software Foundation; either version 2 of the License, or
  9. ** (at your option) any later version.
  10. **
  11. ** This program is distributed in the hope that it will be useful,
  12. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. ** GNU General Public License for more details.
  15. **
  16. ** You should have received a copy of the GNU General Public License
  17. ** along with this program; if not, write to the Free Software
  18. ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  19. **/
  20. /**
  21. * @package API
  22. */
  23. class CUser extends CZBXAPI {
  24. protected $tableName = 'users';
  25. protected $tableAlias = 'u';
  26. /**
  27. * Get Users data
  28. *
  29. * @param array $options
  30. * @param array $options['nodeids'] filter by Node IDs
  31. * @param array $options['usrgrpids'] filter by UserGroup IDs
  32. * @param array $options['userids'] filter by User IDs
  33. * @param boolean $options['type'] filter by User type [ USER_TYPE_ZABBIX_USER: 1, USER_TYPE_ZABBIX_ADMIN: 2, USER_TYPE_SUPER_ADMIN: 3 ]
  34. * @param boolean $options['selectUsrgrps'] extend with UserGroups data for each User
  35. * @param boolean $options['getAccess'] extend with access data for each User
  36. * @param boolean $options['count'] output only count of objects in result. ( result returned in property 'rowscount' )
  37. * @param string $options['pattern'] filter by Host name containing only give pattern
  38. * @param int $options['limit'] output will be limited to given number
  39. * @param string $options['sortfield'] output will be sorted by given property [ 'userid', 'alias' ]
  40. * @param string $options['sortorder'] output will be sorted in given order [ 'ASC', 'DESC' ]
  41. * @return array
  42. */
  43. public function get($options = array()) {
  44. $result = array();
  45. $userType = self::$userData['type'];
  46. // allowed columns for sorting
  47. $sortColumns = array('userid', 'alias');
  48. $sqlParts = array(
  49. 'select' => array('users' => 'u.userid'),
  50. 'from' => array('users' => 'users u'),
  51. 'where' => array(),
  52. 'order' => array(),
  53. 'limit' => null
  54. );
  55. $defOptions = array(
  56. 'nodeids' => null,
  57. 'usrgrpids' => null,
  58. 'userids' => null,
  59. 'mediaids' => null,
  60. 'mediatypeids' => null,
  61. // filter
  62. 'filter' => null,
  63. 'search' => null,
  64. 'searchByAny' => null,
  65. 'startSearch' => null,
  66. 'excludeSearch' => null,
  67. 'searchWildcardsEnabled' => null,
  68. // output
  69. 'output' => API_OUTPUT_REFER,
  70. 'editable' => null,
  71. 'selectUsrgrps' => null,
  72. 'selectMedias' => null,
  73. 'selectMediatypes' => null,
  74. 'getAccess' => null,
  75. 'countOutput' => null,
  76. 'preservekeys' => null,
  77. 'sortfield' => '',
  78. 'sortorder' => '',
  79. 'limit' => null
  80. );
  81. $options = zbx_array_merge($defOptions, $options);
  82. if (is_array($options['output'])) {
  83. unset($sqlParts['select']['users']);
  84. $dbTable = DB::getSchema('users');
  85. $sqlParts['select']['userid'] = ' u.userid';
  86. foreach ($options['output'] as $field) {
  87. if (isset($dbTable['fields'][$field])) {
  88. $sqlParts['select'][$field] = 'u.'.$field;
  89. }
  90. }
  91. $options['output'] = API_OUTPUT_CUSTOM;
  92. }
  93. // permission check
  94. if (USER_TYPE_SUPER_ADMIN == $userType) {
  95. }
  96. elseif (is_null($options['editable']) && self::$userData['type'] == USER_TYPE_ZABBIX_ADMIN) {
  97. $sqlParts['from']['users_groups'] = 'users_groups ug';
  98. $sqlParts['where']['uug'] = 'u.userid=ug.userid';
  99. $sqlParts['where'][] = 'ug.usrgrpid IN ('.
  100. ' SELECT uug.usrgrpid'.
  101. ' FROM users_groups uug'.
  102. ' WHERE uug.userid='.self::$userData['userid'].
  103. ')';
  104. }
  105. elseif (!is_null($options['editable']) || self::$userData['type'] != USER_TYPE_SUPER_ADMIN) {
  106. $options['userids'] = self::$userData['userid'];
  107. }
  108. // userids
  109. if (!is_null($options['userids'])) {
  110. zbx_value2array($options['userids']);
  111. $sqlParts['where'][] = DBcondition('u.userid', $options['userids']);
  112. }
  113. // usrgrpids
  114. if (!is_null($options['usrgrpids'])) {
  115. zbx_value2array($options['usrgrpids']);
  116. if ($options['output'] != API_OUTPUT_SHORTEN) {
  117. $sqlParts['select']['usrgrpid'] = 'ug.usrgrpid';
  118. }
  119. $sqlParts['from']['users_groups'] = 'users_groups ug';
  120. $sqlParts['where'][] = DBcondition('ug.usrgrpid', $options['usrgrpids']);
  121. $sqlParts['where']['uug'] = 'u.userid=ug.userid';
  122. }
  123. // mediaids
  124. if (!is_null($options['mediaids'])) {
  125. zbx_value2array($options['mediaids']);
  126. if ($options['output'] != API_OUTPUT_SHORTEN) {
  127. $sqlParts['select']['mediaid'] = 'm.mediaid';
  128. }
  129. $sqlParts['from']['media'] = 'media m';
  130. $sqlParts['where'][] = DBcondition('m.mediaid', $options['mediaids']);
  131. $sqlParts['where']['mu'] = 'm.userid=u.userid';
  132. }
  133. // mediatypeids
  134. if (!is_null($options['mediatypeids'])) {
  135. zbx_value2array($options['mediatypeids']);
  136. if ($options['output'] != API_OUTPUT_SHORTEN) {
  137. $sqlParts['select']['mediatypeid'] = 'm.mediatypeid';
  138. }
  139. $sqlParts['from']['media'] = 'media m';
  140. $sqlParts['where'][] = DBcondition('m.mediatypeid', $options['mediatypeids']);
  141. $sqlParts['where']['mu'] = 'm.userid=u.userid';
  142. }
  143. // output
  144. if ($options['output'] == API_OUTPUT_EXTEND) {
  145. $sqlParts['select']['users'] = 'u.*';
  146. }
  147. // countOutput
  148. if (!is_null($options['countOutput'])) {
  149. $options['sortfield'] = '';
  150. $sqlParts['select'] = array('COUNT(DISTINCT u.userid) AS rowscount');
  151. }
  152. // filter
  153. if (is_array($options['filter'])) {
  154. if (isset($options['filter']['passwd'])) {
  155. self::exception(ZBX_API_ERROR_PARAMETERS, _('It is not possible to filter by user password.'));
  156. }
  157. zbx_db_filter('users u', $options, $sqlParts);
  158. }
  159. // search
  160. if (is_array($options['search'])) {
  161. if ($options['search']['passwd']) {
  162. self::exception(ZBX_API_ERROR_PARAMETERS, _('It is not possible to search by user password.'));
  163. }
  164. zbx_db_search('users u', $options, $sqlParts);
  165. }
  166. // sorting
  167. zbx_db_sorting($sqlParts, $options, $sortColumns, 'u');
  168. // limit
  169. if (zbx_ctype_digit($options['limit']) && $options['limit']) {
  170. $sqlParts['limit'] = $options['limit'];
  171. }
  172. $sqlParts = $this->applyQueryNodeOptions($this->tableName(), $this->tableAlias(), $options, $sqlParts);
  173. $userids = array();
  174. $sqlParts['select'] = array_unique($sqlParts['select']);
  175. $sqlParts['from'] = array_unique($sqlParts['from']);
  176. $sqlParts['where'] = array_unique($sqlParts['where']);
  177. $sqlParts['order'] = array_unique($sqlParts['order']);
  178. $sqlSelect = '';
  179. $sqlFrom = '';
  180. $sqlWhere = '';
  181. $sqlOrder = '';
  182. if (!empty($sqlParts['select'])) {
  183. $sqlSelect .= implode(',', $sqlParts['select']);
  184. }
  185. if (!empty($sqlParts['from'])) {
  186. $sqlFrom .= implode(',', $sqlParts['from']);
  187. }
  188. if (!empty($sqlParts['where'])) {
  189. $sqlWhere .= implode(' AND ', $sqlParts['where']);
  190. }
  191. if (!empty($sqlParts['order'])) {
  192. $sqlOrder .= ' ORDER BY '.implode(',', $sqlParts['order']);
  193. }
  194. $sqlLimit = $sqlParts['limit'];
  195. $sql = 'SELECT '.zbx_db_distinct($sqlParts).' '.$sqlSelect.
  196. ' FROM '.$sqlFrom.
  197. ' WHERE '.$sqlWhere.
  198. $sqlOrder;
  199. $res = DBselect($sql, $sqlLimit);
  200. while ($user = DBfetch($res)) {
  201. unset($user['passwd']);
  202. if (!is_null($options['countOutput'])) {
  203. $result = $user['rowscount'];
  204. }
  205. else {
  206. $userids[$user['userid']] = $user['userid'];
  207. if ($options['output'] == API_OUTPUT_SHORTEN) {
  208. $result[$user['userid']] = array('userid' => $user['userid']);
  209. }
  210. else {
  211. if (!isset($result[$user['userid']])) {
  212. $result[$user['userid']] = array();
  213. }
  214. if ($options['selectUsrgrps'] && !isset($result[$user['userid']]['usrgrps'])) {
  215. $result[$user['userid']]['usrgrps'] = array();
  216. }
  217. // usrgrpids
  218. if (isset($user['usrgrpid']) && is_null($options['selectUsrgrps'])) {
  219. if (!isset($result[$user['userid']]['usrgrps'])) {
  220. $result[$user['userid']]['usrgrps'] = array();
  221. }
  222. $result[$user['userid']]['usrgrps'][] = array('usrgrpid' => $user['usrgrpid']);
  223. unset($user['usrgrpid']);
  224. }
  225. // mediaids
  226. if (isset($user['mediaid']) && is_null($options['selectMedias'])) {
  227. if (!isset($result[$user['userid']]['medias'])) {
  228. $result[$user['userid']]['medias'] = array();
  229. }
  230. $result[$user['userid']]['medias'][] = array('mediaid' => $user['mediaid']);
  231. unset($user['mediaid']);
  232. }
  233. // mediatypeids
  234. if (isset($user['mediatypeid']) && is_null($options['selectMediatypes'])) {
  235. if (!isset($result[$user['userid']]['mediatypes'])) {
  236. $result[$user['userid']]['mediatypes'] = array();
  237. }
  238. $result[$user['userid']]['mediatypes'][] = array('mediatypeid' => $user['mediatypeid']);
  239. unset($user['mediatypeid']);
  240. }
  241. $result[$user['userid']] += $user;
  242. }
  243. }
  244. }
  245. if (!is_null($options['countOutput'])) {
  246. return $result;
  247. }
  248. /*
  249. * Adding objects
  250. */
  251. if (!is_null($options['getAccess'])) {
  252. foreach ($result as $userid => $user) {
  253. $result[$userid] += array('gui_access' => 0, 'debug_mode' => 0, 'users_status' => 0);
  254. }
  255. $access = DBselect(
  256. 'SELECT ug.userid,MAX(g.gui_access) AS gui_access,'.
  257. ' MAX(g.debug_mode) AS debug_mode,MAX(g.users_status) AS users_status'.
  258. ' FROM usrgrp g,users_groups ug'.
  259. ' WHERE '.DBcondition('ug.userid', $userids).
  260. ' AND g.usrgrpid=ug.usrgrpid'.
  261. ' GROUP BY ug.userid'
  262. );
  263. while ($userAccess = DBfetch($access)) {
  264. $result[$userAccess['userid']] = zbx_array_merge($result[$userAccess['userid']], $userAccess);
  265. }
  266. }
  267. $result = $this->addRelatedObjects($options, $result);
  268. // removing keys (hash -> array)
  269. if (is_null($options['preservekeys'])) {
  270. $result = zbx_cleanHashes($result);
  271. }
  272. return $result;
  273. }
  274. protected function checkInput(&$users, $method) {
  275. $create = ($method == 'create');
  276. $update = ($method == 'update');
  277. $delete = ($method == 'delete');
  278. // permissions
  279. if ($update || $delete) {
  280. $userDBfields = array('userid' => null);
  281. $dbUsers = $this->get(array(
  282. 'output' => array('userid', 'alias', 'autologin', 'autologout'),
  283. 'userids' => zbx_objectValues($users, 'userid'),
  284. 'editable' => true,
  285. 'preservekeys' => true
  286. ));
  287. }
  288. else {
  289. $userDBfields = array('alias' => null, 'passwd' => null, 'usrgrps' => null, 'user_medias' => array());
  290. }
  291. $alias = array();
  292. foreach ($users as &$user) {
  293. if (!check_db_fields($userDBfields, $user)) {
  294. self::exception(ZBX_API_ERROR_PARAMETERS, _s('Wrong fields for user "%s".', $user['alias']));
  295. }
  296. // permission check
  297. if ($create) {
  298. if (USER_TYPE_SUPER_ADMIN != self::$userData['type']) {
  299. self::exception(ZBX_API_ERROR_PARAMETERS, _s('You do not have permissions to create users.'));
  300. }
  301. $dbUser = $user;
  302. }
  303. elseif ($update) {
  304. if (!isset($dbUsers[$user['userid']])) {
  305. self::exception(ZBX_API_ERROR_PARAMETERS, _s('You do not have permissions to update user or user does not exist.'));
  306. }
  307. if (bccomp(self::$userData['userid'], $user['userid']) != 0) {
  308. if (USER_TYPE_SUPER_ADMIN != self::$userData['type']) {
  309. self::exception(ZBX_API_ERROR_PARAMETERS, _s('You do not have permissions to update other users.'));
  310. }
  311. }
  312. $dbUser = $dbUsers[$user['userid']];
  313. }
  314. else {
  315. if (USER_TYPE_SUPER_ADMIN != self::$userData['type']) {
  316. self::exception(ZBX_API_ERROR_PARAMETERS, _s('You do not have permissions to delete users.'));
  317. }
  318. if (!isset($dbUsers[$user['userid']])) {
  319. self::exception(ZBX_API_ERROR_PARAMETERS, _s('You do not have permissions to delete user or user does not exist.'));
  320. }
  321. if (bccomp(self::$userData['userid'], $user['userid']) == 0) {
  322. self::exception(ZBX_API_ERROR_PARAMETERS, _s('User is not allowed to delete himself.'));
  323. }
  324. if ($dbUsers[$user['userid']]['alias'] == ZBX_GUEST_USER) {
  325. self::exception(ZBX_API_ERROR_PARAMETERS, _s('Cannot delete Zabbix internal user "%1$s", try disabling that user.', ZBX_GUEST_USER));
  326. }
  327. continue;
  328. }
  329. // check if user alais
  330. if (isset($user['alias'])) {
  331. // check if we change guest user
  332. if ($dbUser['alias'] == ZBX_GUEST_USER && $user['alias'] != ZBX_GUEST_USER) {
  333. self::exception(ZBX_API_ERROR_PARAMETERS, _('Cannot rename guest user.'));
  334. }
  335. if (!isset($alias[$user['alias']])) {
  336. $alias[$user['alias']] = $update ? $user['userid'] : 1;
  337. }
  338. else {
  339. if ($create || bccomp($user['userid'], $alias[$user['alias']]) != 0) {
  340. self::exception(ZBX_API_ERROR_PARAMETERS, _s('Duplicate user alias "%s".', $user['alias']));
  341. }
  342. }
  343. if (zbx_strlen($user['alias']) > 64) {
  344. self::exception(
  345. ZBX_API_ERROR_PARAMETERS,
  346. _n(
  347. 'Maximum alias length is %2$d characters, "%3$s" is %1$d character.',
  348. 'Maximum alias length is %2$d characters, "%3$s" is %1$d characters.',
  349. zbx_strlen($user['alias']),
  350. 64,
  351. $user['alias']
  352. )
  353. );
  354. }
  355. }
  356. if (isset($user['usrgrps'])) {
  357. if (empty($user['usrgrps'])) {
  358. self::exception(ZBX_API_ERROR_PARAMETERS, _s('User "%s" cannot be without user group.', $dbUser['alias']));
  359. }
  360. // checking if user tries to disable himself (not allowed). No need to check this on creating a user.
  361. if (!$create && bccomp(self::$userData['userid'], $user['userid']) == 0) {
  362. $usrgrps = API::UserGroup()->get(array(
  363. 'usrgrpids' => zbx_objectValues($user['usrgrps'], 'usrgrpid'),
  364. 'output' => API_OUTPUT_EXTEND,
  365. 'preservekeys' => true,
  366. 'nopermissions' => true
  367. ));
  368. foreach ($usrgrps as $groupid => $group) {
  369. if ($group['gui_access'] == GROUP_GUI_ACCESS_DISABLED) {
  370. self::exception(ZBX_API_ERROR_PARAMETERS, _s('User may not modify GUI access for himself by becoming a member of user group "%s".', $group['name']));
  371. }
  372. if ($group['users_status'] == GROUP_STATUS_DISABLED) {
  373. self::exception(ZBX_API_ERROR_PARAMETERS, _s('User may not modify system status for himself by becoming a member of user group "%s".', $group['name']));
  374. }
  375. }
  376. }
  377. }
  378. if (isset($user['type']) && (USER_TYPE_SUPER_ADMIN != self::$userData['type'])) {
  379. self::exception(ZBX_API_ERROR_PARAMETERS, _s('You are not allowed to alter privileges for user "%s".', $dbUser['alias']));
  380. }
  381. if (isset($user['autologin']) && $user['autologin'] == 1 && $dbUser['autologout'] != 0) {
  382. $user['autologout'] = 0;
  383. }
  384. if (isset($user['autologout']) && $user['autologout'] > 0 && $dbUser['autologin'] != 0) {
  385. $user['autologin'] = 0;
  386. }
  387. if (array_key_exists('passwd', $user)) {
  388. if (is_null($user['passwd'])) {
  389. unset($user['passwd']);
  390. }
  391. else {
  392. if ($dbUser['alias'] == ZBX_GUEST_USER && !zbx_empty($user['passwd'])) {
  393. self::exception(ZBX_API_ERROR_PARAMETERS, _s('Not allowed to set password for user "guest".'));
  394. }
  395. $user['passwd'] = md5($user['passwd']);
  396. }
  397. }
  398. if (isset($user['alias'])) {
  399. $nodeids = $update ? id2nodeid($user['userid']) : get_current_nodeid(false);
  400. $userExist = $this->get(array(
  401. 'nodeids' => $nodeids,
  402. 'filter' => array('alias' => $user['alias']),
  403. 'nopermissions' => true
  404. ));
  405. if ($exUser = reset($userExist)) {
  406. if ($create || (bccomp($exUser['userid'], $user['userid']) != 0)) {
  407. self::exception(ZBX_API_ERROR_PARAMETERS, _s('User with alias "%s" already exists.', $user['alias']));
  408. }
  409. }
  410. }
  411. }
  412. unset($user);
  413. }
  414. /**
  415. * Add Users
  416. *
  417. * @param array $users multidimensional array with Users data
  418. * @param string $users['name']
  419. * @param string $users['surname']
  420. * @param array $users['alias']
  421. * @param string $users['passwd']
  422. * @param string $users['url']
  423. * @param int $users['autologin']
  424. * @param int $users['autologout']
  425. * @param string $users['lang']
  426. * @param string $users['theme']
  427. * @param int $users['refresh']
  428. * @param int $users['rows_per_page']
  429. * @param int $users['type']
  430. * @param array $users['user_medias']
  431. * @param string $users['user_medias']['mediatypeid']
  432. * @param string $users['user_medias']['address']
  433. * @param int $users['user_medias']['severity']
  434. * @param int $users['user_medias']['active']
  435. * @param string $users['user_medias']['period']
  436. * @return array|boolean
  437. */
  438. public function create($users) {
  439. $users = zbx_toArray($users);
  440. $this->checkInput($users, __FUNCTION__);
  441. $userids = DB::insert('users', $users);
  442. foreach ($users as $unum => $user) {
  443. $userid = $userids[$unum];
  444. $usrgrps = zbx_objectValues($user['usrgrps'], 'usrgrpid');
  445. foreach ($usrgrps as $groupid) {
  446. $usersGroupdId = get_dbid('users_groups', 'id');
  447. $sql = 'INSERT INTO users_groups (id,usrgrpid,userid) VALUES ('.$usersGroupdId.','.$groupid.','.$userid.')';
  448. if (!DBexecute($sql)) {
  449. self::exception(ZBX_API_ERROR_PARAMETERS, 'DBerror');
  450. }
  451. }
  452. foreach ($user['user_medias'] as $mediaData) {
  453. $mediaid = get_dbid('media', 'mediaid');
  454. $sql = 'INSERT INTO media (mediaid,userid,mediatypeid,sendto,active,severity,period)'.
  455. ' VALUES ('.$mediaid.','.$userid.','.$mediaData['mediatypeid'].','.
  456. zbx_dbstr($mediaData['sendto']).','.$mediaData['active'].','.$mediaData['severity'].','.
  457. zbx_dbstr($mediaData['period']).')';
  458. if (!DBexecute($sql)) {
  459. self::exception(ZBX_API_ERROR_PARAMETERS, 'DBerror');
  460. }
  461. }
  462. }
  463. return array('userids' => $userids);
  464. }
  465. /**
  466. * Update Users
  467. *
  468. * @param array $users multidimensional array with Users data
  469. * @param string $users['userid']
  470. * @param string $users['name']
  471. * @param string $users['surname']
  472. * @param array $users['alias']
  473. * @param string $users['passwd']
  474. * @param string $users['url']
  475. * @param int $users['autologin']
  476. * @param int $users['autologout']
  477. * @param string $users['lang']
  478. * @param string $users['theme']
  479. * @param int $users['refresh']
  480. * @param int $users['rows_per_page']
  481. * @param int $users['type']
  482. * @param array $users['user_medias']
  483. * @param string $users['user_medias']['mediatypeid']
  484. * @param string $users['user_medias']['address']
  485. * @param int $users['user_medias']['severity']
  486. * @param int $users['user_medias']['active']
  487. * @param string $users['user_medias']['period']
  488. * @return boolean
  489. */
  490. public function update($users) {
  491. $users = zbx_toArray($users);
  492. $userids = zbx_objectValues($users, 'userid');
  493. $this->checkInput($users, __FUNCTION__);
  494. foreach ($users as $user) {
  495. $self = (bccomp(self::$userData['userid'], $user['userid']) == 0);
  496. $result = DB::update('users', array(
  497. array(
  498. 'values' => $user,
  499. 'where' => array('userid' => $user['userid'])
  500. )
  501. ));
  502. if (!$result) {
  503. self::exception(ZBX_API_ERROR_PARAMETERS, 'DBerror');
  504. }
  505. if (isset($user['usrgrps']) && !is_null($user['usrgrps'])) {
  506. $newUsrgrpids = zbx_objectValues($user['usrgrps'], 'usrgrpid');
  507. // deleting all relations with groups, but not touching those, where user still must be after update
  508. DBexecute('DELETE FROM users_groups WHERE userid='.$user['userid'].' AND '.DBcondition('usrgrpid', $newUsrgrpids, true));
  509. // getting the list of groups user is currently in
  510. $dbGroupsUserIn = DBSelect('SELECT usrgrpid FROM users_groups WHERE userid='.$user['userid']);
  511. $groupsUserIn = array();
  512. while ($grp = DBfetch($dbGroupsUserIn)) {
  513. $groupsUserIn[$grp['usrgrpid']] = $grp['usrgrpid'];
  514. }
  515. $usrgrps = API::UserGroup()->get(array(
  516. 'usrgrpids' => zbx_objectValues($user['usrgrps'], 'usrgrpid'),
  517. 'output' => API_OUTPUT_EXTEND,
  518. 'preservekeys' => true
  519. ));
  520. foreach ($usrgrps as $groupid => $group) {
  521. // if user is not already in a given group
  522. if (isset($groupsUserIn[$groupid])) {
  523. continue;
  524. }
  525. $usersGroupdId = get_dbid('users_groups', 'id');
  526. $sql = 'INSERT INTO users_groups (id,usrgrpid,userid) VALUES ('.$usersGroupdId.','.$groupid.','.$user['userid'].')';
  527. if (!DBexecute($sql)) {
  528. self::exception(ZBX_API_ERROR_PARAMETERS, 'DBerror');
  529. }
  530. }
  531. }
  532. }
  533. return array('userids' => $userids);
  534. }
  535. public function updateProfile($user) {
  536. $user['userid'] = self::$userData['userid'];
  537. return $this->update(array($user));
  538. }
  539. /**
  540. * Delete Users
  541. *
  542. * @param array $users
  543. * @param array $users[0,...]['userids']
  544. * @return boolean
  545. */
  546. public function delete($users) {
  547. $users = zbx_toArray($users);
  548. $userids = zbx_objectValues($users, 'userid');
  549. $this->checkInput($users, __FUNCTION__);
  550. // delete action operation msg
  551. $operationids = array();
  552. $dbOperations = DBselect(
  553. 'SELECT DISTINCT om.operationid'.
  554. ' FROM opmessage_usr om'.
  555. ' WHERE '.DBcondition('om.userid', $userids)
  556. );
  557. while ($dbOperation = DBfetch($dbOperations)) {
  558. $operationids[$dbOperation['operationid']] = $dbOperation['operationid'];
  559. }
  560. DB::delete('opmessage_usr', array('userid' => $userids));
  561. // delete empty operations
  562. $delOperationids = array();
  563. $dbOperations = DBselect(
  564. 'SELECT DISTINCT o.operationid'.
  565. ' FROM operations o'.
  566. ' WHERE '.DBcondition('o.operationid', $operationids).
  567. ' AND NOT EXISTS(SELECT om.opmessage_usrid FROM opmessage_usr om WHERE om.operationid=o.operationid)'
  568. );
  569. while ($dbOperation = DBfetch($dbOperations)) {
  570. $delOperationids[$dbOperation['operationid']] = $dbOperation['operationid'];
  571. }
  572. DB::delete('operations', array('operationid' => $delOperationids));
  573. DB::delete('media', array('userid' => $userids));
  574. DB::delete('profiles', array('userid' => $userids));
  575. DB::delete('users_groups', array('userid' => $userids));
  576. DB::delete('users', array('userid' => $userids));
  577. return array('userids' => $userids);
  578. }
  579. /**
  580. * Add Medias for User
  581. *
  582. * @param array $mediaData
  583. * @param string $mediaData['userid']
  584. * @param string $mediaData['medias']['mediatypeid']
  585. * @param string $mediaData['medias']['address']
  586. * @param int $mediaData['medias']['severity']
  587. * @param int $mediaData['medias']['active']
  588. * @param string $mediaData['medias']['period']
  589. * @return boolean
  590. */
  591. public function addMedia($mediaData) {
  592. $medias = zbx_toArray($mediaData['medias']);
  593. $users = zbx_toArray($mediaData['users']);
  594. $mediaids = array();
  595. $userids = array();
  596. if (self::$userData['type'] < USER_TYPE_ZABBIX_ADMIN) {
  597. self::exception(ZBX_API_ERROR_PARAMETERS, _('Only Zabbix Admins can add user media.'));
  598. }
  599. foreach ($users as $user) {
  600. $userids[] = $user['userid'];
  601. foreach ($medias as $media) {
  602. if (!validate_period($media['period'])) {
  603. self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect time period'));
  604. }
  605. $mediaid = get_dbid('media', 'mediaid');
  606. $sql = 'INSERT INTO media (mediaid,userid,mediatypeid,sendto,active,severity,period)'.
  607. ' VALUES ('.$mediaid.','.$user['userid'].','.$media['mediatypeid'].','.
  608. zbx_dbstr($media['sendto']).','.$media['active'].','.$media['severity'].','.
  609. zbx_dbstr($media['period']).')';
  610. if (!DBexecute($sql)) {
  611. self::exception(ZBX_API_ERROR_PARAMETERS, 'DBerror');
  612. }
  613. $mediaids[] = $mediaid;
  614. }
  615. }
  616. return array('mediaids' => $mediaids);
  617. }
  618. /**
  619. * Delete User Medias
  620. *
  621. * @param array $mediaids
  622. * @return boolean
  623. */
  624. public function deleteMedia($mediaids) {
  625. $mediaids = zbx_toArray($mediaids);
  626. if (self::$userData['type'] < USER_TYPE_ZABBIX_ADMIN) {
  627. self::exception(ZBX_API_ERROR_PARAMETERS, _('Only Zabbix Admins can remove user media.'));
  628. }
  629. $sql = 'DELETE FROM media WHERE '.DBcondition('mediaid', $mediaids);
  630. if (!DBexecute($sql)) {
  631. self::exception(ZBX_API_ERROR_PARAMETERS, 'DBerror');
  632. }
  633. return array('mediaids' => $mediaids);
  634. }
  635. /**
  636. * Update Medias for User
  637. *
  638. * @param array $mediaData
  639. * @param array $mediaData['users']
  640. * @param array $mediaData['users']['userid']
  641. * @param array $mediaData['medias']
  642. * @param string $mediaData['medias']['mediatypeid']
  643. * @param string $mediaData['medias']['sendto']
  644. * @param int $mediaData['medias']['severity']
  645. * @param int $mediaData['medias']['active']
  646. * @param string $mediaData['medias']['period']
  647. * @return boolean
  648. */
  649. public function updateMedia($mediaData) {
  650. $newMedias = zbx_toArray($mediaData['medias']);
  651. $users = zbx_toArray($mediaData['users']);
  652. if (self::$userData['type'] < USER_TYPE_ZABBIX_ADMIN) {
  653. self::exception(ZBX_API_ERROR_PERMISSIONS, _('Only Zabbix Admins can change user media.'));
  654. }
  655. $updMedias = array();
  656. $delMedias = array();
  657. $userids = zbx_objectValues($users, 'userid');
  658. $result = DBselect(
  659. 'SELECT m.mediaid'.
  660. ' FROM media m'.
  661. ' WHERE '.DBcondition('userid', $userids)
  662. );
  663. while ($media = DBfetch($result)) {
  664. $delMedias[$media['mediaid']] = $media;
  665. }
  666. foreach ($newMedias as $mnum => $media) {
  667. if (!isset($media['mediaid'])) {
  668. continue;
  669. }
  670. if (isset($delMedias[$media['mediaid']])) {
  671. $updMedias[$media['mediaid']] = $newMedias[$mnum];
  672. }
  673. unset($newMedias[$mnum]);
  674. unset($delMedias[$media['mediaid']]);
  675. }
  676. // delete
  677. if (!empty($delMedias)) {
  678. $mediaids = zbx_objectValues($delMedias, 'mediaid');
  679. $result = $this->deleteMedia($mediaids);
  680. if (!$result) {
  681. self::exception(ZBX_API_ERROR_PARAMETERS, _('Cannot delete user media.'));
  682. }
  683. }
  684. // update
  685. foreach ($updMedias as $media) {
  686. if (!validate_period($media['period'])) {
  687. self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect time period "%1$s".', $media['period']));
  688. }
  689. $result = DBexecute(
  690. 'UPDATE media'.
  691. ' SET mediatypeid='.$media['mediatypeid'].','.
  692. ' sendto='.zbx_dbstr($media['sendto']).','.
  693. ' active='.$media['active'].','.
  694. ' severity='.$media['severity'].','.
  695. ' period='.zbx_dbstr($media['period']).
  696. ' WHERE mediaid='.$media['mediaid']
  697. );
  698. if (!$result) {
  699. self::exception(ZBX_API_ERROR_PARAMETERS, _('Cannot update user media.'));
  700. }
  701. }
  702. // create
  703. if (!empty($newMedias)) {
  704. $result = $this->addMedia(array('users' => $users, 'medias' => $newMedias));
  705. if (!$result) {
  706. self::exception(ZBX_API_ERROR_PARAMETERS, _('Cannot insert user media.'));
  707. }
  708. }
  709. return array('userids'=>$userids);
  710. }
  711. // ******************************************************************************
  712. // LOGIN Methods
  713. // ******************************************************************************
  714. public function ldapLogin($user) {
  715. $cnf = isset($user['cnf']) ? $user['cnf'] : null;
  716. if (is_null($cnf)) {
  717. $config = select_config();
  718. foreach ($config as $id => $value) {
  719. if (zbx_strpos($id, 'ldap_') !== false) {
  720. $cnf[str_replace('ldap_', '', $id)] = $config[$id];
  721. }
  722. }
  723. }
  724. if (!function_exists('ldap_connect')) {
  725. self::exception(ZBX_API_ERROR_PARAMETERS, _('Probably php-ldap module is missing.'));
  726. }
  727. $ldap = new CLdap($cnf);
  728. $ldap->connect();
  729. if ($ldap->checkPass($user['user'], $user['password'])) {
  730. return true;
  731. }
  732. else {
  733. self::exception(ZBX_API_ERROR_PARAMETERS, _('Login name or password is incorrect.'));
  734. }
  735. }
  736. private function dbLogin($user) {
  737. global $ZBX_LOCALNODEID;
  738. $login = DBfetch(DBselect(
  739. 'SELECT u.userid'.
  740. ' FROM users u'.
  741. ' WHERE u.alias='.zbx_dbstr($user['user']).
  742. ' AND u.passwd='.zbx_dbstr(md5($user['password'])).
  743. ' AND '.DBin_node('u.userid', $ZBX_LOCALNODEID)
  744. ));
  745. if ($login) {
  746. return true;
  747. }
  748. else {
  749. self::exception(ZBX_API_ERROR_PARAMETERS, _('Login name or password is incorrect.'));
  750. }
  751. }
  752. public function logout($sessionid) {
  753. global $ZBX_LOCALNODEID;
  754. $session = DBfetch(DBselect(
  755. 'SELECT s.*'.
  756. ' FROM sessions s'.
  757. ' WHERE s.sessionid='.zbx_dbstr($sessionid).
  758. ' AND s.status='.ZBX_SESSION_ACTIVE.
  759. ' AND '.DBin_node('s.userid', $ZBX_LOCALNODEID)
  760. ));
  761. if (!$session) {
  762. self::exception(ZBX_API_ERROR_PARAMETERS, _('Cannot logout.'));
  763. }
  764. DBexecute('DELETE FROM sessions WHERE status='.ZBX_SESSION_PASSIVE.' AND userid='.zbx_dbstr($session['userid']));
  765. DBexecute('UPDATE sessions SET status='.ZBX_SESSION_PASSIVE.' WHERE sessionid='.zbx_dbstr($sessionid));
  766. return true;
  767. }
  768. /**
  769. * Login user
  770. *
  771. * @param array $user
  772. * @param array $user['user'] User alias
  773. * @param array $user['password'] User password
  774. * @return string session ID
  775. */
  776. public function login($user) {
  777. global $ZBX_LOCALNODEID;
  778. $name = $user['user'];
  779. $password = md5($user['password']);
  780. $userInfo = DBfetch(DBselect(
  781. 'SELECT u.userid,u.attempt_failed,u.attempt_clock,u.attempt_ip'.
  782. ' FROM users u'.
  783. ' WHERE u.alias='.zbx_dbstr($name).
  784. ' AND '.DBin_node('u.userid', $ZBX_LOCALNODEID)
  785. ));
  786. if (!$userInfo) {
  787. self::exception(ZBX_API_ERROR_PARAMETERS, _('Login name or password is incorrect.'));
  788. }
  789. // check if user is blocked
  790. if ($userInfo['attempt_failed'] >= ZBX_LOGIN_ATTEMPTS) {
  791. if ((time() - $userInfo['attempt_clock']) < ZBX_LOGIN_BLOCK) {
  792. self::exception(ZBX_API_ERROR_PARAMETERS, _s('Account is blocked for %s seconds', (ZBX_LOGIN_BLOCK - (time() - $userInfo['attempt_clock']))));
  793. }
  794. DBexecute('UPDATE users SET attempt_clock='.time().' WHERE alias='.zbx_dbstr($name));
  795. }
  796. // check system permissions
  797. if (!check_perm2system($userInfo['userid'])) {
  798. self::exception(ZBX_API_ERROR_PARAMETERS, _('No permissions for system access.'));
  799. }
  800. $dbAccess = DBfetch(DBselect(
  801. 'SELECT MAX(g.gui_access) AS gui_access'.
  802. ' FROM usrgrp g,users_groups ug'.
  803. ' WHERE ug.userid='.$userInfo['userid'].
  804. ' AND g.usrgrpid=ug.usrgrpid'
  805. ));
  806. if (!zbx_empty($dbAccess['gui_access'])) {
  807. $guiAccess = $dbAccess['gui_access'];
  808. }
  809. else {
  810. $guiAccess = GROUP_GUI_ACCESS_SYSTEM;
  811. }
  812. switch ($guiAccess) {
  813. case GROUP_GUI_ACCESS_INTERNAL:
  814. $authType = ZBX_AUTH_INTERNAL;
  815. break;
  816. case GROUP_GUI_ACCESS_DISABLED:
  817. /* fall through */
  818. case GROUP_GUI_ACCESS_SYSTEM:
  819. $config = select_config();
  820. $authType = $config['authentication_type'];
  821. break;
  822. }
  823. try {
  824. switch ($authType) {
  825. case ZBX_AUTH_LDAP:
  826. $this->ldapLogin($user);
  827. break;
  828. case ZBX_AUTH_INTERNAL:
  829. $this->dbLogin($user);
  830. break;
  831. case ZBX_AUTH_HTTP:
  832. }
  833. }
  834. catch (APIException $e) {
  835. $ip = (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && !empty($_SERVER['HTTP_X_FORWARDED_FOR']))
  836. ? $_SERVER['HTTP_X_FORWARDED_FOR']
  837. : $_SERVER['REMOTE_ADDR'];
  838. $userInfo['attempt_failed']++;
  839. DBexecute(
  840. 'UPDATE users'.
  841. ' SET attempt_failed='.$userInfo['attempt_failed'].','.
  842. ' attempt_clock='.time().','.
  843. ' attempt_ip='.zbx_dbstr($ip).
  844. ' WHERE userid='.$userInfo['userid']
  845. );
  846. add_audit(AUDIT_ACTION_LOGIN, AUDIT_RESOURCE_USER, _s('Login failed "%s".', $name));
  847. self::exception(ZBX_API_ERROR_PARAMETERS, $e->getMessage());
  848. }
  849. // start session
  850. $sessionid = md5(time().$password.$name.rand(0, 10000000));
  851. DBexecute('INSERT INTO sessions (sessionid,userid,lastaccess,status) VALUES ('.zbx_dbstr($sessionid).','.$userInfo['userid'].','.time().','.ZBX_SESSION_ACTIVE.')');
  852. add_audit(AUDIT_ACTION_LOGIN, AUDIT_RESOURCE_USER, _s('Correct login "%s".', $name));
  853. $userData = $this->_getUserData($userInfo['userid']);
  854. $userData['sessionid'] = $sessionid;
  855. $userData['gui_access'] = $guiAccess;
  856. $userData['userid'] = $userInfo['userid'];
  857. if ($userInfo['attempt_failed']) {
  858. DBexecute('UPDATE users SET attempt_failed=0 WHERE userid='.$userInfo['userid']);
  859. }
  860. CWebUser::$data = self::$userData = $userData;
  861. return isset($user['userData']) ? $userData : $userData['sessionid'];
  862. }
  863. /**
  864. * Check if session ID is authenticated
  865. *
  866. * @param string $sessionid session ID
  867. *
  868. * @return array an array of user data
  869. */
  870. public function checkAuthentication($sessionid) {
  871. global $ZBX_LOCALNODEID;
  872. // access DB only once per page load
  873. if (!is_null(self::$userData)) {
  874. return self::$userData;
  875. }
  876. $time = time();
  877. $userInfo = DBfetch(DBselect(
  878. 'SELECT u.userid,u.autologout,s.lastaccess'.
  879. ' FROM sessions s,users u'.
  880. ' WHERE s.sessionid='.zbx_dbstr($sessionid).
  881. ' AND s.status='.ZBX_SESSION_ACTIVE.
  882. ' AND s.userid=u.userid'.
  883. ' AND ((s.lastaccess+u.autologout>'.$time.') OR (u.autologout=0))'.
  884. ' AND '.DBin_node('u.userid', $ZBX_LOCALNODEID)
  885. ));
  886. if (!$userInfo) {
  887. self::exception(ZBX_API_ERROR_PARAMETERS, _('Session terminated, re-login, please.'));
  888. }
  889. // don't check permissions on the same second
  890. if ($time != $userInfo['lastaccess']) {
  891. if (!check_perm2system($userInfo['userid'])) {
  892. self::exception(ZBX_API_ERROR_PARAMETERS, _('No permissions for system access.'));
  893. }
  894. if ($userInfo['autologout'] > 0) {
  895. DBexecute('DELETE FROM sessions WHERE userid='.$userInfo['userid'].' AND lastaccess<'.(time() - $userInfo['autologout']));
  896. }
  897. DBexecute('UPDATE sessions SET lastaccess='.time().' WHERE userid='.$userInfo['userid'].' AND sessionid='.zbx_dbstr($sessionid));
  898. }
  899. $dbAccess = DBfetch(DBselect(
  900. 'SELECT MAX(g.gui_access) AS gui_access'.
  901. ' FROM usrgrp g,users_groups ug'.
  902. ' WHERE ug.userid='.$userInfo['userid'].
  903. ' AND g.usrgrpid=ug.usrgrpid'
  904. ));
  905. if (!zbx_empty($dbAccess['gui_access'])) {
  906. $guiAccess = $dbAccess['gui_access'];
  907. }
  908. else {
  909. $guiAccess = GROUP_GUI_ACCESS_SYSTEM;
  910. }
  911. $userData = $this->_getUserData($userInfo['userid']);
  912. $userData['sessionid'] = $sessionid;
  913. $userData['gui_access'] = $guiAccess;
  914. CWebUser::$data = self::$userData = $userData;
  915. return $userData;
  916. }
  917. private function _getUserData($userid) {
  918. global $ZBX_LOCALNODEID, $ZBX_NODES;
  919. $userData = DBfetch(DBselect(
  920. 'SELECT u.userid,u.alias,u.name,u.surname,u.url,u.autologin,u.autologout,u.lang,u.refresh,u.type,'.
  921. ' u.theme,u.attempt_failed,u.attempt_ip,u.attempt_clock,u.rows_per_page'.
  922. ' FROM users u'.
  923. ' WHERE u.userid='.$userid
  924. ));
  925. $userData['debug_mode'] = (bool) DBfetch(DBselect(
  926. 'SELECT ug.userid'.
  927. ' FROM usrgrp g,users_groups ug'.
  928. ' WHERE ug.userid='.$userid.
  929. ' AND g.usrgrpid=ug.usrgrpid'.
  930. ' AND g.debug_mode='.GROUP_DEBUG_MODE_ENABLED
  931. ));
  932. $userData['userip'] = (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && !empty($_SERVER['HTTP_X_FORWARDED_FOR']))
  933. ? $_SERVER['HTTP_X_FORWARDED_FOR']
  934. : $_SERVER['REMOTE_ADDR'];
  935. if (isset($ZBX_NODES[$ZBX_LOCALNODEID])) {
  936. $userData['node'] = $ZBX_NODES[$ZBX_LOCALNODEID];
  937. }
  938. else {
  939. $userData['node'] = array();
  940. $userData['node']['name'] = '- unknown -';
  941. $userData['node']['nodeid'] = $ZBX_LOCALNODEID;
  942. }
  943. return $userData;
  944. }
  945. public function isReadable($ids) {
  946. if (!is_array($ids)) {
  947. return false;
  948. }
  949. if (empty($ids)) {
  950. return true;
  951. }
  952. $ids = array_unique($ids);
  953. $count = $this->get(array(
  954. 'nodeids' => get_current_nodeid(true),
  955. 'userids' => $ids,
  956. 'output' => API_OUTPUT_SHORTEN,
  957. 'countOutput' => true
  958. ));
  959. return (count($ids) == $count);
  960. }
  961. public function isWritable($ids) {
  962. if (!is_array($ids)) {
  963. return false;
  964. }
  965. if (empty($ids)) {
  966. return true;
  967. }
  968. $ids = array_unique($ids);
  969. $count = $this->get(array(
  970. 'nodeids' => get_current_nodeid(true),
  971. 'userids' => $ids,
  972. 'output' => API_OUTPUT_SHORTEN,
  973. 'editable' => true,
  974. 'countOutput' => true
  975. ));
  976. return (count($ids) == $count);
  977. }
  978. protected function applyQueryNodeOptions($tableName, $tableAlias, array $options, array $sqlParts) {
  979. if (!isset($options['usrgrpids'])) {
  980. $sqlParts = parent::applyQueryNodeOptions($tableName, $tableAlias, $options, $sqlParts);
  981. }
  982. return $sqlParts;
  983. }
  984. protected function addRelatedObjects(array $options, array $result) {
  985. $result = parent::addRelatedObjects($options, $result);
  986. $userids = zbx_objectValues($result, 'userid');
  987. // adding usergroups
  988. if (!is_null($options['selectUsrgrps']) && str_in_array($options['selectUsrgrps'], array(API_OUTPUT_REFER, API_OUTPUT_EXTEND))) {
  989. foreach ($result as &$user) {
  990. $user['usrgrps'] = array();
  991. }
  992. unset($user);
  993. $usrgrps = API::UserGroup()->get(array(
  994. 'output' => $options['selectUsrgrps'],
  995. 'userids' => $userids,
  996. 'preservekeys' => true
  997. ));
  998. foreach ($usrgrps as $usrgrp) {
  999. $uusers = $usrgrp['users'];
  1000. unset($usrgrp['users']);
  1001. $usrgrps = $this->unsetExtraFields('usrgrp', $usrgrps, $options['selectUsrgrps']);
  1002. foreach ($uusers as $user) {
  1003. $result[$user['userid']]['usrgrps'][] = $usrgrp;
  1004. }
  1005. }
  1006. }
  1007. // adding medias
  1008. if (!is_null($options['selectMedias']) && str_in_array($options['selectMedias'], array(API_OUTPUT_REFER, API_OUTPUT_EXTEND))) {
  1009. foreach ($result as &$user) {
  1010. $user['medias'] = array();
  1011. }
  1012. unset($user);
  1013. $userMedias = API::UserMedia()->get(array(
  1014. 'output' => $options['selectMedias'],
  1015. 'userids' => $userids,
  1016. 'preservekeys' => true
  1017. ));
  1018. $userMedias = $this->unsetExtraFields('media', $userMedias, $options['selectMedias']);
  1019. foreach ($userMedias as $mediaid => $media) {
  1020. $result[$media['userid']]['medias'][] = $media;
  1021. }
  1022. }
  1023. // adding media types
  1024. if (!is_null($options['selectMediatypes'])) {
  1025. foreach ($result as &$user) {
  1026. $user['mediatypes'] = array();
  1027. }
  1028. unset($user);
  1029. $mediatypes = API::Mediatype()->get(array(
  1030. 'output' => $options['selectMediatypes'],
  1031. 'userids' => $userids,
  1032. 'selectUsers' => API_OUTPUT_REFER,
  1033. 'preservekeys' => true
  1034. ));
  1035. foreach ($mediatypes as $mediatype) {
  1036. $users = $mediatype['users'];
  1037. unset($mediatype['users']);
  1038. $mediatype = $this->unsetExtraFields('media_type', $mediatype, $options['selectMediatypes']);
  1039. foreach ($users as $user) {
  1040. if (!empty($result[$user['userid']])) {
  1041. $result[$user['userid']]['mediatypes'][] = $mediatype;
  1042. }
  1043. }
  1044. }
  1045. }
  1046. return $result;
  1047. }
  1048. }