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: public function fetchSystemAdmins($forceActive = false) {
176: $users = array();
177:
178: $where = 'perms LIKE "%sysadmin%"';
179: if ($forceActive === true) {
180: $where .= " AND (valid_from <= NOW() OR valid_from = '0000-00-00')" . " AND (valid_to >= NOW() OR valid_to = '0000-00-00')";
181: }
182:
183: $this->select($where);
184: while (($item = $this->next()) !== false) {
185: $users[] = clone $item;
186: }
187:
188: return $users;
189: }
190:
191: 192: 193: 194: 195: 196:
197: public function fetchClientAdmins($client) {
198: $client = (int) $client;
199: $users = array();
200:
201: $where = 'perms LIKE "%admin[' . $client . ']%"';
202:
203: $this->select($where);
204: while (($item = $this->next()) !== false) {
205: $users[] = clone $item;
206: }
207:
208: return $users;
209: }
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: class cApiUser extends Item {
267:
268: 269: 270: 271: 272: 273:
274: const PASS_OK = 0;
275:
276: 277: 278: 279: 280: 281:
282: const PASS_TO_SHORT = 1;
283:
284: 285: 286: 287: 288: 289:
290: const PASS_NOT_STRONG = 2;
291:
292: 293: 294: 295: 296: 297:
298: const PASS_NOT_COMPLEX = 3;
299:
300: 301: 302: 303: 304: 305:
306: const PASS_NOT_ENOUGH_NUMBERS = 4;
307:
308: 309: 310: 311: 312:
313: const PASS_NOT_ENOUGH_SYMBOLS = 5;
314:
315: 316: 317: 318: 319: 320:
321: const PASS_NOT_ENOUGH_MIXED_CHARS = 6;
322:
323: 324: 325: 326: 327: 328:
329: const PASS_NOT_ENOUGH_DIFFERENT_CHARS = 7;
330:
331: 332: 333: 334: 335: 336: 337:
338: const EXCEPTION_USERNAME_EXISTS = 8;
339:
340: 341: 342: 343: 344: 345: 346:
347: const EXCEPTION_PASSWORD_INVALID = 9;
348:
349: 350: 351: 352: 353: 354: 355:
356: const MIN_PASS_LENGTH_DEFAULT = 8;
357:
358: 359: 360: 361: 362:
363: public function __construct($mId = false) {
364: global $cfg;
365: parent::__construct($cfg['tab']['user'], 'user_id');
366: $this->setFilters(array(), array());
367: if ($mId !== false) {
368: $this->loadByPrimaryKey($mId);
369: }
370: }
371:
372: 373: 374: 375: 376: 377:
378: public function loadUserByUserID($userId) {
379: return $this->loadByPrimaryKey($userId);
380: }
381:
382: 383: 384: 385: 386: 387:
388: public function loadUserByUsername($userName) {
389: return $this->loadBy('username', $userName);
390: }
391:
392: 393: 394: 395: 396: 397:
398: public static function userExists($userId) {
399: $test = new cApiUser();
400:
401: return $test->loadByPrimaryKey($userId);
402: }
403:
404: 405: 406: 407: 408: 409:
410: public static function usernameExists($username) {
411: $user = new cApiUser();
412: return $user->loadBy('username', $username);
413: }
414:
415: 416: 417: 418: 419: 420: 421: 422: 423: 424:
425: public static function checkPasswordMask($password) {
426: global $cfg;
427:
428: $iResult = self::PASS_OK;
429:
430: $cfgPw = $cfg['password'];
431:
432: if (!isset($cfgPw['check_password_mask']) || $cfgPw['check_password_mask'] == false) {
433:
434: return $iResult;
435: }
436:
437:
438: $iMinLength = self::MIN_PASS_LENGTH_DEFAULT;
439: if (isset($cfgPw['min_length'])) {
440: $iMinLength = (int) $cfgPw['min_length'];
441: }
442:
443:
444: if (strlen($password) < $iMinLength) {
445: $iResult = self::PASS_TO_SHORT;
446: }
447:
448:
449:
450: if ($iResult == self::PASS_OK && isset($cfgPw['numbers_mandatory']) && (int) $cfgPw['numbers_mandatory'] > 0) {
451:
452: $aNumbersInPassword = array();
453: preg_match_all('/[0-9]/', $password, $aNumbersInPassword);
454:
455: if (count($aNumbersInPassword[0]) < (int) $cfgPw['numbers_mandatory']) {
456: $iResult = self::PASS_NOT_ENOUGH_NUMBERS;
457: }
458: }
459:
460:
461: if ($iResult == self::PASS_OK && isset($cfgPw['symbols_mandatory']) && (int) $cfgPw['symbols_mandatory'] > 0) {
462:
463: $aSymbols = array();
464: $sSymbolsDefault = "/[|!@#$%&*\/=?,;.:\-_+~^ยจ\\\]/";
465: if (isset($cfgPw['symbols_regex']) && !empty($cfgPw['symbols_regex'])) {
466: $sSymbolsDefault = $cfgPw['symbols_regex'];
467: }
468:
469: preg_match_all($sSymbolsDefault, $password, $aSymbols);
470:
471: if (count($aSymbols[0]) < (int) $cfgPw['symbols_mandatory']) {
472: $iResult = self::PASS_NOT_ENOUGH_SYMBOLS;
473: }
474: }
475:
476:
477: if ($iResult == self::PASS_OK && isset($cfgPw['mixed_case_mandatory']) && (int) $cfgPw['mixed_case_mandatory'] > 0) {
478:
479: $aLowerCaseChars = array();
480: $aUpperCaseChars = array();
481:
482: preg_match_all('/[a-z]/', $password, $aLowerCaseChars);
483: preg_match_all('/[A-Z]/', $password, $aUpperCaseChars);
484:
485: if ((count($aLowerCaseChars[0]) < (int) $cfgPw['mixed_case_mandatory']) || (count($aUpperCaseChars[0]) < (int) $cfgPw['mixed_case_mandatory'])) {
486: $iResult = self::PASS_NOT_ENOUGH_MIXED_CHARS;
487: }
488: }
489:
490: return $iResult;
491: }
492:
493: 494: 495: 496: 497: 498:
499: public function encodePassword($password) {
500: return hash("sha256", md5($password) . $this->get("salt"));
501: }
502:
503: 504: 505: 506: 507: 508: 509: 510: 511:
512: public function setField($sField, $mValue, $bSafe = true) {
513: if ('perms' === $sField) {
514: if (is_array($mValue)) {
515: $mValue = implode(',', $mValue);
516: }
517: }
518:
519: return parent::setField($sField, $mValue, $bSafe);
520: }
521:
522: 523: 524: 525: 526:
527: public function getUserId() {
528: return $this->get('user_id');
529: }
530:
531: 532: 533: 534: 535: 536:
537: public function setUserId($uid) {
538: $this->loadByPrimaryKey($uid);
539: }
540:
541: 542: 543: 544: 545: 546: 547:
548: public function setPassword($password) {
549: $result = self::checkPasswordMask($password);
550: if ($result != self::PASS_OK) {
551: return $result;
552: }
553:
554: $encPass = $this->encodePassword($password);
555:
556: if ($this->get('password') != $encPass) {
557: $this->set('password', $encPass);
558: $this->set('using_pw_request', '0');
559: }
560:
561: return $result;
562: }
563:
564: 565: 566: 567: 568: 569: 570: 571: 572: 573:
574: public function savePassword($password) {
575: if ($this->get('password') == $this->encodePassword($password)) {
576: return self::PASS_OK;
577: }
578:
579: $result = $this->setPassword($password);
580:
581: if ($this->store() === false) {
582: return false;
583: } else {
584: return $result;
585: }
586: }
587:
588: 589: 590: 591: 592:
593: public function getUserName() {
594: return $this->get('username');
595: }
596:
597: 598: 599: 600: 601:
602: public function setUserName($sUserName) {
603: if ($this->get('username') != $sUserName) {
604: $this->set('username', $sUserName);
605: }
606: }
607:
608: 609: 610: 611: 612:
613: public function getRealName() {
614: return $this->get('realname');
615: }
616:
617: 618: 619: 620: 621:
622: public function getEffectiveName() {
623: $name = trim($this->get('realname'));
624: if (strlen($name) == 0) {
625: $name = trim($this->get('username'));
626: }
627: return $name;
628: }
629:
630: 631: 632: 633: 634:
635: public function getMail() {
636: return $this->get('email');
637: }
638:
639: 640: 641: 642: 643:
644: public function getTelNumber() {
645: return $this->get('telephone');
646: }
647:
648: 649: 650: 651: 652: 653: 654: 655: 656:
657: public function getAddressData() {
658: $aret = array(
659: 'street' => $this->get('address_street'),
660: 'city' => $this->get('address_city'),
661: 'country' => $this->get('address_country'),
662: 'zip' => $this->get('address_zip')
663: );
664:
665: return $aret;
666: }
667:
668: 669: 670: 671: 672:
673: public function getUseWysi() {
674: return $this->get('wysi');
675: }
676:
677: 678: 679: 680: 681:
682: public function getValidDateTo() {
683: return $this->get('valid_to');
684: }
685:
686: 687: 688: 689: 690:
691: public function getValidDateFrom() {
692: return $this->get('valid_from');
693: }
694:
695: 696: 697: 698: 699:
700: public function getPerms() {
701: return $this->get('perms');
702: }
703:
704: 705: 706: 707: 708:
709: public function getPermsArray() {
710: return explode(',', $this->get('perms'));
711: }
712:
713: 714: 715: 716: 717:
718: public function setRealName($sRealName) {
719: if ($this->get('realname') != $sRealName) {
720: $this->set('realname', $sRealName);
721: }
722: }
723:
724: 725: 726: 727: 728:
729: public function setMail($sMail) {
730: if ($this->get('email') != $sMail) {
731: $this->set('email', $sMail);
732: }
733: }
734:
735: 736: 737: 738: 739:
740: public function setTelNumber($sTelNumber) {
741: if ($this->get('telephone') != $sTelNumber) {
742: $this->set('telephone', $sTelNumber);
743: }
744: }
745:
746: 747: 748: 749: 750: 751: 752: 753:
754: public function setAddressData($sStreet, $sCity, $sZip, $sCountry) {
755: if ($this->get('address_street') != $sStreet) {
756: $this->set('address_street', $sStreet);
757: }
758: if ($this->get('address_city') != $sCity) {
759: $this->set('address_city', $sCity);
760: }
761: if ($this->get('address_zip') != $sZip) {
762: $this->set('address_zip', $sZip);
763: }
764: if ($this->get('address_country') != $sCountry) {
765: $this->set('address_country', $sCountry);
766: }
767: }
768:
769: 770: 771: 772: 773:
774: public function setStreet($sStreet) {
775: if ($this->get('address_street') != $sStreet) {
776: $this->set('address_street', $sStreet);
777: }
778: }
779:
780: 781: 782: 783: 784:
785: public function setCity($sCity) {
786: if ($this->get('address_city') != $sCity) {
787: $this->set('address_city', $sCity);
788: }
789: }
790:
791: 792: 793: 794: 795:
796: public function setZip($sZip) {
797: if ($this->get('address_zip') != $sZip) {
798: $this->set('address_zip', $sZip);
799: }
800: }
801:
802: 803: 804: 805: 806:
807: public function setCountry($sCountry) {
808: if ($this->get('address_country') != $sCountry) {
809: $this->set('address_country', $sCountry);
810: }
811: }
812:
813: 814: 815: 816: 817:
818: public function setUseWysi($iUseWysi) {
819: if ($this->get('wysi') != $iUseWysi) {
820: $this->set('wysi', $iUseWysi);
821: }
822: }
823:
824: 825: 826: 827: 828:
829: public function setValidDateTo($sValidateTo) {
830: if ('0000-00-00' == $this->get('valid_to') && 0 == strlen(trim($sValidateTo))) {
831: return;
832: }
833: if ($this->get('valid_to') != $sValidateTo) {
834: $this->set('valid_to', $sValidateTo);
835: }
836: }
837:
838: 839: 840: 841: 842:
843: public function setValidDateFrom($sValidateFrom) {
844: if ('0000-00-00' == $this->get('valid_from') && 0 == strlen(trim($sValidateFrom))) {
845: return;
846: }
847: if ($this->get('valid_from') != $sValidateFrom) {
848: $this->set('valid_from', $sValidateFrom);
849: }
850: }
851:
852: 853: 854: 855: 856:
857: public function setPerms($perms) {
858: if ($this->get('perms') != $perms) {
859: $this->set('perms', $perms);
860: }
861: }
862:
863: 864: 865: 866: 867: 868: 869:
870: public function getEffectiveUserPerms() {
871: global $perm;
872:
873:
874:
875: $aUserPerms = array();
876: $aUserPermsSelf = explode(',', $this->values['perms']);
877: foreach ($aUserPermsSelf as $sPerm) {
878: if (trim($sPerm) != '') {
879: $aUserPerms[] = $sPerm;
880: }
881: }
882:
883:
884: $groups = $perm->getGroupsForUser($this->values['user_id']);
885:
886: foreach ($groups as $value) {
887:
888: $oGroup = new cApiGroup($value);
889: $aGroupPerms = $oGroup->getPermsArray();
890:
891:
892:
893: foreach ($aGroupPerms as $sPerm) {
894: if (trim($sPerm) != '' && !in_array($sPerm, $aUserPerms)) {
895: $aUserPerms[] = $sPerm;
896: }
897: }
898: }
899: return implode(',', $aUserPerms);
900: }
901:
902: 903: 904: 905: 906: 907: 908: 909: 910:
911: public function getGroupNamesByUserID($userid = NULL, $bAddDescription = true) {
912: $userid = (NULL === $userid) ? $this->get('user_id') : $userid;
913:
914: $aGroups = array();
915:
916: $oGroupColl = new cApiGroupCollection();
917: $groups = $oGroupColl->fetchByUserID($userid);
918:
919: foreach ($groups as $group) {
920: $sTemp = $group->get('groupname');
921: $sTemp = substr($sTemp, 4, strlen($sTemp) - 4);
922:
923: if (true === $bAddDescription) {
924: $sDescription = trim($group->get('description'));
925: if ($sDescription != '') {
926: $sTemp .= ' (' . $sDescription . ')';
927: }
928: }
929:
930: $aGroups[] = $sTemp;
931: }
932:
933: return $aGroups;
934: }
935:
936: 937: 938: 939: 940: 941: 942:
943: public function getGroupIDsByUserID($userid) {
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: $aGroups[] = $group->get('group_id');
953: }
954:
955: return $aGroups;
956: }
957:
958: 959: 960: 961: 962: 963: 964: 965: 966:
967: public function getUserProperty($type, $name, $group = false) {
968: global $perm;
969:
970: if (!is_object($perm)) {
971: $perm = new cPermission();
972: }
973:
974: $result = false;
975:
976: if ($group == true) {
977:
978: $groups = $perm->getGroupsForUser($this->values['user_id']);
979:
980: foreach ($groups as $groupid) {
981: $groupPropColl = new cApiGroupPropertyCollection($groupid);
982: $groupProp = $groupPropColl->fetchByGroupIdTypeName($type, $name);
983: if ($groupProp) {
984: $result = $groupProp->get('value');
985: }
986: }
987: }
988:
989:
990: $userPropColl = new cApiUserPropertyCollection($this->values['user_id']);
991: $userProp = $userPropColl->fetchByUserIdTypeName($type, $name);
992: if ($userProp) {
993: $result = $userProp->get('value');
994: }
995:
996: return ($result !== false) ? $result : false;
997: }
998:
999: 1000: 1001: 1002: 1003: 1004: 1005: 1006: 1007: 1008: 1009: 1010: 1011: 1012:
1013: public function getUserPropertiesByType($type, $group = false) {
1014: global $perm;
1015:
1016: if (!is_object($perm)) {
1017: $perm = new cPermission();
1018: }
1019:
1020: $props = array();
1021:
1022: if ($group == true) {
1023:
1024: $groups = $perm->getGroupsForUser($this->values['user_id']);
1025: foreach ($groups as $groupid) {
1026: $groupPropColl = new cApiGroupPropertyCollection($groupid);
1027: $groupProps = $groupPropColl->fetchByGroupIdType($type);
1028: foreach ($groupProps as $groupProp) {
1029: $props[$groupProp->get('name')] = $groupProp->get('value');
1030: }
1031: }
1032: }
1033:
1034:
1035: $userPropColl = new cApiUserPropertyCollection($this->values['user_id']);
1036: $userProps = $userPropColl->fetchByUserIdType($type);
1037: foreach ($userProps as $userProp) {
1038: $props[$userProp->get('name')] = $userProp->get('value');
1039: }
1040:
1041: return $props;
1042: }
1043:
1044: 1045: 1046: 1047: 1048: 1049: 1050: 1051: 1052: 1053: 1054: 1055: 1056:
1057: public function getUserProperties() {
1058: $userPropColl = new cApiUserPropertyCollection($this->values['user_id']);
1059: $userProps = $userPropColl->fetchByUserId();
1060:
1061: $props = array();
1062:
1063: foreach ($userProps as $userProp) {
1064: $props[$userProp->get('iduserprop')] = array(
1065: 'name' => $userProp->get('name'),
1066: 'type' => $userProp->get('type'),
1067: 'value' => $userProp->get('value')
1068: );
1069: }
1070:
1071: return $props;
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: