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