Completed
Push — master ( 530ddf...47cb1f )
by Jean-Christophe
02:11
created

AuthController::noAttempts()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 21
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 21
rs 9.3142
c 0
b 0
f 0
cc 2
eloc 12
nc 2
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
14
 /**
15
 * Controller Auth
16
 * @property \Ajax\php\ubiquity\JsUtils $jquery
17
 **/
18
abstract class AuthController extends ControllerBase{
19
	/**
20
	 * @var AuthFiles
21
	 */
22
	protected $authFiles;
23
	protected $_controller;
24
	protected $_action;
25
	protected $_actionParams;
26
	protected $_noAccessMsg;
27
	protected $_loginCaption;
28
	protected $_attemptsSessionKey="_attempts";
29
	
30
	public function __construct(){
31
		parent::__construct();
32
		$this->_controller=Startup::getController();
33
		$this->_action=Startup::getAction();
34
		$this->_actionParams=Startup::getActionParams();
35
		$this->_noAccessMsg=new FlashMessage("You are not authorized to access the page <b>{url}</b> !","Forbidden access","error","warning circle");
36
		$this->_loginCaption="Log in";
37
	}
38
	
39
	public function index(){
40
		if(($nbAttempsMax=$this->attemptsNumber())!=null){
41
			$nb=USession::getTmp($this->_attemptsSessionKey,$nbAttempsMax);
42
			if($nb<=0){
43
				$this->badLogin();
44
				return;
45
			}
46
		}
47
		$this->authLoadView($this->_getFiles()->getViewIndex(),["action"=>$this->_getBaseRoute()."/connect",
48
				"loginInputName"=>$this->_getLoginInputName(),"loginLabel"=>$this->loginLabel(),
49
				"passwordInputName"=>$this->_getPasswordInputName(),"passwordLabel"=>$this->passwordLabel()
50
		]);
51
	}
52
	
53
	/**
54
	 * To override
55
	 * Return the base route for this Auth controller
56
	 * @return string
57
	 */
58
	public function _getBaseRoute(){
59
		return ClassUtils::getClassSimpleName(get_class($this));
60
	}
61
	/**
62
	 * {@inheritDoc}
63
	 * @see \controllers\ControllerBase::isValid()
64
	 */
65
	public final function isValid($action) {
0 ignored issues
show
Coding Style introduced by
As per PSR2, final should precede the visibility keyword.
Loading history...
66
		return true;
67
	}
68
	
69
	/**
70
	 * Action called when the user does not have access rights to a requested resource
71
	 * @param array|string $urlParts
72
	 */
73
	public function noAccess($urlParts){
74
		if(!is_array($urlParts)){
75
			$urlParts=explode(".", $urlParts);
76
		}
77
		USession::set("urlParts", $urlParts);
78
		$fMessage=$this->_noAccessMsg;
79
		$this->noAccessMessage($fMessage);
80
		$message=$this->fMessage($fMessage->parseContent(["url"=>implode("/",$urlParts)]));		
81
		$this->authLoadView($this->_getFiles()->getViewNoAccess(),["_message"=>$message,"authURL"=>$this->_getBaseRoute(),"bodySelector"=>$this->_getBodySelector(),"_loginCaption"=>$this->_loginCaption]);
82
	}
83
	
84
	/**
85
	 * Override for modifying the noAccess message
86
	 * @param FlashMessage $fMessage
87
	 */
88
	protected function noAccessMessage(FlashMessage $fMessage){
89
		
90
	}
91
	
92
	/**
93
	 * Override for modifying attempts message
94
	 * You can use {_timer} and {_attemptsCount} variables in message content
95
	 * @param FlashMessage $fMessage
96
	 * @param int $attempsCount
97
	 */
98
	protected function attemptsNumberMessage(FlashMessage $fMessage,$attempsCount){
99
		
100
	}
101
	
102
	/**
103
	 * Override to implement the complete connection procedure 
104
	 */
105
	public function connect(){
106
		if(URequest::isPost()){
107
			if($connected=$this->_connect()){
108
				if(USession::exists($this->_attemptsSessionKey)){
109
					USession::delete($this->_attemptsSessionKey);
110
				}
111
				$this->onConnect($connected);
112
			}else{
113
				$this->onBadCreditentials();
114
			}
115
		}
116
	}
117
	
118
	/**
119
	 * Processes the data posted by the login form
120
	 * Have to return the connected user instance
121
	 */
122
	abstract protected function _connect();
123
	
124
	/**
125
	 * @param object $connected
126
	 */
127
	abstract protected function onConnect($connected);
128
	
129
	/**
130
	 * To override for defining a new action when creditentials are invalid
131
	 */
132
	protected function onBadCreditentials(){
133
		$this->badLogin();
134
	}
135
	
136
	/**
137
	 * Default Action for invalid creditentials
138
	 */
139
	public function badLogin(){
140
		$fMessage=new FlashMessage("Invalid creditentials!","Connection problem","warning","warning circle");
141
		$this->badLoginMessage($fMessage);
142
		$attemptsMessage="";
143
		if(($nbAttempsMax=$this->attemptsNumber())!=null){
144
			$nb=USession::getTmp($this->_attemptsSessionKey,$nbAttempsMax);
145
			$nb--;
146
			if($nb<0) $nb=0;
147
			if($nb==0){
148
				$fAttemptsNumberMessage=$this->noAttempts();
149
			}else{
150
				$fAttemptsNumberMessage=new FlashMessage("<i class='ui warning icon'></i> You still have {_attemptsCount} attempts to log in.",null,"bottom attached warning","");
151
			}
152
			USession::setTmp($this->_attemptsSessionKey, $nb,$this->attemptsTimeout());
153
			$this->attemptsNumberMessage($fAttemptsNumberMessage,$nb);
154
			$fAttemptsNumberMessage->parseContent(["_attemptsCount"=>$nb,"_timer"=>"<span id='timer'></span>"]);
155
			$attemptsMessage=$this->fMessage($fAttemptsNumberMessage,"timeout-message");
156
			$fMessage->addType("attached");
157
		}
158
		$message=$this->fMessage($fMessage,"bad-login").$attemptsMessage;
159
		$this->authLoadView($this->_getFiles()->getViewNoAccess(),["_message"=>$message,"authURL"=>$this->_getBaseRoute(),"bodySelector"=>$this->_getBodySelector(),"_loginCaption"=>$this->_loginCaption]);
160
	}
161
	
162
	protected function noAttempts(){
163
		$timeout=$this->attemptsTimeout();
164
		$plus="";
165
		if(is_numeric($timeout)){
166
			$this->jquery->exec("$('._login').addClass('disabled');",true);
167
			$plus=" You can try again {_timer}";
168
			$this->jquery->exec("var startTimer=function(duration, display) {var timer = duration, minutes, seconds;
169
    										var interval=setInterval(function () {
170
        										minutes = parseInt(timer / 60, 10);seconds = parseInt(timer % 60, 10);
171
										        minutes = minutes < 10 ? '0' + minutes : minutes;
172
        										seconds = seconds < 10 ? '0' + seconds : seconds;
173
										        display.html('in ' +minutes + ':' + seconds);
174
										        if (--timer < 0) {clearInterval(interval);$('#timeout-message').hide();$('#bad-login').removeClass('attached');$('._login').removeClass('disabled');}
175
    										}, 1000);
176
										}",true);
177
			$timeToLeft=USession::getTimeout($this->_attemptsSessionKey);
178
			$this->jquery->exec("startTimer({$timeToLeft},$('#timer'));",true);
179
			$this->jquery->compile($this->view);
180
		}
181
		return new FlashMessage("<i class='ui warning icon'></i> You have no more attempt of connection !".$plus,null,"bottom attached error","");
182
	}
183
	
184
	/**
185
	 * To override for modifying the bad login message
186
	 * @param FlashMessage $fMessage
187
	 */
188
	protected function badLoginMessage(FlashMessage $fMessage){
189
		
190
	}
191
	
192
	private function authLoadView($viewName,$vars=[]){
193
		$files=$this->_getFiles();
194
		$mainTemplate=$files->getBaseTemplate();
1 ignored issue
show
Bug introduced by
Are you sure the assignment to $mainTemplate is correct as $files->getBaseTemplate() (which targets Ubiquity\controllers\Aut...iles::getBaseTemplate()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
195
		if(isset($mainTemplate)){
196
			$vars["_viewname"]=$viewName;
197
			$vars["_base"]=$mainTemplate;
198
			$this->loadView($files->getViewBaseTemplate(),$vars);
199
		}else{
200
			$this->loadView($viewName,$vars);
201
		}
202
	}
203
	
204
	/**
205
	 * Logout action
206
	 * Terminate the session and display a logout message
207
	 */
208
	public function terminate(){
209
		USession::terminate();
210
		$fMessage=new FlashMessage("You have been properly disconnected!","Logout","success","checkmark");
211
		$this->terminateMessage($fMessage);
212
		$message=$this->fMessage($fMessage);
213
		$this->authLoadView($this->_getFiles()->getViewNoAccess(),["_message"=>$message,"authURL"=>$this->_getBaseRoute(),"bodySelector"=>$this->_getBodySelector(),"_loginCaption"=>$this->_loginCaption]);
214
	}
215
	
216
	public function _disConnected(){
217
		$fMessage=new FlashMessage("You have been disconnected from the application!","Logout","","sign out");
218
		$this->disconnectedMessage($fMessage);
219
		$message=$this->fMessage($fMessage);
220
		$this->jquery->getOnClick("._signin", $this->_getBaseRoute(),$this->_getBodySelector(),["stopPropagation"=>false,"preventDefault"=>false]);
221
		$this->jquery->execOn("click", "._close", "window.open(window.location,'_self').close();");
222
		$this->jquery->renderView($this->_getFiles()->getViewDisconnected(),["_title"=>"Session ended","_message"=>$message]);
223
	}
224
	
225
	/**
226
	 * To override for modifying the logout message
227
	 * @param FlashMessage $fMessage
228
	 */
229
	protected function terminateMessage(FlashMessage $fMessage){
230
		
231
	}
232
	
233
	/**
234
	 * To override for modifying the disconnect message
235
	 * @param FlashMessage $fMessage
236
	 */
237
	protected function disconnectedMessage(FlashMessage $fMessage){
238
		
239
	}
240
	
241
	/**
242
	 * Action displaying the logged user information 
243
	 * if _displayInfoAsString returns true, use _infoUser var in views to display user info
244
	 * @return string|null
245
	 */
246
	public function info(){
247
		return $this->loadView($this->_getFiles()->getViewInfo(),["connected"=>USession::get($this->_getUserSessionKey()),"authURL"=>$this->_getBaseRoute(),"bodySelector"=>$this->_getBodySelector()],$this->_displayInfoAsString());
248
	}
249
	
250
	protected function fMessage(FlashMessage $fMessage,$id=null){
251
		return $this->message($fMessage->getType(), $fMessage->getTitle(), $fMessage->getContent(),$fMessage->getIcon(),$id);
252
	}
253
	
254
	public function message($type,$header,$body,$icon="info",$id=null){
255
		return $this->loadView($this->_getFiles()->getViewMessage(),get_defined_vars(),true);
256
	}
257
	
258
	protected function getOriginalURL(){
259
		return USession::get("urlParts");
260
	}
261
	
262
	/**
263
	 * To override for defining user session key, default : "activeUser"
264
	 * @return string
265
	 */
266
	public function _getUserSessionKey(){
267
		return "activeUser";
268
	}
269
	
270
	/**
271
	 * To override for getting active user, default : USession::get("activeUser")
272
	 * @return string
273
	 */
274
	public function _getActiveUser(){
275
		return USession::get($this->_getUserSessionKey());
276
	}
277
	
278
	/**
279
	 * To override
280
	 * Returns the maximum number of allowed login attempts
281
	 */
282
	protected function attemptsNumber(){
283
		return;
284
	}
285
	
286
	/**
287
	 * To override
288
	 * Returns the time before trying to connect again
289
	 * Effective only if attemptsNumber return a number
290
	 * @return number
291
	 */
292
	protected function attemptsTimeout(){
293
		return 3*60;
294
	}
295
	
296
	public function _checkConnection(){
297
		UResponse::asJSON();
298
		echo "{\"valid\":".UString::getBooleanStr($this->_isValidUser())."}";
299
	}
300
	
301
	/**
302
	 * return boolean true if activeUser is valid
303
	 */
304
	abstract public function _isValidUser();
305
	
306
	/**
307
	 * To override for changing view files
308
	 * @return AuthFiles
309
	 */
310
	protected function getFiles ():AuthFiles{
311
		return new AuthFiles();
312
	}
313
	
314
	/**
315
	 * Override to define if info is displayed as string
316
	 * if set to true, use _infoUser var in views to display user info
317
	 */
318
	public function _displayInfoAsString(){
319
		return false;
320
	}
321
	
322
	public function _checkConnectionTimeout(){
323
		return;
324
	}
325
	
326
	private function _getFiles():AuthFiles{
327
		if(!isset($this->authFiles)){
328
			$this->authFiles=$this->getFiles();
329
		}
330
		return $this->authFiles;
331
	}
332
	
333
	public function _getLoginInputName(){
334
		return "email";
335
	}
336
337
	protected function loginLabel(){
338
		return ucfirst($this->_getLoginInputName());
339
	}
340
	
341
	public function _getPasswordInputName(){
342
		return "password";
343
	}
344
	
345
	protected function passwordLabel(){
346
		return ucfirst($this->_getPasswordInputName());
347
	}
348
	
349
	public function _getBodySelector(){
350
		return "body";
351
	}
352
	
353
	/**
354
	 * Sets the default noAccess message
355
	 * Default : "You are not authorized to access the page <b>{url}</b> !"
356
	 * @param string $content
357
	 * @param string $title
358
	 * @param string $type
359
	 * @param string $icon
360
	 */
361
	public function _setNoAccessMsg($content,$title=NULL,$type=NULL,$icon=null) {
362
		$this->_noAccessMsg->setValues($content,$title,$type,$icon);
363
	}
364
	/**
365
	 * @param string $_loginCaption
366
	 */
367
	public function _setLoginCaption($_loginCaption) {
368
		$this->_loginCaption = $_loginCaption;
369
	}
370
	
371
	
372
373
374
}
375