1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
16:
17: defined('CON_FRAMEWORK') || die('Illegal call: Missing framework initialization - request aborted.');
18:
19: 20: 21: 22: 23: 24:
25: class cApiUserCollection extends ItemCollection {
26:
27: 28: 29: 30: 31: 32: 33:
34: public function __construct($where = false) {
35: global $cfg;
36: parent::__construct($cfg['tab']['user'], 'user_id');
37: $this->_setItemClass('cApiUser');
38: if ($where !== false) {
39: $this->select($where);
40: }
41: }
42:
43: 44: 45: 46: 47: 48:
49: public function create($username) {
50: $primaryKeyValue = md5($username);
51:
52: $item = parent::createNewItem($primaryKeyValue);
53: if ($item->usernameExists($username)) {
54: return false;
55: }
56:
57: $item->set('username', $username);
58: $item->set('salt', md5($username.rand(1000, 9999).rand(1000, 9999).rand(1000, 9999)));
59: $item->store();
60:
61: return $item;
62: }
63:
64: 65: 66: 67: 68: 69:
70: public function deleteUserByUsername($username) {
71: $result = $this->deleteBy('username', $username);
72: return ($result > 0)? true : false;
73: }
74:
75: 76: 77: 78: 79: 80: 81: 82: 83:
84: public function fetchAccessibleUsers($perms, $includeAdmins = false, $orderBy = '') {
85: $users = array();
86: $limit = array();
87: $where = '';
88:
89: if (!in_array('sysadmin', $perms)) {
90:
91: $clientColl = new cApiClientCollection();
92: $allClients = $clientColl->getAvailableClients();
93:
94: foreach ($allClients as $key => $value) {
95: if (in_array('client[' . $key . ']', $perms) || in_array('admin[' . $key . ']', $perms)) {
96: $limit[] = 'perms LIKE "%client[' . $$this->escape($key) . ']%"';
97: if ($includeAdmins) {
98: $limit[] = 'perms LIKE "%admin[' . $this->escape($key) . ']%"';
99: }
100: }
101: if (in_array('admin[' . $key . ']', $perms)) {
102: $limit[] = 'perms LIKE "%admin[' . $key . ']%"';
103: }
104: }
105:
106: if ($includeAdmins) {
107: $limit[] = 'perms LIKE "%sysadmin%"';
108: }
109:
110: if (count($limit) > 0) {
111: $where = '1 AND ' . implode(' OR ', $limit);
112: }
113: }
114:
115: if (empty($orderBy)) {
116: $orderBy = 'realname, username';
117: }
118:
119: $this->select($where, '', $this->escape($orderBy));
120: while (($oItem = $this->next()) !== false) {
121: $users[] = clone $oItem;
122: }
123:
124: return $users;
125: }
126:
127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139:
140: public function getAccessibleUsers($perms, $includeAdmins = false, $orderBy = '') {
141: $users = array();
142: $oUsers = $this->fetchAccessibleUsers($perms, $includeAdmins, $orderBy);
143: foreach ($oUsers as $oItem) {
144: $users[$oItem->get('user_id')] = array(
145: 'username' => $oItem->get('username'),
146: 'realname' => $oItem->get('realname')
147: );
148: }
149: return $users;
150: }
151:
152: 153: 154: 155: 156: 157:
158: public function fetchAvailableUsers($orderBy = 'realname ASC') {
159: $users = array();
160:
161: $this->select('', '', $this->escape($orderBy));
162: while (($oItem = $this->next()) !== false) {
163: $users[] = clone $oItem;
164: }
165:
166: return $users;
167: }
168:
169: 170: 171: 172: 173: 174: 175:
176: public function fetchSystemAdmins($forceActive = false) {
177: $users = array();
178:
179: $where = 'perms LIKE "%sysadmin%"';
180: if ($forceActive === true) {
181: $where .= " AND (valid_from <= NOW() OR valid_from = '0000-00-00')" . " AND (valid_to >= NOW() OR valid_to = '0000-00-00')";
182: }
183:
184: $this->select($where);
185: while (($item = $this->next()) !== false) {
186: $users[] = clone $item;
187: }
188:
189: return $users;
190: }
191:
192: 193: 194: 195: 196: 197:
198: public function fetchClientAdmins($client) {
199: $client = (int) $client;
200: $users = array();
201:
202: $where = 'perms LIKE "%admin[' . $client . ']%"';
203:
204: $this->select($where);
205: while (($item = $this->next()) !== false) {
206: $users[] = clone $item;
207: }
208:
209: return $users;
210: }
211:
212: }
213:
214: 215: 216: 217: 218: 219: 220: 221: 222: 223: 224: 225: 226: 227: 228: 229: 230: 231: 232: 233: 234: 235: 236: 237: 238: 239: 240: 241: 242: 243: 244: 245: 246: 247: 248: 249: 250: 251: 252: 253: 254: 255: 256: 257: 258: 259: 260: 261: 262: 263: 264: 265: 266: 267:
268: class cApiUser extends Item {
269:
270: 271: 272: 273: 274: 275:
276: const PASS_OK = 0;
277:
278: 279: 280: 281: 282: 283:
284: const PASS_TO_SHORT = 1;
285:
286: 287: 288: 289: 290: 291:
292: const PASS_NOT_STRONG = 2;
293:
294: 295: 296: 297: 298: 299:
300: const PASS_NOT_COMPLEX = 3;
301:
302: 303: 304: 305: 306: 307:
308: const PASS_NOT_ENOUGH_NUMBERS = 4;
309:
310: 311: 312: 313: 314:
315: const PASS_NOT_ENOUGH_SYMBOLS = 5;
316:
317: 318: 319: 320: 321: 322:
323: const PASS_NOT_ENOUGH_MIXED_CHARS = 6;
324:
325: 326: 327: 328: 329: 330:
331: const PASS_NOT_ENOUGH_DIFFERENT_CHARS = 7;
332:
333: 334: 335: 336: 337: 338: 339:
340: const EXCEPTION_USERNAME_EXISTS = 8;
341:
342: 343: 344: 345: 346: 347: 348:
349: const EXCEPTION_PASSWORD_INVALID = 9;
350:
351: 352: 353: 354: 355: 356: 357:
358: const MIN_PASS_LENGTH_DEFAULT = 8;
359:
360: 361: 362: 363: 364:
365: public function __construct($mId = false) {
366: global $cfg;
367: parent::__construct($cfg['tab']['user'], 'user_id');
368: $this->setFilters(array(), array());
369: if ($mId !== false) {
370: $this->loadByPrimaryKey($mId);
371: }
372: }
373:
374: 375: 376: 377: 378: 379:
380: public function loadUserByUserID($userId) {
381: return $this->loadByPrimaryKey($userId);
382: }
383:
384: 385: 386: 387: 388: 389:
390: public function loadUserByUsername($userName) {
391: return $this->loadBy('username', $userName);
392: }
393:
394: 395: 396: 397: 398:
399: public static function userExists($userId) {
400: $test = new cApiUser();
401:
402: return $test->loadByPrimaryKey($userId);
403: }
404:
405: 406: 407: 408: 409: 410:
411: public static function usernameExists($username) {
412: $user = new cApiUser();
413: return $user->loadBy('username', $username);
414: }
415:
416: 417: 418: 419: 420: 421: 422: 423: 424: 425:
426: public static function checkPasswordMask($password) {
427: global $cfg;
428:
429: $iResult = self::PASS_OK;
430:
431: $cfgPw = $cfg['password'];
432:
433: if (!isset($cfgPw['check_password_mask']) || $cfgPw['check_password_mask'] == false) {
434:
435: return $iResult;
436: }
437:
438:
439: $iMinLength = self::MIN_PASS_LENGTH_DEFAULT;
440: if (isset($cfgPw['min_length'])) {
441: $iMinLength = (int) $cfgPw['min_length'];
442: }
443:
444:
445: if (strlen($password) < $iMinLength) {
446: $iResult = self::PASS_TO_SHORT;
447: }
448:
449:
450:
451: if ($iResult == self::PASS_OK && isset($cfgPw['numbers_mandatory']) && (int) $cfgPw['numbers_mandatory'] > 0) {
452:
453: $aNumbersInPassword = array();
454: preg_match_all('/[0-9]/', $password, $aNumbersInPassword);
455:
456: if (count($aNumbersInPassword[0]) < (int) $cfgPw['numbers_mandatory']) {
457: $iResult = self::PASS_NOT_ENOUGH_NUMBERS;
458: }
459: }
460:
461:
462: if ($iResult == self::PASS_OK && isset($cfgPw['symbols_mandatory']) && (int) $cfgPw['symbols_mandatory'] > 0) {
463:
464: $aSymbols = array();
465: $sSymbolsDefault = "/[|!@#$%&*\/=?,;.:\-_+~^ยจ\\\]/";
466: if (isset($cfgPw['symbols_regex']) && !empty($cfgPw['symbols_regex'])) {
467: $sSymbolsDefault = $cfgPw['symbols_regex'];
468: }
469:
470: preg_match_all($sSymbolsDefault, $password, $aSymbols);
471:
472: if (count($aSymbols[0]) < (int) $cfgPw['symbols_mandatory']) {
473: $iResult = self::PASS_NOT_ENOUGH_SYMBOLS;
474: }
475: }
476:
477:
478: if ($iResult == self::PASS_OK && isset($cfgPw['mixed_case_mandatory']) && (int) $cfgPw['mixed_case_mandatory'] > 0) {
479:
480: $aLowerCaseChars = array();
481: $aUpperCaseChars = array();
482:
483: preg_match_all('/[a-z]/', $password, $aLowerCaseChars);
484: preg_match_all('/[A-Z]/', $password, $aUpperCaseChars);
485:
486: if ((count($aLowerCaseChars[0]) < (int) $cfgPw['mixed_case_mandatory']) || (count($aUpperCaseChars[0]) < (int) $cfgPw['mixed_case_mandatory'])) {
487: $iResult = self::PASS_NOT_ENOUGH_MIXED_CHARS;
488: }
489: }
490:
491: return $iResult;
492: }
493:
494: 495: 496: 497: 498: 499:
500: public function encodePassword($password) {
501: return hash("sha256", md5($password).$this->get("salt"));
502: }
503:
504: 505: 506: 507: 508: 509: 510:
511: public function setField($sField, $mValue, $bSafe = true) {
512: if ('perms' === $sField) {
513: if (is_array($mValue)) {
514: $mValue = implode(',', $mValue);
515: }
516: }
517:
518: return parent::setField($sField, $mValue, $bSafe);
519: }
520:
521: 522: 523: 524: 525:
526: public function getUserId() {
527: return $this->get('user_id');
528: }
529:
530: 531: 532: 533: 534: 535:
536: public function setUserId($uid) {
537: $this->loadByPrimaryKey($uid);
538: }
539:
540: 541: 542: 543: 544: 545: 546:
547: public function setPassword($password) {
548: $result = self::checkPasswordMask($password);
549: if ($result != self::PASS_OK) {
550: return $result;
551: }
552:
553: $encPass = $this->encodePassword($password);
554:
555: if ($this->get('password') != $encPass) {
556: $this->set('password', $encPass);
557: $this->set('using_pw_request', '0');
558: }
559:
560: return $result;
561: }
562:
563: 564: 565: 566: 567: 568: 569: 570: 571: 572:
573: public function savePassword($password) {
574: if ($this->get('password') == $this->encodePassword($password)) {
575: return self::PASS_OK;
576: }
577:
578: $result = $this->setPassword($password);
579:
580: if ($this->store() === false) {
581: return false;
582: } else {
583: return $result;
584: }
585: }
586:
587: 588: 589: 590: 591:
592: public function getUserName() {
593: return $this->get('username');
594: }
595:
596: 597: 598: 599: 600:
601: public function setUserName($sUserName) {
602: if ($this->get('username') != $sUserName) {
603: $this->set('username', $sUserName);
604: }
605: }
606:
607: 608: 609: 610: 611:
612: public function getRealName() {
613: return $this->get('realname');
614: }
615:
616: 617: 618: 619: 620:
621: public function getEffectiveName() {
622: $name = trim($this->get('realname'));
623: if (strlen($name) == 0) {
624: $name = trim($this->get('username'));
625: }
626: return $name;
627: }
628:
629: 630: 631: 632: 633:
634: public function getMail() {
635: return $this->get('email');
636: }
637:
638: 639: 640: 641: 642:
643: public function getTelNumber() {
644: return $this->get('telephone');
645: }
646:
647: 648: 649: 650: 651: 652: 653: 654: 655:
656: public function getAddressData() {
657: $aret = array(
658: 'street' => $this->get('address_street'),
659: 'city' => $this->get('address_city'),
660: 'country' => $this->get('address_country'),
661: 'zip' => $this->get('address_zip')
662: );
663:
664: return $aret;
665: }
666:
667: 668: 669: 670: 671:
672: public function getUseWysi() {
673: return $this->get('wysi');
674: }
675:
676: 677: 678: 679: 680:
681: public function getValidDateTo() {
682: return $this->get('valid_to');
683: }
684:
685: 686: 687: 688: 689:
690: public function getValidDateFrom() {
691: return $this->get('valid_from');
692: }
693:
694: 695: 696: 697: 698:
699: public function getPerms() {
700: return $this->get('perms');
701: }
702:
703: 704: 705: 706: 707:
708: public function getPermsArray() {
709: return explode(',', $this->get('perms'));
710: }
711:
712: 713: 714: 715: 716:
717: public function setRealName($sRealName) {
718: if ($this->get('realname') != $sRealName) {
719: $this->set('realname', $sRealName);
720: }
721: }
722:
723: 724: 725: 726: 727:
728: public function setMail($sMail) {
729: if ($this->get('email') != $sMail) {
730: $this->set('email', $sMail);
731: }
732: }
733:
734: 735: 736: 737: 738:
739: public function setTelNumber($sTelNumber) {
740: if ($this->get('telephone') != $sTelNumber) {
741: $this->set('telephone', $sTelNumber);
742: }
743: }
744:
745: 746: 747: 748: 749: 750: 751: 752:
753: public function setAddressData($sStreet, $sCity, $sZip, $sCountry) {
754: if ($this->get('address_street') != $sStreet) {
755: $this->set('address_street', $sStreet);
756: }
757: if ($this->get('address_city') != $sCity) {
758: $this->set('address_city', $sCity);
759: }
760: if ($this->get('address_zip') != $sZip) {
761: $this->set('address_zip', $sZip);
762: }
763: if ($this->get('address_country') != $sCountry) {
764: $this->set('address_country', $sCountry);
765: }
766: }
767:
768: 769: 770: 771: 772:
773: public function setStreet($sStreet) {
774: if ($this->get('address_street') != $sStreet) {
775: $this->set('address_street', $sStreet);
776: }
777: }
778:
779: 780: 781: 782: 783:
784: public function setCity($sCity) {
785: if ($this->get('address_city') != $sCity) {
786: $this->set('address_city', $sCity);
787: }
788: }
789:
790: 791: 792: 793: 794:
795: public function setZip($sZip) {
796: if ($this->get('address_zip') != $sZip) {
797: $this->set('address_zip', $sZip);
798: }
799: }
800:
801: 802: 803: 804: 805:
806: public function setCountry($sCountry) {
807: if ($this->get('address_country') != $sCountry) {
808: $this->set('address_country', $sCountry);
809: }
810: }
811:
812: 813: 814: 815: 816:
817: public function setUseWysi($iUseWysi) {
818: if ($this->get('wysi') != $iUseWysi) {
819: $this->set('wysi', $iUseWysi);
820: }
821: }
822:
823: 824: 825: 826: 827:
828: public function setValidDateTo($sValidateTo) {
829: if ('0000-00-00' == $this->get('valid_to') && 0 == strlen(trim($sValidateTo))) {
830: return;
831: }
832: if ($this->get('valid_to') != $sValidateTo) {
833: $this->set('valid_to', $sValidateTo);
834: }
835: }
836:
837: 838: 839: 840: 841:
842: public function setValidDateFrom($sValidateFrom) {
843: if ('0000-00-00' == $this->get('valid_from') && 0 == strlen(trim($sValidateFrom))) {
844: return;
845: }
846: if ($this->get('valid_from') != $sValidateFrom) {
847: $this->set('valid_from', $sValidateFrom);
848: }
849: }
850:
851: 852: 853: 854: 855:
856: public function setPerms($perms) {
857: if ($this->get('perms') != $perms) {
858: $this->set('perms', $perms);
859: }
860: }
861:
862: 863: 864: 865: 866: 867: 868:
869: public function getEffectiveUserPerms() {
870: global $perm;
871:
872:
873:
874: $aUserPerms = array();
875: $aUserPermsSelf = explode(',', $this->values['perms']);
876: foreach ($aUserPermsSelf as $sPerm) {
877: if (trim($sPerm) != '') {
878: $aUserPerms[] = $sPerm;
879: }
880: }
881:
882:
883: $groups = $perm->getGroupsForUser($this->values['user_id']);
884:
885: foreach ($groups as $value) {
886:
887: $oGroup = new cApiGroup($value);
888: $aGroupPerms = $oGroup->getPermsArray();
889:
890:
891:
892: foreach ($aGroupPerms as $sPerm) {
893: if (trim($sPerm) != '' && !in_array($sPerm, $aUserPerms)) {
894: $aUserPerms[] = $sPerm;
895: }
896: }
897: }
898: return implode(',', $aUserPerms);
899: }
900:
901: 902: 903: 904: 905: 906: 907: 908: 909:
910: public function getGroupNamesByUserID($userid = null, $bAddDescription = true) {
911: $userid = (null === $userid)? $this->get('user_id') : $userid;
912:
913: $aGroups = array();
914:
915: $oGroupColl = new cApiGroupCollection();
916: $groups = $oGroupColl->fetchByUserID($userid);
917:
918: foreach ($groups as $group) {
919: $sTemp = $group->get('groupname');
920: $sTemp = substr($sTemp, 4, strlen($sTemp) - 4);
921:
922: if (true === $bAddDescription) {
923: $sDescription = trim($group->get('description'));
924: if ($sDescription != '') {
925: $sTemp .= ' (' . $sDescription . ')';
926: }
927: }
928:
929: $aGroups[] = $sTemp;
930: }
931:
932: return $aGroups;
933: }
934:
935: 936: 937: 938: 939: 940: 941:
942: public function getGroupIDsByUserID($userid) {
943: $userid = (null === $userid)? $this->get('user_id') : $userid;
944:
945: $aGroups = array();
946:
947: $oGroupColl = new cApiGroupCollection();
948: $groups = $oGroupColl->fetchByUserID($userid);
949:
950: foreach ($groups as $group) {
951: $aGroups[] = $group->get('group_id');
952: }
953:
954: return $aGroups;
955: }
956:
957: 958: 959: 960: 961: 962: 963: 964: 965:
966: public function getUserProperty($type, $name, $group = false) {
967: global $perm;
968:
969: if (!is_object($perm)) {
970: $perm = new cPermission();
971: }
972:
973: $result = false;
974:
975: if ($group == true) {
976:
977: $groups = $perm->getGroupsForUser($this->values['user_id']);
978:
979: foreach ($groups as $groupid) {
980: $groupPropColl = new cApiGroupPropertyCollection($groupid);
981: $groupProp = $groupPropColl->fetchByGroupIdTypeName($type, $name);
982: if ($groupProp) {
983: $result = $groupProp->get('value');
984: }
985: }
986: }
987:
988:
989: $userPropColl = new cApiUserPropertyCollection($this->values['user_id']);
990: $userProp = $userPropColl->fetchByUserIdTypeName($type, $name);
991: if ($userProp) {
992: $result = $userProp->get('value');
993: }
994:
995: return ($result !== false)? $result : false;
996: }
997:
998: 999: 1000: 1001: 1002: 1003: 1004: 1005: 1006: 1007: 1008: 1009: 1010: 1011:
1012: public function getUserPropertiesByType($type, $group = false) {
1013: global $perm;
1014:
1015: if (!is_object($perm)) {
1016: $perm = new cPermission();
1017: }
1018:
1019: $props = array();
1020:
1021: if ($group == true) {
1022:
1023: $groups = $perm->getGroupsForUser($this->values['user_id']);
1024: foreach ($groups as $groupid) {
1025: $groupPropColl = new cApiGroupPropertyCollection($groupid);
1026: $groupProps = $groupPropColl->fetchByGroupIdType($type);
1027: foreach ($groupProps as $groupProp) {
1028: $props[$groupProp->get('name')] = $groupProp->get('value');
1029: }
1030: }
1031: }
1032:
1033:
1034: $userPropColl = new cApiUserPropertyCollection($this->values['user_id']);
1035: $userProps = $userPropColl->fetchByUserIdType($type);
1036: foreach ($userProps as $userProp) {
1037: $props[$userProp->get('name')] = $userProp->get('value');
1038: }
1039:
1040: return $props;
1041: }
1042:
1043: 1044: 1045: 1046: 1047: 1048: 1049: 1050: 1051: 1052: 1053: 1054: 1055:
1056: public function getUserProperties() {
1057: $userPropColl = new cApiUserPropertyCollection($this->values['user_id']);
1058: $userProps = $userPropColl->fetchByUserId();
1059:
1060: $props = array();
1061:
1062: foreach ($userProps as $userProp) {
1063: $props[$userProp->get('iduserprop')] = array(
1064: 'name' => $userProp->get('name'),
1065: 'type' => $userProp->get('type'),
1066: 'value' => $userProp->get('value')
1067: );
1068: }
1069:
1070: return $props;
1071: }
1072:
1073: 1074: 1075: 1076: 1077: 1078: 1079: 1080: 1081:
1082: public function setUserProperty($type, $name, $value) {
1083: $userPropColl = new cApiUserPropertyCollection($this->values['user_id']);
1084: $userProps = $userPropColl->setValueByTypeName($type, $name, $value);
1085: }
1086:
1087: 1088: 1089: 1090: 1091: 1092: 1093:
1094: public function deleteUserProperty($type, $name) {
1095: $userPropColl = new cApiUserPropertyCollection($this->values['user_id']);
1096: return $userPropColl->deleteByUserIdTypeName($type, $name);
1097: }
1098:
1099: 1100: 1101: 1102: 1103: 1104: 1105:
1106: public static function getErrorString($iErrorCode) {
1107: global $cfg;
1108:
1109: $sError = '';
1110:
1111: switch ($iErrorCode) {
1112: case self::PASS_NOT_ENOUGH_MIXED_CHARS:
1113: $sError = sprintf(i18n('Please use at least %d lower and upper case characters in your password!'), $cfg['password']['mixed_case_mandatory']);
1114: break;
1115: case self::PASS_NOT_ENOUGH_NUMBERS:
1116: $sError = sprintf(i18n('Please use at least %d numbers in your password!'), $cfg['password']['numbers_mandatory']);
1117: break;
1118: case self::PASS_NOT_ENOUGH_SYMBOLS:
1119: $sError = sprintf(i18n('Please use at least %d symbols in your password!'), $cfg['password']['symbols_mandatory']);
1120: break;
1121: case self::PASS_TO_SHORT:
1122: $sError = sprintf(i18n('Password is too short! Please use at least %d signs.'), ($cfg['password']['min_length'] > 0? $cfg['password']['min_length'] : self::MIN_PASS_LENGTH_DEFAULT));
1123: break;
1124: case self::PASS_NOT_ENOUGH_DIFFERENT_CHARS:
1125: $sError = sprintf(i18n('Password does not contain enough different characters.'));
1126: break;
1127: case self::PASS_NOT_STRONG:
1128: $sError = i18n('Please choose a more secure password!');
1129: break;
1130: default:
1131: $sError = 'I do not really know what has happened. But your password does not match the
1132: policies! Please consult your administrator. The error code is #' . $iErrorCode;
1133: }
1134:
1135: return $sError;
1136: }
1137:
1138: }
1139: