User.class.php (26396B)
1 <?php 2 3 namespace cms\model; 4 5 // OpenRat Content Management System 6 // Copyright (C) 2002-2012 Jan Dankert, cms@jandankert.de 7 // 8 // This program is free software; you can redistribute it and/or 9 // modify it under the terms of the GNU General Public License 10 // as published by the Free Software Foundation; either version 2 11 // of the License, or (at your option) any later version. 12 // 13 // This program is distributed in the hope that it will be useful, 14 // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 // GNU General Public License for more details. 17 // 18 // You should have received a copy of the GNU General Public License 19 // along with this program; if not, write to the Free Software 20 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 use security\Password; 22 23 24 /** 25 * Darstellen eines Benutzers 26 * 27 * @author Jan Dankert 28 */ 29 class User extends ModelBase 30 { 31 var $userid = 0; 32 var $error = ''; 33 34 var $name = ''; 35 var $fullname = ''; 36 var $ldap_dn; 37 var $tel; 38 var $mail; 39 var $desc; 40 var $style; 41 var $isAdmin; 42 var $rights; 43 var $loginDate = 0; 44 45 var $language; 46 var $timezone; 47 var $passwordExpires; 48 var $passwordAlgo; 49 50 var $lastLogin; 51 var $otpSecret; 52 var $hotp ; 53 var $hotpCount; 54 var $totp ; 55 56 57 58 var $mustChangePassword = false; 59 var $groups = null; 60 var $loginModuleName = null; 61 62 // Konstruktor 63 public function __construct( $userid='' ) 64 { 65 if ( is_numeric($userid) ) 66 $this->userid = $userid; 67 } 68 69 70 /** 71 * get all users. 72 * 73 * @return array 74 */ 75 public static function listAll() 76 { 77 $sql = db()->sql( 'SELECT id,name '. 78 ' FROM {{user}}'. 79 ' ORDER BY name' ); 80 81 return $sql->getAssoc(); 82 } 83 84 85 /** 86 * Get all users. 87 * 88 * @return array with user objects 89 */ 90 public static function getAllUsers() 91 { 92 $list = array(); 93 $sql = db()->sql( 'SELECT * '. 94 ' FROM {{user}}'. 95 ' ORDER BY name' ); 96 97 foreach($sql->getAll() as $row ) 98 { 99 $user = new User(); 100 $user->setDatabaseRow( $row ); 101 102 $list[] = $user; 103 } 104 105 return $list; 106 } 107 108 109 /** 110 * Benutzer als aktiven Benutzer in die Session schreiben. 111 */ 112 public function setCurrent() 113 { 114 $this->loginDate = time(); 115 116 \Session::setUser( $this ); 117 } 118 119 120 121 /** 122 * Benutzer als aktiven Benutzer in die Session schreiben. 123 */ 124 public function updateLoginTimestamp() 125 { 126 $stmt = db()->sql( <<<SQL 127 UPDATE {{user}} 128 SET last_login={time} 129 WHERE id={userid} 130 SQL 131 ); 132 $stmt->setInt( 'time' ,time() ); 133 $stmt->setInt( 'userid',$this->userid ); 134 135 // Datenbankabfrage ausfuehren 136 $stmt->query(); 137 } 138 139 140 /** 141 * Erzeugt eine WHERE-Bedingung zur Verwendung in einer SQL-Anfrage.<br> 142 * Es wird eine Oder-Liste mit allen Gruppen-Ids erzeugt. 143 * 144 * @return String SQL-WHERE-Bedingung 145 */ 146 function getGroupClause() 147 { 148 $groupIds = $this->getGroupIds(); 149 150 if ( count($groupIds) > 0 ) 151 $groupclause = ' groupid='.implode(' OR groupid=',$groupIds ); 152 else 153 $groupclause = ' 1=0 '; 154 155 return $groupclause; 156 } 157 158 159 /** 160 * Lesen aller Projekte, fuer die der Benutzer berechtigt ist. 161 * 162 * @return Array [Projekt-Id] = Projekt-Name 163 */ 164 public function getReadableProjects() 165 { 166 $db = db_connection(); 167 168 if ( $this->isAdmin ) 169 { 170 // Administratoren haben Rechte auf alle Projekte. 171 return Project::getAllProjects(); 172 } 173 else 174 { 175 $groupClause = $this->getGroupClause(); 176 $sql = $db->sql(<<<SQL 177 SELECT DISTINCT {{project}}.id,{{project}}.name 178 FROM {{object}} 179 LEFT JOIN {{acl}} ON {{object}}.id = {{acl}}.objectid 180 LEFT JOIN {{project}} ON {{project}}.id = {{object}}.projectid 181 WHERE {{object}}.parentid IS NULL AND 182 {{acl}}.id IS NOT NULL AND 183 ( {{acl}}.userid={userid} OR 184 $groupClause OR 185 ({{acl}}.userid IS NULL AND {{acl}}.groupid IS NULL)) 186 ORDER BY {{project}}.name 187 SQL 188 ); 189 $sql->setInt ( 'userid',$this->userid ); 190 191 return $sql->getAssoc(); 192 } 193 194 } 195 196 197 198 /** 199 * Ermittelt alls Projekte, fuer die der Benutzer berechtigt ist. 200 * @return Array [0..n] = Projekt-Id 201 */ 202 function getReadableProjectIds() 203 { 204 return array_keys( $this->getReadableProjects() ); 205 } 206 207 208 209 /** 210 * Ermittelt zu diesem Benutzer den Login-Token. 211 */ 212 function createNewLoginToken() 213 { 214 $selector = Password::randomHexString(24); 215 $token = Password::randomHexString(24); 216 217 $tokenHash = Password::hash($token,Password::ALGO_SHA1); 218 219 $stmt = db()->sql( 'SELECT max(id) FROM {{auth}}'); 220 $count = $stmt->getOne(); 221 222 $stmt = db()->sql( <<<SQL 223 INSERT INTO {{auth}} (id,userid,selector,token,token_algo,expires,create_date,platform,name) 224 VALUES( {id},{userid},{selector},{token},{token_algo},{expires},{create_date},{platform},{name} ) 225 SQL 226 ); 227 $expirationPeriodDays = Conf()->subset('user')->subset('security')->get('token_expires_after_days',730); 228 229 $stmt->setInt( 'id' ,++$count ); 230 $stmt->setInt( 'userid' ,$this->userid ); 231 232 $stmt->setString( 'selector' ,$selector ); 233 $stmt->setString( 'token' ,$tokenHash ); 234 $stmt->setInt ( 'token_algo' ,Password::ALGO_SHA1 ); 235 236 $stmt->setInt( 'expires' ,time() + ($expirationPeriodDays*24*60*60) ); 237 $stmt->setInt( 'create_date',time() ); 238 239 $browser = new \Browser(); 240 $stmt->setString( 'platform',$browser->platform ); 241 $stmt->setString( 'name' ,$browser->name ); 242 $row = $stmt->getRow(); 243 244 // Zusammensetzen des Tokens 245 return $selector.'.'.$token; 246 } 247 248 249 /** 250 * Ermittelt zu diesem Benutzer den Login-Token. 251 */ 252 function deleteLoginToken( $selector ) 253 { 254 $stmt = db()->sql( <<<SQL 255 DELETE FROM {{auth}} 256 WHERE selector = {selector} 257 SQL 258 ); 259 $stmt->setString('selector',$selector ); 260 $stmt->execute(); 261 } 262 263 264 /** 265 * Lesen Benutzer aus der Datenbank. 266 */ 267 public function load() 268 { 269 $stmt = db()->sql( 'SELECT * FROM {{user}}'. 270 ' WHERE id={userid}' ); 271 $stmt->setInt( 'userid',$this->userid ); 272 $row = $stmt->getRow(); 273 274 if ( count($row) == 0 ) 275 throw new \ObjectNotFoundException(); 276 277 $this->setDatabaseRow( $row ); 278 } 279 280 281 /** 282 * Benutzerobjekt �ber Benutzernamen ermitteln.<br> 283 * Liefert ein neues Benutzerobjekt zur�ck. 284 * 285 * @static 286 * @param name Benutzername 287 */ 288 public static function loadWithName( $name ) 289 { 290 // Benutzer �ber Namen suchen 291 $sql = db()->sql( 'SELECT id FROM {{user}}'. 292 ' WHERE name={name}' ); 293 //Html::debug($sql); 294 $sql->setString( 'name',$name ); 295 296 $userId = $sql->getOne(); 297 298 if (empty($userId)) 299 return null; // no user found. 300 301 // Benutzer �ber Id instanziieren 302 $neuerUser = new \cms\model\User( $userId ); 303 304 $neuerUser->load(); 305 306 return $neuerUser; 307 } 308 309 310 311 /** 312 * Stellt fest, ob der Benutzer korrekt geladen ist. 313 */ 314 public function isValid() 315 { 316 return intval($this->userid) > 0; 317 } 318 319 320 321 /** 322 * Lesen Benutzer aus der Datenbank 323 */ 324 protected function setDatabaseRow( $row ) 325 { 326 global $conf; 327 328 $this->userid = $row['id' ]; 329 $this->name = $row['name' ]; 330 $this->style = $row['style' ]; 331 $this->isAdmin = ( $row['is_admin'] == '1'); 332 $this->ldap_dn = $row['ldap_dn' ]; 333 $this->fullname = $row['fullname']; 334 $this->tel = $row['tel' ]; 335 $this->mail = $row['mail' ]; 336 $this->desc = $row['descr' ]; 337 $this->language = $row['language']; 338 $this->timezone = $row['timezone']; 339 $this->lastLogin = $row['last_login']; 340 $this->otpSecret = $row['otp_secret']; 341 $this->hotp = ($row['hotp']==1); 342 $this->hotpCount = $row['hotp_counter']; 343 $this->totp = ($row['totp']==1); 344 $this->passwordExpires = $row['password_expires']; 345 $this->passwordAlgo = $row['password_algo']; 346 347 if ( $this->fullname == '' ) 348 $this->fullname = $this->name; 349 350 if ( empty($this->style) ) 351 $this->style = $conf['interface']['style']['default']; 352 } 353 354 355 356 /** 357 * Namen ermitteln.<br> 358 * Wenn "fullname" gefuellt, dann diesen benutzen, sonst den Benutzernamen. 359 */ 360 function getName() 361 { 362 if ( empty($this->fullname)) 363 return $this->name; 364 else 365 return $this->fullname; 366 } 367 368 369 370 /** 371 * Liest einen Benutzernamen aus der Datenbank. 372 * 373 * @param int Benutzer-Id 374 * @return String Benutzername 375 */ 376 function getUserName( $userid ) 377 { 378 $db = db_connection(); 379 380 $sql = $db->sql( 'SELECT name FROM {{user}}'. 381 ' WHERE id={userid}' ); 382 $sql->setInt( 'userid',$userid ); 383 384 $name = $sql->getOne(); 385 386 if ( $name == '' ) 387 return lang('UNKNOWN'); 388 else return $name; 389 } 390 391 392 /** 393 * Speichern Benutzer in der Datenbank. 394 */ 395 function save() 396 { 397 $db = db_connection(); 398 399 $sql = $db->sql( <<<SQL 400 UPDATE {{user}} 401 SET name={name}, 402 fullname={fullname}, 403 ldap_dn ={ldap_dn} , 404 tel ={tel} , 405 descr ={desc} , 406 mail ={mail} , 407 style ={style} , 408 language = {language}, 409 timezone = {timezone}, 410 is_admin = {isAdmin}, 411 totp = {totp}, 412 hotp = {hotp} 413 WHERE id={userid} 414 SQL 415 ); 416 $sql->setString ( 'name' ,$this->name ); 417 $sql->setString ( 'fullname',$this->fullname); 418 $sql->setString ( 'ldap_dn' ,$this->ldap_dn ); 419 $sql->setString ( 'tel' ,$this->tel ); 420 $sql->setString ( 'desc' ,$this->desc ); 421 $sql->setString ( 'mail' ,$this->mail ); 422 $sql->setString ( 'style' ,$this->style ); 423 $sql->setString ( 'language',$this->language); 424 $sql->setString ( 'timezone',$this->timezone); 425 $sql->setBoolean( 'isAdmin' ,$this->isAdmin ); 426 $sql->setBoolean( 'totp' ,$this->totp ); 427 $sql->setBoolean( 'hotp' ,$this->hotp ); 428 $sql->setInt ( 'userid' ,$this->userid ); 429 430 // Datenbankabfrage ausfuehren 431 $sql->query(); 432 } 433 434 435 /** 436 * Benutzer hinzuf�gen 437 * 438 * @param String $name Benutzername 439 */ 440 function add( $name = '' ) 441 { 442 if ( $name != '' ) 443 $this->name = $name; 444 445 $db = db_connection(); 446 447 $sql = $db->sql('SELECT MAX(id) FROM {{user}}'); 448 $this->userid = intval($sql->getOne())+1; 449 450 $sql = $db->sql('INSERT INTO {{user}}'. 451 ' (id,name,password_hash,ldap_dn,fullname,tel,mail,descr,style,is_admin,password_salt)'. 452 " VALUES( {userid},{name},'','','','','','','default',0,'' )" ); 453 $sql->setInt ('userid',$this->userid); 454 $sql->setString('name' ,$this->name ); 455 456 // Datenbankbefehl ausfuehren 457 $sql->query(); 458 459 $this->addNewUserGroups(); // Neue Gruppen hinzufuegen. 460 461 $this->renewOTPSecret(); 462 } 463 464 465 466 /** 467 * Zu einem neuen Benutzer automatisch Gruppen hinzufuegen. 468 * Diese Methode wird automatisch in "add()" aufgerufen. 469 */ 470 function addNewUserGroups() 471 { 472 global $conf; 473 $groupNames = explode(',',@$conf['security']['newuser']['groups']); 474 475 if ( count($groupNames) == 0 ) 476 return; // Nichts zu tun. 477 478 $db = db_connection(); 479 480 $groupNames = "'".implode("','",$groupNames)."'"; 481 $sql = $db->sql("SELECT id FROM {{group}} WHERE name IN($groupNames)"); 482 $groupIds = array_unique( $sql->getCol() ); 483 484 // Wir brauchen hier nicht weiter pr�fen, ob der Benutzer eine Gruppe schon hat, denn 485 // - passiert dies nur bei der Neuanlage eines Benutzers 486 // - Enth�lt die Group-Id-Liste eine ID nur 1x. 487 488 // Gruppen diesem Benutzer zuordnen. 489 foreach( $groupIds as $groupId ) 490 $this->addGroup( $groupId ); 491 } 492 493 494 /** 495 * Benutzer entfernen.<br> 496 * Vor dem Entfernen werden alle Referenzen auf diesen Benutzer entfernt:<br> 497 * - "Erzeugt von" f�r diesen Benutzer entfernen.<br> 498 * - "Letzte �nderung von" f�r diesen Benutzer entfernen<br> 499 * - Alle Archivdaten in Dateien mit diesem Benutzer entfernen<br> 500 * - Alle Berechtigungen dieses Benutzers l?schen<br> 501 * - Alle Gruppenzugehoerigkeiten dieses Benutzers l?schen<br> 502 * - Benutzer loeschen<br> 503 */ 504 public function delete() 505 { 506 $db = db_connection(); 507 508 // "Erzeugt von" f�r diesen Benutzer entfernen. 509 $sql = $db->sql( 'UPDATE {{object}} '. 510 'SET create_userid=null '. 511 'WHERE create_userid={userid}' ); 512 $sql->setInt ('userid',$this->userid ); 513 $sql->query(); 514 515 // "Letzte �nderung von" f�r diesen Benutzer entfernen 516 $sql = $db->sql( 'UPDATE {{object}} '. 517 'SET lastchange_userid=null '. 518 'WHERE lastchange_userid={userid}' ); 519 $sql->setInt ('userid',$this->userid ); 520 $sql->query(); 521 522 // Alle Archivdaten in Dateien mit diesem Benutzer entfernen 523 $sql = $db->sql( 'UPDATE {{value}} '. 524 'SET lastchange_userid=null '. 525 'WHERE lastchange_userid={userid}' ); 526 $sql->setInt ('userid',$this->userid ); 527 $sql->query(); 528 529 // Alle Berechtigungen dieses Benutzers l?schen 530 $sql = $db->sql( 'DELETE FROM {{acl}} '. 531 'WHERE userid={userid}' ); 532 $sql->setInt ('userid',$this->userid ); 533 $sql->query(); 534 535 // Alle Gruppenzugehoerigkeiten dieses Benutzers l?schen 536 $sql = $db->sql( 'DELETE FROM {{usergroup}} '. 537 'WHERE userid={userid}' ); 538 $sql->setInt ('userid',$this->userid ); 539 $sql->query(); 540 541 $stmt = db()->sql( <<<SQL 542 DELETE FROM {{auth}} 543 WHERE userid={userid} 544 SQL 545 ); 546 $stmt->setInt ('userid',$this->userid ); 547 $stmt->execute(); 548 549 // Benutzer loeschen 550 $sql = $db->sql( 'DELETE FROM {{user}} '. 551 'WHERE id={userid}' ); 552 $sql->setInt ('userid',$this->userid ); 553 $sql->query(); 554 } 555 556 557 /** 558 * Ermitteln der Eigenschaften zu diesem Benutzer 559 * 560 * @return array Liste der Eigenschaften als assoziatives Array 561 */ 562 public function getProperties() 563 { 564 return parent::getProperties() + array('id'=>$this->userid,'is_admin'=> $this->isAdmin); 565 } 566 567 568 569 /** 570 * Setzt ein neues Kennwort fuer diesen Benutzer. 571 * 572 * @param password Kennwortt 573 * @param always true, wenn Kennwort dauerhaft. 574 */ 575 function setPassword( $password, $always=true ) 576 { 577 $db = db_connection(); 578 579 $sql = $db->sql( 'UPDATE {{user}} SET password_hash={password},password_algo={algo},password_expires={expires} '. 580 'WHERE id={userid}' ); 581 582 if ( $always ) 583 { 584 $algo = Password::bestAlgoAvailable(); 585 $expire = null; 586 } 587 else 588 { 589 // Klartext-Kennwort, der Benutzer muss das Kennwort beim nä. Login ändern. 590 $algo = Password::ALGO_PLAIN; 591 $expire = time(); 592 } 593 594 // Hashsumme für Kennwort erzeugen 595 if ( $expire == null ) 596 $sql->setNull('expires'); 597 else 598 $sql->setInt('expires',$expire); 599 600 $sql->setInt ('algo' ,$algo ); 601 $sql->setString('password',Password::hash(User::pepperPassword($password),$algo) ); 602 $sql->setInt ('userid' ,$this->userid ); 603 604 $sql->query(); 605 } 606 607 608 /** 609 * Gruppen ermitteln, in denen der Benutzer Mitglied ist. 610 * 611 * @return array mit Id:Name 612 */ 613 function getGroups() 614 { 615 if ( !is_array($this->groups) ) 616 { 617 $db = db_connection(); 618 619 $sql = $db->sql( 'SELECT {{group}}.id,{{group}}.name FROM {{group}} '. 620 'LEFT JOIN {{usergroup}} ON {{usergroup}}.groupid={{group}}.id '. 621 'WHERE {{usergroup}}.userid={userid}' ); 622 $sql->setInt('userid',$this->userid ); 623 $this->groups = $sql->getAssoc(); 624 } 625 626 return $this->groups; 627 } 628 629 630 // Gruppen ermitteln, in denen der Benutzer Mitglied ist 631 function getGroupIds() 632 { 633 return array_keys( $this->getGroups() ); 634 635 /* 636 $db = db_connection(); 637 638 $sql = $db->sql( 'SELECT groupid FROM {{usergroup}} '. 639 'WHERE userid={userid}' ); 640 $sql->setInt('userid',$this->userid ); 641 642 return $sql->getCol( $sql ); 643 */ 644 } 645 646 647 // Gruppen ermitteln, in denen der Benutzer *nicht* Mitglied ist 648 function getOtherGroups() 649 { 650 $db = db_connection(); 651 652 $sql = $db->sql( 'SELECT {{group}}.id,{{group}}.name FROM {{group}}'. 653 ' LEFT JOIN {{usergroup}} ON {{usergroup}}.groupid={{group}}.id AND {{usergroup}}.userid={userid}'. 654 ' WHERE {{usergroup}}.userid IS NULL' ); 655 $sql->setInt('userid' ,$this->userid ); 656 657 return $sql->getAssoc(); 658 } 659 660 661 662 /** 663 * Benutzer zu einer Gruppe hinzufuegen. 664 * 665 * @param groupid die Gruppen-Id 666 */ 667 function addGroup( $groupid ) 668 { 669 $db = db_connection(); 670 671 $sql = $db->sql('SELECT MAX(id) FROM {{usergroup}}'); 672 $usergroupid = intval($sql->getOne())+1; 673 674 $sql = $db->sql( 'INSERT INTO {{usergroup}} '. 675 ' (id,userid,groupid) '. 676 ' VALUES( {usergroupid},{userid},{groupid} )' ); 677 $sql->setInt('usergroupid',$usergroupid ); 678 $sql->setInt('userid' ,$this->userid ); 679 $sql->setInt('groupid' ,$groupid ); 680 681 $sql->query(); 682 683 } 684 685 686 687 /** 688 * Benutzer aus Gruppe entfernen. 689 * 690 * @param groupid die Gruppen-Id 691 */ 692 function delGroup( $groupid ) 693 { 694 $db = db_connection(); 695 696 $sql = $db->sql( 'DELETE FROM {{usergroup}} '. 697 ' WHERE userid={userid} AND groupid={groupid}' ); 698 $sql->setInt ('userid' ,$this->userid ); 699 $sql->setInt ('groupid' ,$groupid ); 700 701 $sql->query(); 702 } 703 704 705 /** 706 * Ermitteln aller Rechte des Benutzers im aktuellen Projekt. 707 * 708 * @param Integer $projectid Projekt-Id 709 * @param Integer $languageid Sprache-Id 710 */ 711 function loadRights( $projectid,$languageid ) 712 { 713 } 714 715 716 /** 717 * Ermitteln aller Berechtigungen des Benutzers.<br> 718 * Diese Daten werden auf der Benutzerseite in der Administration angezeigt. 719 * 720 * @return array 721 */ 722 function getAllAcls() 723 { 724 725 $this->delRights(); 726 727 $group_clause = $this->getGroupClause(); 728 729 $sql = db()->sql( 'SELECT {{acl}}.*,{{object}}.projectid,{{language}}.name AS languagename FROM {{acl}}'. 730 ' LEFT JOIN {{object}} '. 731 ' ON {{object}}.id={{acl}}.objectid '. 732 ' LEFT JOIN {{language}} '. 733 ' ON {{language}}.id={{acl}}.languageid '. 734 ' WHERE ( {{acl}}.userid={userid} OR '.$group_clause. 735 ' OR ({{acl}}.userid IS NULL AND {{acl}}.groupid IS NULL) )'. 736 ' ORDER BY {{object}}.projectid,{{acl}}.languageid' ); 737 $sql->setInt ( 'userid' ,$this->userid ); 738 739 $aclList = array(); 740 741 foreach($sql->getAll() as $row ) 742 { 743 $acl = new Acl(); 744 $acl->setDatabaseRow( $row ); 745 $acl->projectid = $row['projectid' ]; 746 if ( intval($acl->languageid) == 0 ) 747 $acl->languagename = lang('GLOBAL_ALL_LANGUAGES'); 748 else 749 $acl->languagename = $row['languagename']; 750 $aclList[] = $acl; 751 } 752 753 return $aclList; 754 } 755 756 757 /** 758 * Ermitteln aller Berechtigungen. 759 * @return array Berechtigungen 760 */ 761 function getRights() 762 { 763 throw new \DomainException('User.class::getRights()'); 764 765 // $db = db_connection(); 766 // $var = array(); 767 // 768 // // Alle Projekte lesen 769 // $sql = $db->sql( 'SELECT id,name FROM {{project}}' ); 770 // $projects = $sql->getAssoc( $sql ); 771 // 772 // foreach( $projects as $projectid=>$projectname ) 773 // { 774 // $var[$projectid] = array(); 775 // $var[$projectid]['name'] = $projectname; 776 // $var[$projectid]['folders'] = array(); 777 // $var[$projectid]['rights'] = array(); 778 // 779 // $sql = $db->sql( 'SELECT {{acl}}.* FROM {{acl}}'. 780 // ' LEFT JOIN {{folder}} ON {{acl}}.folderid = {{folder}}.id'. 781 // ' WHERE {{folder}}.projectid={projectid}'. 782 // ' AND {{acl}}.userid={userid}' ); 783 // $sql->setInt('projectid',$projectid ); 784 // $sql->setInt('userid' ,$this->userid ); 785 // 786 // $acls = $sql->getAll( $sql ); 787 // 788 // foreach( $acls as $acl ) 789 // { 790 // $aclid = $acl['id']; 791 // $folder = new Folder( $acl['folderid'] ); 792 // $folder->load(); 793 // $var[$projectid]['rights'][$aclid] = $acl; 794 // $var[$projectid]['rights'][$aclid]['foldername'] = implode(' » ',$folder->parentfolder( false,true )); 795 // $var[$projectid]['rights'][$aclid]['delete_url'] = Html::url(array('action'=>'user','subaction'=>'delright','aclid'=>$aclid)); 796 // } 797 // 798 // $sql = $db->sql( 'SELECT id FROM {{folder}}'. 799 // ' WHERE projectid={projectid}' ); 800 // $sql->setInt('projectid',$projectid); 801 // $folders = $sql->getCol( $sql ); 802 // 803 // $var[$projectid]['folders'] = array(); 804 // 805 // foreach( $folders as $folderid ) 806 // { 807 // $folder = new Folder( $folderid ); 808 // $folder->load(); 809 // $var[$projectid]['folders'][$folderid] = implode(' » ',$folder->parentfolder( false,true )); 810 // } 811 // 812 // asort( $var[$projectid]['folders'] ); 813 // } 814 // 815 // return $var; 816 } 817 818 819 /** 820 * Entfernt alle Rechte aus diesem Benutzerobjekt. 821 */ 822 function delRights() 823 { 824 $this->rights = array(); 825 } 826 827 828 /** 829 * Ueberpruft, ob der Benutzer ein bestimmtes Recht hat 830 * 831 * @param $objectid Objekt-Id zu dem Objekt, dessen Rechte untersucht werden sollen 832 * @param $type Typ des Rechts (Lesen,Schreiben,...) als Konstante Acl::ACL_* 833 */ 834 function hasRight( $objectid,$type ) 835 { 836 global $conf; 837 if ( $this->isAdmin && !$conf['security']['readonly'] ) 838 return true; 839 840 if ( $this->isAdmin && $type & Acl::ACL_READ ) 841 return true; 842 843 if ( !isset($this->rights[$objectid]) ) 844 return false; 845 846 return $this->rights[$objectid] & $type; 847 } 848 849 850 /** 851 * Berechtigung dem Benutzer hinzufuegen. 852 * 853 * @param objectid Objekt-Id, zu dem eine Berechtigung hinzugefuegt werden soll 854 * @param Art des Rechtes, welches hinzugefuegt werden soll 855 */ 856 function addRight( $objectid,$type ) 857 { 858 global $conf; 859 860 if ( $conf['security']['readonly'] ) 861 if ( $type & Acl::ACL_READ ) 862 $type = Acl::ACL_READ; 863 else 864 $type = 0; 865 866 if ( $type & Acl::ACL_PUBLISH && $conf['security']['nopublish'] ) 867 $type -= Acl::ACL_PUBLISH; 868 869 870 if ( !isset($this->rights[$objectid]) ) 871 $this->rights[$objectid] = 0; 872 873 $this->rights[$objectid] = $this->rights[$objectid] | $type; 874 } 875 876 877 /** 878 * Ermitteln aller zur Verfuegung stehenden Stylesheets 879 */ 880 public function getAvailableStyles() 881 { 882 global $conf; 883 $styles = array(); 884 885 foreach( $conf['style'] as $key=>$values) 886 $styles[$key] = $values['name']; 887 888 return $styles; 889 } 890 891 /** 892 * Ueberpruefen des Kennwortes. 893 * 894 * Es wird festgestellt, ob das Kennwort dem des Benutzers entspricht. 895 * Es wird dabei nur gegen die interne Datenbank geprüft. Weitere 896 * Loginmodule werden nicht aufgerufen! 897 * Diese Methode darf kein Bestandteil des Logins sein, da nur das Kennwort geprüft wird! 898 * Kennwortablauf und Token werden nicht geprüft! 899 */ 900 function checkPassword( $password ) 901 { 902 $db = db_connection(); 903 // Laden des Benutzers aus der Datenbank, um Password-Hash zu ermitteln. 904 $sql = $db->sql( 'SELECT * FROM {{user}}'. 905 ' WHERE id={userid}' ); 906 $sql->setInt( 'userid',$this->userid ); 907 $row_user = $sql->getRow(); 908 909 // Pruefen ob Kennwort mit Datenbank uebereinstimmt. 910 return Password::check(User::pepperPassword($password),$row_user['password_hash'],$row_user['password_algo']); 911 } 912 913 914 /** 915 * Erzeugt ein aussprechbares Kennwort. 916 * 917 * Inspired by http://www.phpbuilder.com/annotate/message.php3?id=1014451 918 * 919 * @return String Zuf�lliges Kennwort 920 */ 921 function createPassword() 922 { 923 global $conf; 924 925 $pw = ''; 926 $c = 'bcdfghjklmnprstvwz'; //consonants except hard to speak ones 927 $v = 'aeiou'; //vowels 928 $a = $c.$v; //both 929 930 //use two syllables... 931 for ( $i=0; $i < intval($conf['security']['password']['min_length'])/3; $i++ ) 932 { 933 $pw .= $c[rand(0, strlen($c)-1)]; 934 $pw .= $v[rand(0, strlen($v)-1)]; 935 $pw .= $a[rand(0, strlen($a)-1)]; 936 } 937 //... and add a nice number 938 $pw .= rand(10,99); 939 940 return $pw; 941 } 942 943 944 /** 945 * Das Kennwort "pfeffern". 946 * 947 * Siehe http://de.wikipedia.org/wiki/Salt_%28Kryptologie%29#Pfeffer 948 * für weitere Informationen. 949 * 950 * @param Kennwort 951 * @return Das gepfefferte Kennwort 952 */ 953 public static function pepperPassword( $pass ) 954 { 955 $salt = Conf()->subset('security')->subset('password')->get('pepper'); 956 957 return $salt.$pass; 958 } 959 960 961 /** 962 * Ermittelt projektübergreifend die letzten Änderungen des Benutzers. 963 * 964 * @return array <string, unknown> 965 */ 966 public function getLastChanges() 967 { 968 $db = db_connection(); 969 970 $sql = $db->sql( <<<SQL 971 SELECT {{object}}.id as objectid, 972 {{object}}.filename as filename, 973 {{object}}.typeid as typeid, 974 {{object}}.lastchange_date as lastchange_date, 975 {{project}}.id as projectid, 976 {{project}}.name as projectname 977 FROM {{object}} 978 LEFT JOIN {{project}} 979 ON {{object}}.projectid = {{project}}.id 980 WHERE {{object}}.lastchange_userid = {userid} 981 ORDER BY {{object}}.lastchange_date DESC 982 SQL 983 ); 984 985 $sql->setInt( 'userid', $this->userid ); 986 987 return $sql->getAll(); 988 989 } 990 991 992 /** 993 * Calculate the code, with given secret and point in time. 994 * 995 * @param string $secret 996 * @param int|null $timeSlice 997 * 998 * @return string 999 */ 1000 public function getTOTPCode() 1001 { 1002 $codeLength = 6; 1003 $timeSlice = floor(time() / 30); 1004 $secretkey = @hex2bin($this->otpSecret); 1005 // Pack time into binary string 1006 $time = chr(0).chr(0).chr(0).chr(0).pack('N*', $timeSlice); 1007 // Hash it with users secret key 1008 $hm = hash_hmac('SHA1', $time, $secretkey, true); 1009 // Use last nipple of result as index/offset 1010 $offset = ord(substr($hm, -1)) & 0x0F; 1011 // grab 4 bytes of the result 1012 $hashpart = substr($hm, $offset, 4); 1013 // Unpak binary value 1014 $value = unpack('N', $hashpart); 1015 $value = $value[1]; 1016 // Only 32 bits 1017 $value = $value & 0x7FFFFFFF; 1018 $modulo = pow(10, $codeLength); 1019 return str_pad($value % $modulo, $codeLength, '0', STR_PAD_LEFT); 1020 } 1021 1022 1023 /** 1024 * Erzeugt ein neues OTP-Secret. 1025 */ 1026 public function renewOTPSecret() { 1027 1028 $secret = Password::randomHexString(64); 1029 1030 $db = db_connection(); 1031 1032 $stmt = $db->sql('UPDATE {{user}} SET otp_secret={secret} WHERE id={id}'); 1033 1034 $stmt->setString( 'secret', $secret ); 1035 $stmt->setInt ( 'id' , $this->userid ); 1036 1037 $stmt->execute(); 1038 1039 } 1040 1041 } 1042