Completed
Push — master ( 055906...b769fa )
by Jean-Christophe
01:43
created

AuthController::getBaseUrl()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
namespace Ubiquity\controllers\auth;
3
4
use Ubiquity\utils\http\USession;
5
use Ubiquity\utils\http\URequest;
6
use Ubiquity\utils\flash\FlashMessage;
7
use Ubiquity\controllers\ControllerBase;
8
use Ubiquity\controllers\Auth\AuthFiles;
9
use Ubiquity\cache\ClassUtils;
10
use Ubiquity\utils\http\UResponse;
11
use Ubiquity\utils\base\UString;
12
use Ubiquity\controllers\Startup;
13
use Ubiquity\utils\http\UCookie;
14
15
 /**
16
 * Controller Auth
17
 * @property \Ajax\php\ubiquity\JsUtils $jquery
18
 **/
19
abstract class AuthController extends ControllerBase{
20
	/**
21
	 * @var AuthFiles
22
	 */
23
	protected $authFiles;
24
	protected $_controller;
25
	protected $_action;
26
	protected $_actionParams;
27
	protected $_noAccessMsg;
28
	protected $_loginCaption;
29
	protected $_attemptsSessionKey="_attempts";
30
	
31
	public function __construct(){
32
		parent::__construct();
33
		$this->_controller=Startup::getController();
34
		$this->_action=Startup::getAction();
35
		$this->_actionParams=Startup::getActionParams();
36
		$this->_noAccessMsg=new FlashMessage("You are not authorized to access the page <b>{url}</b> !","Forbidden access","error","warning circle");
37
		$this->_loginCaption="Log in";
38
	}
39
	
40
	public function index(){
41
		if(($nbAttempsMax=$this->attemptsNumber())!==null){
42
			$nb=USession::getTmp($this->_attemptsSessionKey,$nbAttempsMax);
43
			if($nb<=0){
44
				$this->badLogin();
45
				return;
46
			}
47
		}
48
		$this->authLoadView($this->_getFiles()->getViewIndex(),["action"=>$this->getBaseUrl()."/connect",
49
				"loginInputName"=>$this->_getLoginInputName(),"loginLabel"=>$this->loginLabel(),
50
				"passwordInputName"=>$this->_getPasswordInputName(),"passwordLabel"=>$this->passwordLabel(),
51
				"rememberCaption"=>$this->rememberCaption()
52
		]);
53
	}
54
	
55
	/**
56
	 * To override
57
	 * Return the base route for this Auth controller
58
	 * @return string
59
	 */
60
	public function _getBaseRoute(){
61
		return ClassUtils::getClassSimpleName(get_class($this));
62
	}
63
	
64
	private function getBaseUrl(){
65
		return URequest::getUrl($this->_getBaseRoute());
66
	}
67
	/**
68
	 * {@inheritDoc}
69
	 * @see \controllers\ControllerBase::isValid()
70
	 */
71
	public final function isValid($action) {
72
		return true;
73
	}
74
	
75
	/**
76
	 * Action called when the user does not have access rights to a requested resource
77
	 * @param array|string $urlParts
78
	 */
79
	public function noAccess($urlParts){
80
		if(!is_array($urlParts)){
81
			$urlParts=explode(".", $urlParts);
82
		}
83
		USession::set("urlParts", $urlParts);
84
		$fMessage=$this->_noAccessMsg;
85
		$this->noAccessMessage($fMessage);
86
		$message=$this->fMessage($fMessage->parseContent(["url"=>implode("/",$urlParts)]));		
87
		$this->authLoadView($this->_getFiles()->getViewNoAccess(),["_message"=>$message,"authURL"=>$this->getBaseUrl(),"bodySelector"=>$this->_getBodySelector(),"_loginCaption"=>$this->_loginCaption]);
88
	}
89
	
90
	/**
91
	 * Override for modifying the noAccess message
92
	 * @param FlashMessage $fMessage
93
	 */
94
	protected function noAccessMessage(FlashMessage $fMessage){
95
		
96
	}
97
	
98
	/**
99
	 * Override for modifying attempts message
100
	 * You can use {_timer} and {_attemptsCount} variables in message content
101
	 * @param FlashMessage $fMessage
102
	 * @param int $attempsCount
103
	 */
104
	protected function attemptsNumberMessage(FlashMessage $fMessage,$attempsCount){
105
		
106
	}
107
	
108
	/**
109
	 * Override to implement the complete connection procedure 
110
	 */
111
	public function connect(){
112
		if(URequest::isPost()){
113
			if($connected=$this->_connect()){
114
				if(isset($_POST["ck-remember"])){
115
					$this->rememberMe($connected);
116
				}
117
				if(USession::exists($this->_attemptsSessionKey)){
118
					USession::delete($this->_attemptsSessionKey);
119
				}
120
				$this->onConnect($connected);
121
			}else{
122
				$this->onBadCreditentials();
123
			}
124
		}
125
	}
126
	
127
	/**
128
	 * Processes the data posted by the login form
129
	 * Have to return the connected user instance
130
	 */
131
	abstract protected function _connect();
132
	
133
	/**
134
	 * @param object $connected
135
	 */
136
	abstract protected function onConnect($connected);
137
	
138
	/**
139
	 * To override for defining a new action when creditentials are invalid
140
	 */
141
	protected function onBadCreditentials(){
142
		$this->badLogin();
143
	}
144
	
145
	/**
146
	 * Default Action for invalid creditentials
147
	 */
148
	public function badLogin(){
149
		$fMessage=new FlashMessage("Invalid creditentials!","Connection problem","warning","warning circle");
150
		$this->badLoginMessage($fMessage);
151
		$attemptsMessage="";
152
		if(($nbAttempsMax=$this->attemptsNumber())!==null){
153
			$nb=USession::getTmp($this->_attemptsSessionKey,$nbAttempsMax);
154
			$nb--;
155
			if($nb<0) $nb=0;
156
			if($nb==0){
157
				$fAttemptsNumberMessage=$this->noAttempts();
158
			}else{
159
				$fAttemptsNumberMessage=new FlashMessage("<i class='ui warning icon'></i> You still have {_attemptsCount} attempts to log in.",null,"bottom attached warning","");
160
			}
161
			USession::setTmp($this->_attemptsSessionKey, $nb,$this->attemptsTimeout());
162
			$this->attemptsNumberMessage($fAttemptsNumberMessage,$nb);
163
			$fAttemptsNumberMessage->parseContent(["_attemptsCount"=>$nb,"_timer"=>"<span id='timer'></span>"]);
164
			$attemptsMessage=$this->fMessage($fAttemptsNumberMessage,"timeout-message");
165
			$fMessage->addType("attached");
166
		}
167
		$message=$this->fMessage($fMessage,"bad-login").$attemptsMessage;
168
		$this->authLoadView($this->_getFiles()->getViewNoAccess(),["_message"=>$message,"authURL"=>$this->getBaseUrl(),"bodySelector"=>$this->_getBodySelector(),"_loginCaption"=>$this->_loginCaption]);
169
	}
170
	
171
	protected function noAttempts(){
172
		$timeout=$this->attemptsTimeout();
173
		$plus="";
174
		if(is_numeric($timeout)){
175
			$this->jquery->exec("$('._login').addClass('disabled');",true);
176
			$plus=" You can try again {_timer}";
177
			$this->jquery->exec("var startTimer=function(duration, display) {var timer = duration, minutes, seconds;
178
    										var interval=setInterval(function () {
179
        										minutes = parseInt(timer / 60, 10);seconds = parseInt(timer % 60, 10);
180
										        minutes = minutes < 10 ? '0' + minutes : minutes;
181
        										seconds = seconds < 10 ? '0' + seconds : seconds;
182
										        display.html(minutes + ':' + seconds);
183
										        if (--timer < 0) {clearInterval(interval);$('#timeout-message').hide();$('#bad-login').removeClass('attached');$('._login').removeClass('disabled');}
184
    										}, 1000);
185
										}",true);
186
			$timeToLeft=USession::getTimeout($this->_attemptsSessionKey);
187
			$this->jquery->exec("startTimer({$timeToLeft},$('#timer'));",true);
188
			$this->jquery->compile($this->view);
189
		}
190
		return new FlashMessage("<i class='ui warning icon'></i> You have no more attempt of connection !".$plus,null,"bottom attached error","");
191
	}
192
	
193
	/**
194
	 * To override for modifying the bad login message
195
	 * @param FlashMessage $fMessage
196
	 */
197
	protected function badLoginMessage(FlashMessage $fMessage){
198
		
199
	}
200
	
201
	private function authLoadView($viewName,$vars=[]){
202
		$files=$this->_getFiles();
203
		$mainTemplate=$files->getBaseTemplate();
204
		if(isset($mainTemplate)){
205
			$vars["_viewname"]=$viewName;
206
			$vars["_base"]=$mainTemplate;
207
			$this->loadView($files->getViewBaseTemplate(),$vars);
208
		}else{
209
			$this->loadView($viewName,$vars);
210
		}
211
	}
212
	
213
	/**
214
	 * Logout action
215
	 * Terminate the session and display a logout message
216
	 */
217
	public function terminate(){
218
		USession::terminate();
219
		$fMessage=new FlashMessage("You have been properly disconnected!","Logout","success","checkmark");
220
		$this->terminateMessage($fMessage);
221
		$message=$this->fMessage($fMessage);
222
		$this->authLoadView($this->_getFiles()->getViewNoAccess(),["_message"=>$message,"authURL"=>$this->getBaseUrl(),"bodySelector"=>$this->_getBodySelector(),"_loginCaption"=>$this->_loginCaption]);
223
	}
224
	
225
	public function _disConnected(){
226
		$fMessage=new FlashMessage("You have been disconnected from the application!","Logout","","sign out");
227
		$this->disconnectedMessage($fMessage);
228
		$message=$this->fMessage($fMessage);
229
		$this->jquery->getOnClick("._signin", $this->getBaseUrl(),$this->_getBodySelector(),["stopPropagation"=>false,"preventDefault"=>false]);
230
		$this->jquery->execOn("click", "._close", "window.open(window.location,'_self').close();");
231
		$this->jquery->renderView($this->_getFiles()->getViewDisconnected(),["_title"=>"Session ended","_message"=>$message]);
232
	}
233
	
234
	/**
235
	 * To override for modifying the logout message
236
	 * @param FlashMessage $fMessage
237
	 */
238
	protected function terminateMessage(FlashMessage $fMessage){
239
		
240
	}
241
	
242
	/**
243
	 * To override for modifying the disconnect message
244
	 * @param FlashMessage $fMessage
245
	 */
246
	protected function disconnectedMessage(FlashMessage $fMessage){
247
		
248
	}
249
	
250
	/**
251
	 * Action displaying the logged user information 
252
	 * if _displayInfoAsString returns true, use _infoUser var in views to display user info
253
	 * @return string|null
254
	 */
255
	public function info(){
256
		return $this->loadView($this->_getFiles()->getViewInfo(),["connected"=>USession::get($this->_getUserSessionKey()),"authURL"=>$this->getBaseUrl(),"bodySelector"=>$this->_getBodySelector()],$this->_displayInfoAsString());
257
	}
258
	
259
	protected function fMessage(FlashMessage $fMessage,$id=null){
260
		return $this->message($fMessage->getType(), $fMessage->getTitle(), $fMessage->getContent(),$fMessage->getIcon(),$id);
261
	}
262
	
263
	public function message($type,$header,$body,$icon="info",$id=null){
264
		return $this->loadView($this->_getFiles()->getViewMessage(),get_defined_vars(),true);
265
	}
266
	
267
	protected function getOriginalURL(){
268
		return USession::get("urlParts");
269
	}
270
	
271
	/**
272
	 * To override for defining user session key, default : "activeUser"
273
	 * @return string
274
	 */
275
	public function _getUserSessionKey(){
276
		return "activeUser";
277
	}
278
	
279
	/**
280
	 * To override for getting active user, default : USession::get("activeUser")
281
	 * @return string
282
	 */
283
	public function _getActiveUser(){
284
		return USession::get($this->_getUserSessionKey());
285
	}
286
	
287
	/**
288
	 * To override
289
	 * Returns the maximum number of allowed login attempts
290
	 */
291
	protected function attemptsNumber(){
292
		return;
293
	}
294
	
295
	/**
296
	 * To override
297
	 * Returns the time before trying to connect again
298
	 * Effective only if attemptsNumber return a number
299
	 * @return number
300
	 */
301
	protected function attemptsTimeout(){
302
		return 3*60;
303
	}
304
	
305
	public function _checkConnection(){
306
		UResponse::asJSON();
307
		echo "{\"valid\":".UString::getBooleanStr($this->_isValidUser())."}";
308
	}
309
	
310
	/**
311
	 * return boolean true if activeUser is valid
312
	 */
313
	abstract public function _isValidUser();
314
	
315
	/**
316
	 * To override for changing view files
317
	 * @return AuthFiles
318
	 */
319
	protected function getFiles ():AuthFiles{
320
		return new AuthFiles();
321
	}
322
	
323
	/**
324
	 * Override to define if info is displayed as string
325
	 * if set to true, use _infoUser var in views to display user info
326
	 */
327
	public function _displayInfoAsString(){
328
		return false;
329
	}
330
	
331
	public function _checkConnectionTimeout(){
332
		return;
333
	}
334
	
335
	private function _getFiles():AuthFiles{
336
		if(!isset($this->authFiles)){
337
			$this->authFiles=$this->getFiles();
338
		}
339
		return $this->authFiles;
340
	}
341
	
342
	public function _getLoginInputName(){
343
		return "email";
344
	}
345
346
	protected function loginLabel(){
347
		return ucfirst($this->_getLoginInputName());
348
	}
349
	
350
	public function _getPasswordInputName(){
351
		return "password";
352
	}
353
	
354
	protected function passwordLabel(){
355
		return ucfirst($this->_getPasswordInputName());
356
	}
357
	
358
	public function _getBodySelector(){
359
		return "body";
360
	}
361
	
362
	/**
363
	 * Sets the default noAccess message
364
	 * Default : "You are not authorized to access the page <b>{url}</b> !"
365
	 * @param string $content
366
	 * @param string $title
367
	 * @param string $type
368
	 * @param string $icon
369
	 */
370
	public function _setNoAccessMsg($content,$title=NULL,$type=NULL,$icon=null) {
371
		$this->_noAccessMsg->setValues($content,$title,$type,$icon);
372
	}
373
	/**
374
	 * @param string $_loginCaption
375
	 */
376
	public function _setLoginCaption($_loginCaption) {
377
		$this->_loginCaption = $_loginCaption;
378
	}
379
	
380
	protected function rememberCaption(){
381
		return "Remember me";
382
	}
383
	
384
	protected function getViewVars($viewname){
385
		return ["authURL"=>$this->getBaseUrl(),"bodySelector"=>$this->_getBodySelector(),"_loginCaption"=>$this->_loginCaption];
386
	}
387
	
388
	/**
389
	 * Saves the connected user identifier in a cookie
390
	 * @param object $connected
391
	 */
392
	protected function rememberMe($connected){
393
		$id= $this->toCookie($connected);
394
		if(isset($id)){
395
			UCookie::set($this->_getUserSessionKey(),$id);
396
		}
397
	}
398
	
399
	/**
400
	 * Returns the cookie for auto connection
401
	 * @return NULL|string
402
	 */
403
	protected function getCookieUser(){
404
		return UCookie::get($this->_getUserSessionKey());
405
	}
406
	
407
	/**
408
	 * Returns the value from connected user to save it in the cookie for auto connection
409
	 * @param object $connected
410
	 */
411
	protected function toCookie($connected){
412
		return;
413
	}
414
	
415
	/**
416
	 * Loads the user from database using the cookie value
417
	 * @param string $cookie
418
	 */
419
	protected function fromCookie($cookie){
420
		return;
421
	}
422
	
423
	/**
424
	 * Auto connect the user
425
	 */
426
	public function _autoConnect() {
427
		$cookie=$this->getCookieUser();
428
		if(isset($cookie)){
429
			$user=$this->fromCookie($cookie);
430
			if(isset($user)){
431
				USession::set($this->_getUserSessionKey(), $user);
432
			}
433
		}
434
	}
435
	/**
436
	 * Deletes the cookie for auto connection and returns to index
437
	 */
438
	public function forgetConnection(){
439
		UCookie::delete($this->_getUserSessionKey());
440
		$this->index();
441
	}
442
}
443