openrat-cms

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

LoginLoginAction.class.php (8174B)


      1 <?php
      2 namespace cms\action\login;
      3 use cms\action\Action;
      4 use cms\action\LoginAction;
      5 use cms\action\Method;
      6 use cms\action\RequestParams;
      7 use cms\auth\Auth;
      8 use cms\auth\AuthRunner;
      9 use cms\base\Configuration;
     10 use cms\base\DB;
     11 use cms\base\Startup;
     12 use cms\model\User;
     13 use language\Language;
     14 use language\Messages;
     15 use logger\Logger;
     16 use security\Password;
     17 use util\Browser;
     18 use util\exception\ObjectNotFoundException;
     19 use util\exception\SecurityException;
     20 use util\exception\ValidationException;
     21 use util\mail\Mail;
     22 use util\Request;
     23 use util\Session;
     24 use util\text\TextMessage;
     25 
     26 
     27 class LoginLoginAction extends LoginAction implements Method {
     28     public function view() {
     29         $loginConfig    = Configuration::subset('security');
     30         $securityConfig = Configuration::subset('security');
     31         $authenticateConfig  = Configuration::subset('authenticate');
     32 
     33         $authenticateEnabled = $authenticateConfig->is('enable',true);
     34 		$oidcList = [];
     35 
     36         $oidcConfig = Configuration::subset(['security','oidc']);
     37 
     38         if   ( $oidcConfig->is('enabled',true) ) {
     39         	foreach ( $oidcConfig->subset('provider')->subsets() as $name=>$providerConfig ) {
     40         		if   ( $providerConfig->is('enabled',true)) {
     41         			$oidcList[ $name ] = $providerConfig->get('label',$name );
     42 				}
     43 			}
     44 		}
     45 
     46         $this->setTemplateVar('enableUserPasswordLogin',$authenticateEnabled);
     47         $this->setTemplateVar('enableOpenIdConnect'    ,(boolean)$oidcList  );
     48         $this->setTemplateVar('provider'               ,$oidcList           );
     49 
     50 		$dbids = $this->getSelectableDatabases();
     51 
     52         if	( ! $dbids )
     53             $this->addWarningFor( null,Messages::NO_DATABASE_CONFIGURATION );
     54 
     55         $this->setTemplateVar( 'dbids',$dbids );
     56 
     57         // Database was already connected in the Dispatcher. So we MUST have a db connection here.
     58         $dbId = Request::getDatabaseId();
     59         $this->setTemplateVar('dbid',$dbId);
     60 
     61         $this->setTemplateVar('register'     ,$loginConfig->get('register' ));
     62         $this->setTemplateVar('send_password',$loginConfig->get('send_password'));
     63 
     64         // Versuchen, einen Benutzernamen zu ermitteln, der im Eingabeformular vorausgewählt wird.
     65         $username = AuthRunner::getUsername('preselect');
     66 
     67         $this->setTemplateVar('login_name',$username);
     68 
     69         // If the preselected user is the default user, we have a password.
     70 		if   ( $username == $securityConfig->subset('default')->get('username') )
     71 			$this->setTemplateVar('login_password',  $securityConfig->subset('default')->get('password') );
     72     }
     73 
     74 
     75     public function post() {
     76 
     77 		Request::setUser(null); // Altes Login entfernen.
     78 		
     79 		if	( Configuration::subset('login')->is('nologin',false ) )
     80 			throw new SecurityException('login disabled');
     81 
     82 		$loginName     = $this->request->getAlphanum('login_name' );
     83 		$loginPassword = $this->request->getText('login_password');
     84 		$newPassword1  = $this->request->getText('password1'     );
     85 		$newPassword2  = $this->request->getText('password2'     );
     86 		$token         = $this->request->getText('user_token'    );
     87 
     88 
     89 		// Jedes Authentifizierungsmodul durchlaufen, bis ein Login erfolgreich ist.
     90 		$authResult = AuthRunner::checkLogin('authenticate',$loginName,$loginPassword, $token );
     91 		Password::delay();
     92 
     93 		if  ( $authResult & Auth::STATUS_PW_EXPIRED ) {
     94 
     95 			// Der Benutzer hat zwar ein richtiges Kennwort eingegeben, aber dieses ist abgelaufen.
     96 			// Wir versuchen hier, das neue zu setzen (sofern eingegeben).
     97 			if	( $newPassword1 )
     98 			{
     99 				$passwordConfig = Configuration::subset(['security','password']);
    100 
    101 				if	( $newPassword1 != $newPassword2 )
    102 					throw new ValidationException('password2',Messages::PASSWORDS_DO_NOT_MATCH);
    103 				elseif	( strlen($newPassword1) < $passwordConfig->get('min_length',10) )
    104 					throw new ValidationException('password1',Messages::PASSWORD_MINLENGTH,array('minlength'=>$passwordConfig->get('min_length',10)));
    105 				else
    106 				{
    107 					// Kennwoerter identisch und lang genug.
    108 					$user = User::loadWithName($loginName,User::AUTH_TYPE_INTERNAL);
    109 					$user->setPassword( $newPassword1,true );
    110 					$loginPassword = $newPassword1;
    111 
    112 					$authResult -= Auth::STATUS_PW_EXPIRED;
    113 				}
    114 			}
    115 		}
    116 
    117 		if	( $authResult & Auth::STATUS_TOKEN_NEEDED )
    118 			// Token falsch.
    119 			throw new ValidationException('user_token',Messages::LOGIN_FAILED_TOKEN_FAILED );
    120 
    121 		if	( $authResult & Auth::STATUS_PW_EXPIRED ) {
    122 
    123 			if   ( $authResult & Auth::STATUS_FAILED )
    124 				// Anmeldung gescheitert, Benutzer muss Kennwort ?ndern.
    125 				throw new ValidationException('password1',Messages::LOGIN_FAILED_MUSTCHANGEPASSWORD);
    126 		}
    127 
    128 		$ip = getenv("REMOTE_ADDR");
    129 
    130 		if	( $authResult & Auth::STATUS_FAILED ) {
    131 			Logger::debug(TextMessage::create('login failed for user ${name} from IP ${ip}',
    132 				[
    133 					'name' => $loginName,
    134 					'ip' => $ip
    135 				]
    136 			));
    137 
    138 			// Login failed.
    139 			throw new ValidationException('login_password',Messages::LOGIN_FAILED, ['name' => $loginName] );
    140 		}
    141 
    142 		if ( $authResult & Auth::STATUS_SUCCESS ) {
    143 
    144 			Logger::info(TextMessage::create('Login successful for user ${0}', [$loginName]));
    145 
    146 			$browser = new Browser();
    147 			Logger::debug(TextMessage::create('Login successful for user ${0} from IP ${1} with ${2} (${3})',[$loginName,$ip,$browser->name,$browser->platform]));
    148 
    149 			try {
    150 				// Benutzer über den Benutzernamen laden.
    151 				$user = User::loadWithName($loginName, User::AUTH_TYPE_INTERNAL, null);
    152 				$user->setCurrent();
    153 				$user->updateLoginTimestamp();
    154 
    155 				if ($user->passwordAlgo != Password::bestAlgoAvailable())
    156 					// Re-Hash the password with a better hash algo.
    157 					$user->setPassword($loginPassword);
    158 
    159 			} catch (ObjectNotFoundException $ex) {
    160 				// Benutzer wurde zwar authentifiziert, ist aber in der
    161 				// internen Datenbank nicht vorhanden
    162 				if (Configuration::subset(['security', 'newuser'])->is('autoadd', true)) {
    163 
    164 					if   ( Startup::readonly() )
    165 						throw new \LogicException('System is readonly so this user cannot be inserted.');
    166 
    167 					// Neue Benutzer in die interne Datenbank uebernehmen.
    168 					$user = new User();
    169 					$user->name = $loginName;
    170 					$user->fullname = $loginName;
    171 					$user->persist();
    172 					Logger::debug( TextMessage::create('user ${0} authenticated successful and added to internal user table',[$loginName]) );
    173 					$user->updateLoginTimestamp();
    174 				} else {
    175 					// Benutzer soll nicht angelegt werden.
    176 					// Daher ist die Anmeldung hier gescheitert.
    177 					// Anmeldung gescheitert.
    178 					Logger::warn( TextMessage::create('user ${0} authenticated successful, but not found in internal user table',[$loginName]) );
    179 
    180 					throw new ValidationException('login_password',Messages::LOGIN_FAILED,['name' => $loginName ]);
    181 				}
    182 			}
    183 
    184 			// Cookie setzen
    185 			$this->setCookie(Action::COOKIE_DB_ID   ,DB::get()->id );
    186 			$this->setCookie(Action::COOKIE_USERNAME,$user->name   );
    187 
    188 			if	( $this->request->isTrue('remember') ) {
    189 				// Sets the login token cookie
    190 				$this->setCookie(Action::COOKIE_TOKEN   ,$user->createNewLoginToken() );
    191 			}
    192 
    193 			// Anmeldung erfolgreich.
    194 			if	( Configuration::subset('security')->is('renew_session_login',false) )
    195 				$this->recreateSession();
    196 
    197 			// Send mail to user to inform about the new login.
    198 			if   ( $user->mail && Configuration::subset('security')->is('inform_user_about_new_login',true) ) {
    199 				$mail = new Mail( $user->mail, Messages::MAIL_NEW_LOGIN_SUBJECT, Messages::MAIL_NEW_LOGIN_TEXT );
    200 				$browser = new \util\Browser();
    201 				$mail->setVar( 'platform',$browser->platform );
    202 				$mail->setVar( 'browser' ,$browser->name     );
    203 				$mail->setVar( 'username',$user->name        );
    204 				$mail->setVar( 'name'    ,$user->getName()   );
    205 				$mail->send();
    206 			}
    207 
    208 			$this->addNoticeFor( $user,Messages::LOGIN_OK, array('name' => $user->getName() ));
    209 
    210 			// Setting the user-defined language
    211 			$config = Request::getConfig();
    212 			$language = new Language();
    213 			$config['language'] = $language->getLanguage($user->language);
    214 			$config['language']['language_code'] = $user->language;
    215 
    216 			Request::setConfig( $config );
    217 
    218 			return; // everything ok, user logged in.
    219 		}
    220 
    221 		throw new \LogicException('Auth module must return either SUCCESS or FAIL, but got '.$authResult);
    222 	}
    223 }