Passed
Push — master ( 0ed261...e52b37 )
by Jean-Christophe
17:09
created

AuthController::finalize()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 4

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 6
c 1
b 0
f 1
dl 0
loc 8
ccs 7
cts 7
cp 1
rs 10
cc 4
nc 5
nop 0
crap 4
1
<?php
2
3
namespace Ubiquity\controllers\auth;
4
5
use Ubiquity\utils\http\USession;
6
use Ubiquity\utils\http\URequest;
7
use Ubiquity\utils\flash\FlashMessage;
8
use Ubiquity\controllers\Controller;
9
use Ubiquity\utils\http\UResponse;
10
use Ubiquity\utils\base\UString;
11
use Ubiquity\controllers\Startup;
12
use Ajax\service\Javascript;
13
use Ubiquity\utils\http\UCookie;
14
use Ubiquity\controllers\semantic\InsertJqueryTrait;
15
use Ajax\semantic\html\collections\form\HtmlForm;
16
use Ajax\semantic\components\validation\Rule;
17
use Ajax\php\ubiquity\JsUtils;
18
use Ubiquity\cache\CacheManager;
19
20
/**
21
 * Controller Auth
22
 *
23
 * @property \Ajax\php\ubiquity\JsUtils $jquery
24
 */
25
abstract class AuthController extends Controller {
26
	use AuthControllerCoreTrait,AuthControllerVariablesTrait,AuthControllerOverrideTrait,InsertJqueryTrait,AuthControllerValidationTrait;
27
28
	/**
29
	 *
30
	 * @var AuthFiles
31
	 */
32
	protected $authFiles;
33
	protected $_controller;
34
	protected $_action;
35
	protected $_actionParams;
36
	protected $_noAccessMsg;
37
	protected $_loginCaption;
38
	protected $_attemptsSessionKey = "_attempts";
39
	protected $_controllerInstance;
40
	protected $_compileJS = true;
41
	protected $_invalid=false;
42
43 1
	public function __construct($instance = null) {
44 1
		parent::__construct ();
45 1
		$this->_insertJquerySemantic ();
46 1
		$this->_controller = Startup::getController ();
47 1
		$this->_action = Startup::getAction ();
48 1
		$this->_actionParams = Startup::getActionParams ();
49 1
		$this->_noAccessMsg = new FlashMessage ( 'You are not authorized to access the page <b>{url}</b> !', "Forbidden access", 'error', 'warning circle' );
50 1
		$this->_loginCaption = 'Log in';
51 1
		$this->_controllerInstance = $instance;
52 1
		if (isset ( $instance ))
53
			Startup::injectDependences ( $instance );
54 1
	}
55
56 1
	public function index() {
57 1
		if (($nbAttempsMax = $this->attemptsNumber ()) !== null) {
58
			$nb = USession::getTmp ( $this->_attemptsSessionKey, $nbAttempsMax );
59
			if ($nb <= 0) {
60
				$this->badLogin ();
61
				return;
62
			}
63
		}
64 1
		if($this->useAjax()){
65 1
			$this->_addFrmAjaxBehavior('frm-login');
66
		}
67 1
		$vData=[ "action" => $this->getBaseUrl () . 'connect','loginInputName' => $this->_getLoginInputName (),'loginLabel' => $this->loginLabel (),'passwordInputName' => $this->_getPasswordInputName (),'passwordLabel' => $this->passwordLabel (),'rememberCaption' => $this->rememberCaption () ];
68 1
		$this->addAccountCreationViewData($vData,true);
69 1
		$this->authLoadView ( $this->_getFiles ()->getViewIndex (), $vData );
70 1
	}
71
	
72
	public function addAccount(){
73
		if($this->hasAccountCreation()){
74
			if($this->useAjax()){
75
				$frm=$this->_addFrmAjaxBehavior('frm-create');
76
				$passwordInputName=$this->_getPasswordInputName();
77
				$frm->addExtraFieldRules($passwordInputName.'-conf', ['empty',"match[$passwordInputName]"]);
78
				if($this->newAccountCreationRule('')!==null){
79
					$this->jquery->exec(Rule::ajax($this->jquery, 'checkAccount', $this->getBaseUrl () . '/_newAccountCreationRule', '{}', 'result=data.result;', 'postForm', [
80
									'form' => 'frm-create'
81
							]), true);
82
					$frm->addExtraFieldRule($this->_getLoginInputName(), 'checkAccount','Account {value} is not available!');
83
				}
84
			}
85
			$this->authLoadView ( $this->_getFiles ()->getViewCreate(), [ 'action' => $this->getBaseUrl () . '/createAccount','loginInputName' => $this->_getLoginInputName (),'loginLabel' => $this->loginLabel (),'passwordInputName' => $this->_getPasswordInputName (),'passwordLabel' => $this->passwordLabel (),'passwordConfLabel'=>$this->passwordConfLabel(),'rememberCaption' => $this->rememberCaption () ] );
86
		}
87
	}
88
	
89
90
	public function createAccount(){
91
		$account=URequest::post($this->_getLoginInputName());
92
		$msgSup='';
93
		if($this->_create($account,URequest::post($this->_getPasswordInputName()))){
94
			if($this->hasEmailValidation()){
95
				$email=$this->getEmailFromNewAccount($account);
96
				$this->prepareEmailValidation($email);
97
				$msgSup='<br>Confirm your email address by checking at <b>$email</b>.';
98
			}
99
			$msg=new FlashMessage ( '<b>{account}</b> account created with success!'.$msgSup, 'Account creation', 'success', 'check square' );
100
		}else{
101
			$msg=new FlashMessage ( 'The account <b>{account}</b> was not created!', 'Account creation', 'error', 'warning circle' );
102
		}
103
		$message=$this->fMessage($msg->parseContent(['account'=>$account]));
104
		$this->authLoadView ( $this->_getFiles ()->getViewNoAccess (), [ '_message' => $message,'authURL' => $this->getBaseUrl (),'bodySelector' => $this->_getBodySelector (),'_loginCaption' => $this->_loginCaption ] );
105
	}
106
107
	/**
108
	 *
109
	 * {@inheritdoc}
110
	 * @see \Ubiquity\controllers\Controller::isValid()
111
	 */
112 1
	public final function isValid($action) {
113 1
		return true;
114
	}
115
116
	/**
117
	 * Action called when the user does not have access rights to a requested resource
118
	 *
119
	 * @param array|string $urlParts
120
	 */
121 1
	public function noAccess($urlParts) {
122 1
		if (! \is_array ( $urlParts )) {
123
			$urlParts = \explode ( '.', $urlParts );
124
		}
125 1
		USession::set ( 'urlParts', $urlParts );
126 1
		$fMessage = $this->_noAccessMsg;
127 1
		$this->noAccessMessage ( $fMessage );
128 1
		$message = $this->fMessage ( $fMessage->parseContent ( [ 'url' => \implode ( '/', $urlParts ) ] ) );
129
		
130 1
		if (URequest::isAjax ()) {
131
			$this->jquery->get ( $this->_getBaseRoute () . '/info/f', '#_userInfo', [ 'historize' => false,'jqueryDone' => 'replaceWith','hasLoader' => false,'attr' => '' ] );
132
			$this->jquery->compile ( $this->view );
133
		}
134
		
135 1
		$vData=[ '_message' => $message,'authURL' => $this->getBaseUrl (),'bodySelector' => $this->_getBodySelector (),'_loginCaption' => $this->_loginCaption ];
136 1
		$this->addAccountCreationViewData($vData);
137 1
		$this->authLoadView ( $this->_getFiles ()->getViewNoAccess (), $vData);
138 1
	}
139
140
	/**
141
	 * Override to implement the complete connection procedure
142
	 */
143 1
	public function connect() {
144 1
		if (URequest::isPost ()) {
145 1
			if ($connected = $this->_connect ()) {
146 1
				if (isset ( $_POST ['ck-remember'] )) {
147
					$this->rememberMe ( $connected );
148
				}
149 1
				if (USession::exists ( $this->_attemptsSessionKey )) {
150
					USession::delete ( $this->_attemptsSessionKey );
151
				}
152 1
				if($this->has2FA($connected)){
153
					$this->initializeAuth();
154
					USession::set($this->_getUserSessionKey().'-2FA', $connected);
155
					$this->send2FACode();
156
					$this->confirm();
157
					$this->finalizeAuth();
158
				}else{
159 1
					$this->onConnect ( $connected );
160
				}
161
			} else {
162 1
				$this->_invalid=true;
163 1
				$this->initializeAuth();
164 1
				$this->onBadCreditentials ();
165 1
				$this->finalizeAuth();
166
			}
167
		}
168 1
	}
169
170
	/**
171
	 * Default Action for invalid creditentials
172
	 */
173 1
	public function badLogin() {
174 1
		$fMessage = new FlashMessage ( 'Invalid creditentials!', 'Connection problem', 'warning', 'warning circle' );
175 1
		$this->badLoginMessage ( $fMessage );
176 1
		$attemptsMessage = "";
177 1
		if (($nbAttempsMax = $this->attemptsNumber ()) !== null) {
178
			$nb = USession::getTmp ( $this->_attemptsSessionKey, $nbAttempsMax );
179
			$nb --;
180
			if ($nb < 0) {
181
				$nb = 0;
182
			}
183
			if ($nb == 0) {
184
				$fAttemptsNumberMessage = $this->noAttempts ();
185
			} else {
186
				$fAttemptsNumberMessage = new FlashMessage ( '<i class="ui warning icon"></i> You still have {_attemptsCount} attempts to log in.', null, 'bottom attached warning', '' );
187
			}
188
			USession::setTmp ( $this->_attemptsSessionKey, $nb, $this->attemptsTimeout () );
189
			$this->attemptsNumberMessage ( $fAttemptsNumberMessage, $nb );
190
			$fAttemptsNumberMessage->parseContent ( [ '_attemptsCount' => $nb,'_timer' => '<span id="timer"></span>' ] );
191
			$attemptsMessage = $this->fMessage ( $fAttemptsNumberMessage, 'timeout-message' );
192
			$fMessage->addType ( "attached" );
193
		}
194 1
		$message = $this->fMessage ( $fMessage, 'bad-login' ) . $attemptsMessage;
195 1
		$this->authLoadView ( $this->_getFiles ()->getViewNoAccess (), [ '_message' => $message,'authURL' => $this->getBaseUrl (),'bodySelector' => $this->_getBodySelector (),'_loginCaption' => $this->_loginCaption ] );
196 1
	}
197
	
198
	/**
199
	 * Logout action
200
	 * Terminate the session and display a logout message
201
	 */
202 1
	public function terminate() {
203 1
		USession::terminate ();
204 1
		$fMessage = new FlashMessage ( 'You have been properly disconnected!', 'Logout', 'success', 'checkmark' );
205 1
		$this->terminateMessage ( $fMessage );
206 1
		$message = $this->fMessage ( $fMessage );
207 1
		$this->authLoadView ( $this->_getFiles ()->getViewNoAccess (), [ '_message' => $message,'authURL' => $this->getBaseUrl (),'bodySelector' => $this->_getBodySelector (),'_loginCaption' => $this->_loginCaption ] );
208 1
	}
209
210
	public function _disConnected() {
211
		$fMessage = new FlashMessage ( 'You have been disconnected from the application!', 'Logout', '', 'sign out' );
212
		$this->disconnectedMessage ( $fMessage );
213
		$message = $this->fMessage ( $fMessage );
214
		$this->jquery->getOnClick ( '._signin', $this->getBaseUrl (), $this->_getBodySelector (), [ 'stopPropagation' => false,'preventDefault' => false ] );
215
		$this->jquery->execOn ( 'click', '._close', "window.open(window.location,'_self').close();" );
216
		return $this->jquery->renderView ( $this->_getFiles ()->getViewDisconnected (), [ "_title" => 'Session ended','_message' => $message ], true );
217
	}
218
219
	/**
220
	 * Action displaying the logged user information
221
	 * if _displayInfoAsString returns true, use _infoUser var in views to display user info
222
	 *
223
	 * @param null|boolean $force
224
	 * @return string|null
225
	 * @throws \Exception
226
	 */
227 1
	public function info($force = null) {
228 1
		if (isset ( $force )) {
229
			$displayInfoAsString = ($force === true) ? true : false;
230
		} else {
231 1
			$displayInfoAsString = $this->_displayInfoAsString ();
232
		}
233 1
		return $this->loadView ( $this->_getFiles ()->getViewInfo (), [ 'connected' => USession::get ( $this->_getUserSessionKey () ),'authURL' => $this->getBaseUrl (),'bodySelector' => $this->_getBodySelector () ], $displayInfoAsString );
234
	}
235
	
236
	public function checkConnection() {
237
		UResponse::asJSON ();
238
		echo "{\"valid\":" . UString::getBooleanStr ( $this->_isValidUser () ) . "}";
239
	}
240
241
	/**
242
	 * Sets the default noAccess message
243
	 * Default : "You are not authorized to access the page <b>{url}</b> !"
244
	 *
245
	 * @param string $content
246
	 * @param string $title
247
	 * @param string $type
248
	 * @param string $icon
249
	 */
250
	public function _setNoAccessMsg($content, $title = NULL, $type = NULL, $icon = null) {
251
		$this->_noAccessMsg->setValues ( $content, $title, $type, $icon );
252
	}
253
254
	/**
255
	 *
256
	 * @param string $_loginCaption
257
	 */
258
	public function _setLoginCaption($_loginCaption) {
259
		$this->_loginCaption = $_loginCaption;
260
	}
261
262
	/**
263
	 * Auto connect the user
264
	 */
265 1
	public function _autoConnect() {
266 1
		$cookie = $this->getCookieUser ();
267 1
		if (isset ( $cookie )) {
268
			$user = $this->fromCookie ( $cookie );
269
			if (isset ( $user )) {
270
				USession::set ( $this->_getUserSessionKey (), $user );
271
			}
272
		}
273 1
	}
274
275
	/**
276
	 * Deletes the cookie for auto connection and returns to index
277
	 */
278
	public function forgetConnection() {
279
		UCookie::delete ( $this->_getUserSessionKey () );
280
		$this->index ();
281
	}
282
283
	/**
284
	 *
285
	 * {@inheritdoc}
286
	 * @see \Ubiquity\controllers\ControllerBase::finalize()
287
	 */
288 1
	public function finalize() {
289 1
		if (! UResponse::isJSON ()) {
290 1
			if(Startup::getAction()!=='connect') {
291 1
				$this->finalizeAuth();
292
			}
293 1
			$this->jquery->execAtLast ( "if($('#_userInfo').length){\$('#_userInfo').replaceWith(" . preg_replace ( "/$\R?^/m", "", Javascript::prep_element ( $this->info () ) ) . ");}" );
294 1
			if ($this->_compileJS) {
295 1
				echo $this->jquery->compile ();
296
			}
297
		}
298 1
	}
299
300 1
	protected function finalizeAuth() {
301 1
		if (!URequest::isAjax()) {
302 1
			$this->loadView('@activeTheme/main/vFooter.html');
303
		}
304 1
	}
305
306
	/**
307
	 *
308
	 * {@inheritdoc}
309
	 * @see \Ubiquity\controllers\ControllerBase::initialize()
310
	 */
311 1
	public function initialize() {
312 1
		if(Startup::getAction()!=='connect') {
313 1
			$this->initializeAuth();
314
		}
315 1
	}
316
317 1
	protected function initializeAuth() {
318 1
		if (!URequest::isAjax()) {
319 1
			$this->loadView('@activeTheme/main/vHeader.html');
320
		}
321 1
	}
322
323
	/**
324
	 *
325
	 * @param string $url
326
	 */
327 1
	public function _forward($url, $initialize = null, $finalize = null) {
328 1
		if (! isset ( $initialize )) {
329 1
			$initialize = (! isset ( $this->_controllerInstance ) || URequest::isAjax ());
330
		}
331 1
		if (! isset ( $finalize )) {
332 1
			$finalize = $initialize;
333
		}
334 1
		Startup::forward ( $url, $initialize, $finalize );
335 1
	}
336
	
337
	public function _addAjaxBehavior(JsUtils $jquery=null,$ajaxParameters=['hasLoader'=>'$(this).children(".button")','historize'=>false,'listenerOn'=>'body']){
338
		$jquery??=$this->jquery;
339
		$jquery->getHref('.ajax[data-target]','', $ajaxParameters);
340
		$jquery->postFormAction('.ui.form',$this->_getBodySelector(),$ajaxParameters);
341
	}
342
343 1
	public function _addFrmAjaxBehavior($id):HtmlForm{
344 1
		$frm=$this->jquery->semantic()->htmlForm($id);
345 1
		$frm->addExtraFieldRule($this->_getLoginInputName(),'empty');
346 1
		$frm->addExtraFieldRule($this->_getPasswordInputName(),'empty');
347 1
		$frm->setValidationParams(['inline'=>true,'on'=>'blur']);
348 1
		return $frm;
349
	}
350
}
351