Completed
Push — master ( b99700...ceccd5 )
by Jean-Christophe
01:32
created

AuthController::toCookie()   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 1
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\utils\http\UResponse;
10
use Ubiquity\utils\base\UString;
11
use Ubiquity\controllers\Startup;
12
use Ubiquity\utils\http\UCookie;
13
use Ajax\service\Javascript;
14
15
 /**
16
 * Controller Auth
17
 * @property \Ajax\php\ubiquity\JsUtils $jquery
18
 **/
19
abstract class AuthController extends ControllerBase{
20
	use AuthControllerVariablesTrait,AuthControllerOverrideTrait;
21
	
22
	/**
23
	 * @var AuthFiles
24
	 */
25
	protected $authFiles;
26
	protected $_controller;
27
	protected $_action;
28
	protected $_actionParams;
29
	protected $_noAccessMsg;
30
	protected $_loginCaption;
31
	protected $_attemptsSessionKey="_attempts";
32
	protected $_controllerInstance;
33
	
34
	public function __construct($instance=null){
35
		parent::__construct();
36
		$this->_controller=Startup::getController();
37
		$this->_action=Startup::getAction();
38
		$this->_actionParams=Startup::getActionParams();
39
		$this->_noAccessMsg=new FlashMessage("You are not authorized to access the page <b>{url}</b> !","Forbidden access","error","warning circle");
40
		$this->_loginCaption="Log in";
41
		$this->_controllerInstance=$instance;
42
		if(isset($instance))
43
			Startup::injectDependences($instance, Startup::getConfig());
44
	}
45
	
46
	public function index(){
47
		if(($nbAttempsMax=$this->attemptsNumber())!==null){
48
			$nb=USession::getTmp($this->_attemptsSessionKey,$nbAttempsMax);
49
			if($nb<=0){
50
				$this->badLogin();
51
				return;
52
			}
53
		}
54
		$this->authLoadView($this->_getFiles()->getViewIndex(),["action"=>$this->getBaseUrl()."/connect",
55
				"loginInputName"=>$this->_getLoginInputName(),"loginLabel"=>$this->loginLabel(),
56
				"passwordInputName"=>$this->_getPasswordInputName(),"passwordLabel"=>$this->passwordLabel(),
57
				"rememberCaption"=>$this->rememberCaption()
58
		]);
59
	}
60
	
61
	private function getBaseUrl(){
62
		return URequest::getUrl($this->_getBaseRoute());
63
	}
64
	/**
65
	 * {@inheritDoc}
66
	 * @see \controllers\ControllerBase::isValid()
67
	 */
68
	public final function isValid($action) {
69
		return true;
70
	}
71
	
72
	/**
73
	 * Action called when the user does not have access rights to a requested resource
74
	 * @param array|string $urlParts
75
	 */
76
	public function noAccess($urlParts){
77
		if(!is_array($urlParts)){
78
			$urlParts=explode(".", $urlParts);
79
		}
80
		USession::set("urlParts", $urlParts);
81
		$fMessage=$this->_noAccessMsg;
82
		$this->noAccessMessage($fMessage);
83
		$message=$this->fMessage($fMessage->parseContent(["url"=>implode("/",$urlParts)]));
84
		/*if(URequest::isAjax()){
85
			$this->jquery->get($this->_getBaseRoute()."/info/f","#_userInfo",["historize"=>false,"jqueryDone"=>"replaceWith","hasLoader"=>false,"attr"=>""]);
86
			$this->jquery->compile($this->view);
87
		}*/
88
		$this->authLoadView($this->_getFiles()->getViewNoAccess(),["_message"=>$message,"authURL"=>$this->getBaseUrl(),"bodySelector"=>$this->_getBodySelector(),"_loginCaption"=>$this->_loginCaption]);
89
	}
90
	
91
92
	
93
	/**
94
	 * Override to implement the complete connection procedure 
95
	 */
96
	public function connect(){
97
		if(URequest::isPost()){
98
			if($connected=$this->_connect()){
99
				if(isset($_POST["ck-remember"])){
100
					$this->rememberMe($connected);
101
				}
102
				if(USession::exists($this->_attemptsSessionKey)){
103
					USession::delete($this->_attemptsSessionKey);
104
				}
105
				$this->onConnect($connected);
106
			}else{
107
				$this->onBadCreditentials();
108
			}
109
		}
110
	}
111
	
112
	/**
113
	 * Default Action for invalid creditentials
114
	 */
115
	public function badLogin(){
116
		$fMessage=new FlashMessage("Invalid creditentials!","Connection problem","warning","warning circle");
117
		$this->badLoginMessage($fMessage);
118
		$attemptsMessage="";
119
		if(($nbAttempsMax=$this->attemptsNumber())!==null){
120
			$nb=USession::getTmp($this->_attemptsSessionKey,$nbAttempsMax);
121
			$nb--;
122
			if($nb<0) $nb=0;
123
			if($nb==0){
124
				$fAttemptsNumberMessage=$this->noAttempts();
125
			}else{
126
				$fAttemptsNumberMessage=new FlashMessage("<i class='ui warning icon'></i> You still have {_attemptsCount} attempts to log in.",null,"bottom attached warning","");
127
			}
128
			USession::setTmp($this->_attemptsSessionKey, $nb,$this->attemptsTimeout());
129
			$this->attemptsNumberMessage($fAttemptsNumberMessage,$nb);
130
			$fAttemptsNumberMessage->parseContent(["_attemptsCount"=>$nb,"_timer"=>"<span id='timer'></span>"]);
131
			$attemptsMessage=$this->fMessage($fAttemptsNumberMessage,"timeout-message");
132
			$fMessage->addType("attached");
133
		}
134
		$message=$this->fMessage($fMessage,"bad-login").$attemptsMessage;
135
		$this->authLoadView($this->_getFiles()->getViewNoAccess(),["_message"=>$message,"authURL"=>$this->getBaseUrl(),"bodySelector"=>$this->_getBodySelector(),"_loginCaption"=>$this->_loginCaption]);
136
	}
137
	
138
	protected function noAttempts(){
139
		$timeout=$this->attemptsTimeout();
140
		$plus="";
141
		if(is_numeric($timeout)){
142
			$this->jquery->exec("$('._login').addClass('disabled');",true);
143
			$plus=" You can try again {_timer}";
144
			$this->jquery->exec("var startTimer=function(duration, display) {var timer = duration, minutes, seconds;
145
    										var interval=setInterval(function () {
146
        										minutes = parseInt(timer / 60, 10);seconds = parseInt(timer % 60, 10);
147
										        minutes = minutes < 10 ? '0' + minutes : minutes;
148
        										seconds = seconds < 10 ? '0' + seconds : seconds;
149
										        display.html(minutes + ':' + seconds);
150
										        if (--timer < 0) {clearInterval(interval);$('#timeout-message').hide();$('#bad-login').removeClass('attached');$('._login').removeClass('disabled');}
151
    										}, 1000);
152
										}",true);
153
			$timeToLeft=USession::getTimeout($this->_attemptsSessionKey);
154
			$this->jquery->exec("startTimer({$timeToLeft},$('#timer'));",true);
155
			$this->jquery->compile($this->view);
156
		}
157
		return new FlashMessage("<i class='ui warning icon'></i> You have no more attempt of connection !".$plus,null,"bottom attached error","");
158
	}
159
	
160
161
	private function authLoadView($viewName,$vars=[]){
162
		$files=$this->_getFiles();
163
		$mainTemplate=$files->getBaseTemplate();
164
		if(isset($mainTemplate)){
165
			$vars["_viewname"]=$viewName;
166
			$vars["_base"]=$mainTemplate;
167
			$this->loadView($files->getViewBaseTemplate(),$vars);
168
		}else{
169
			$this->loadView($viewName,$vars);
170
		}
171
	}
172
	
173
	/**
174
	 * Logout action
175
	 * Terminate the session and display a logout message
176
	 */
177
	public function terminate(){
178
		USession::terminate();
179
		$fMessage=new FlashMessage("You have been properly disconnected!","Logout","success","checkmark");
180
		$this->terminateMessage($fMessage);
181
		$message=$this->fMessage($fMessage);
182
		$this->authLoadView($this->_getFiles()->getViewNoAccess(),["_message"=>$message,"authURL"=>$this->getBaseUrl(),"bodySelector"=>$this->_getBodySelector(),"_loginCaption"=>$this->_loginCaption]);
183
	}
184
	
185
	public function _disConnected(){
186
		$fMessage=new FlashMessage("You have been disconnected from the application!","Logout","","sign out");
187
		$this->disconnectedMessage($fMessage);
188
		$message=$this->fMessage($fMessage);
189
		$this->jquery->getOnClick("._signin", $this->getBaseUrl(),$this->_getBodySelector(),["stopPropagation"=>false,"preventDefault"=>false]);
190
		$this->jquery->execOn("click", "._close", "window.open(window.location,'_self').close();");
191
		return $this->jquery->renderView($this->_getFiles()->getViewDisconnected(),["_title"=>"Session ended","_message"=>$message],true);
192
	}
193
	
194
	/**
195
	 * Action displaying the logged user information 
196
	 * if _displayInfoAsString returns true, use _infoUser var in views to display user info
197
	 * @return string|null
198
	 */
199
	public function info($force=null){
200
		if(isset($force)){
201
			$displayInfoAsString=($force===true)?true:false;
202
		}else{
203
			$displayInfoAsString=$this->_displayInfoAsString();
204
		}
205
		return $this->loadView($this->_getFiles()->getViewInfo(),["connected"=>USession::get($this->_getUserSessionKey()),"authURL"=>$this->getBaseUrl(),"bodySelector"=>$this->_getBodySelector()],$displayInfoAsString);
206
	}
207
	
208
	protected function fMessage(FlashMessage $fMessage,$id=null){
209
		return $this->message($fMessage->getType(), $fMessage->getTitle(), $fMessage->getContent(),$fMessage->getIcon(),$id);
210
	}
211
	
212
	public function message($type,$header,$body,$icon="info",$id=null){
213
		return $this->loadView($this->_getFiles()->getViewMessage(),get_defined_vars(),true);
214
	}
215
	
216
	protected function getOriginalURL(){
217
		return USession::get("urlParts");
218
	}
219
	
220
	public function checkConnection(){
221
		UResponse::asJSON();
222
		echo "{\"valid\":".UString::getBooleanStr($this->_isValidUser())."}";
223
	}
224
	
225
	
226
	/**
227
	 * To override for changing view files
228
	 * @return AuthFiles
229
	 */
230
	protected function getFiles ():AuthFiles{
231
		return new AuthFiles();
232
	}
233
	
234
	private function _getFiles():AuthFiles{
235
		if(!isset($this->authFiles)){
236
			$this->authFiles=$this->getFiles();
237
		}
238
		return $this->authFiles;
239
	}
240
	
241
	/**
242
	 * Sets the default noAccess message
243
	 * Default : "You are not authorized to access the page <b>{url}</b> !"
244
	 * @param string $content
245
	 * @param string $title
246
	 * @param string $type
247
	 * @param string $icon
248
	 */
249
	public function _setNoAccessMsg($content,$title=NULL,$type=NULL,$icon=null) {
250
		$this->_noAccessMsg->setValues($content,$title,$type,$icon);
251
	}
252
	/**
253
	 * @param string $_loginCaption
254
	 */
255
	public function _setLoginCaption($_loginCaption) {
256
		$this->_loginCaption = $_loginCaption;
257
	}
258
	
259
	protected function getViewVars($viewname){
260
		return ["authURL"=>$this->getBaseUrl(),"bodySelector"=>$this->_getBodySelector(),"_loginCaption"=>$this->_loginCaption];
261
	}
262
	
263
	/**
264
	 * Saves the connected user identifier in a cookie
265
	 * @param object $connected
266
	 */
267
	protected function rememberMe($connected){
268
		$id= $this->toCookie($connected);
1 ignored issue
show
Bug introduced by
Are you sure the assignment to $id is correct as $this->toCookie($connected) (which targets Ubiquity\controllers\aut...errideTrait::toCookie()) 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...
269
		if(isset($id)){
270
			UCookie::set($this->_getUserSessionKey(),$id);
271
		}
272
	}
273
	
274
	/**
275
	 * Returns the cookie for auto connection
276
	 * @return NULL|string
277
	 */
278
	protected function getCookieUser(){
279
		return UCookie::get($this->_getUserSessionKey());
280
	}
281
	
282
	/**
283
	 * Auto connect the user
284
	 */
285
	public function _autoConnect() {
286
		$cookie=$this->getCookieUser();
287
		if(isset($cookie)){
288
			$user=$this->fromCookie($cookie);
1 ignored issue
show
Bug introduced by
Are you sure the assignment to $user is correct as $this->fromCookie($cookie) (which targets Ubiquity\controllers\aut...rideTrait::fromCookie()) 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...
289
			if(isset($user)){
290
				USession::set($this->_getUserSessionKey(), $user);
291
			}
292
		}
293
	}
294
	/**
295
	 * Deletes the cookie for auto connection and returns to index
296
	 */
297
	public function forgetConnection(){
298
		UCookie::delete($this->_getUserSessionKey());
299
		$this->index();
300
	}
301
	/**
302
	 * {@inheritDoc}
303
	 * @see \Ubiquity\controllers\ControllerBase::finalize()
304
	 */
305
	public function finalize() {
306
		if(!UResponse::isJSON()){
307 View Code Duplication
			if(!URequest::isAjax()){
1 ignored issue
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
308
				if(isset($this->_controllerInstance)){
309
					call_user_func_array(array($this->_controllerInstance, 'parent::finalize'), []);
310
				}else{
311
					parent::finalize();	
312
				}
313
			}
314
			$this->jquery->execAtLast("if($('#_userInfo').length){\$('#_userInfo').html(".preg_replace("/$\R?^/m", "",Javascript::prep_element($this->info())).");}");
315
			echo $this->jquery->compile();
316
		}
317
	}
318
319
	/**
320
	 * {@inheritDoc}
321
	 * @see \Ubiquity\controllers\ControllerBase::initialize()
322
	 */
323
	public function initialize() {
324 View Code Duplication
		if(!URequest::isAjax()){
1 ignored issue
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
325
			if(isset($this->_controllerInstance)){
326
				call_user_func_array(array($this->_controllerInstance, 'parent::initialize'), []);
327
			}else{
328
				parent::initialize();
329
			}
330
		}
331
	}
332
	
333
	/**
334
	 * @param string $url
335
	 */
336
	public function _forward($url){
337
		$initFinalize=true;
338
		if(isset($this->_controllerInstance) && !URequest::isAjax()){
339
			$initFinalize=false;
340
		}
341
		Startup::forward($url,$initFinalize,$initFinalize);
342
	}
343
344
}
345