Completed
Push — master ( 774d12...7a0ba2 )
by Wanderson
02:14
created

User::setRecoreryHash()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
3
namespace Win\Authentication;
4
5
use Win\Mvc\Application;
6
use Win\Authentication\UserDAO;
7
use Local\Person\Person;
8
use Local\Person\PersonDAO;
9
use Win\Helper\Url;
10
use Win\Mvc\Block;
11
use Win\Mailer\Email;
12
use Win\File\Image;
13
use Win\Calendar\Date;
14
15
/**
16
 * Usuários do sistema
17
 */
18
class User {
19
20
	private static $accessLevels = [0, 1, 2];
21
22
	const ACCESS_DENIED = 0;
23
	const ACCESS_ALLOWED = 1;
24
	const ACCESS_ADMIN = 2;
25
26
	private static $passwordSalt = 'E50H%gDui#';
27
	private $id;
28
	private $isEnabled;
29
	private $isLogged;
30
	private $accessLevel;
31
	private $name;
32
	private $email;
33
	private $confirmEmail;
34
	private $password;
35
	private $confirmPassword;
36
	private $passwordHash;
37
	private $recoreryHash;
38
39
	/** @var Date */
40
	private $loginDate;
41
42
	/** @var Image */
43
	private $image;
44
45
	/** @var Group */
46
	private $group;
47
	private $groupId;
48
49
	/** @var Person */
50
	private $person;
51
52
	public function __construct() {
53
		$this->id = 0;
54
		$this->isEnabled = true;
55
		$this->isLogged = false;
56
		$this->accessLevel = self::ACCESS_DENIED;
57
		$this->name = '';
58
		$this->email = '';
59
		$this->confirmEmail = '';
60
		$this->password = null;
61
		$this->confirmPassword = null;
62
		$this->passwordHash = null;
63
		$this->recoreryHash = null;
64
		$this->image = new Image();
65
		$this->image->setDirectory('data/upload/user');
66
		$this->loginDate = new Date('00/00/0000');
67
		$this->group = null;
68
		$this->groupId = 0;
69
		$this->person = null;
70
	}
71
72
	public function getId() {
73
		return $this->id;
74
	}
75
76
	public function isEnabled() {
77
		return $this->isEnabled;
78
	}
79
80
	public function isLogged() {
81
		return $this->isLogged;
82
	}
83
84
	public function getAccessLevel() {
85
		return $this->accessLevel;
86
	}
87
88
	public function accessIsDenied() {
89
		return ($this->accessLevel == self::ACCESS_DENIED);
90
	}
91
92
	/** @return boolean */
93
	public function isAdmin() {
94
		return ($this->accessLevel == self::ACCESS_ADMIN);
95
	}
96
97
	public function getGroup() {
98
		if (is_null($this->group)) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
99
			// groupDAO
100
		}
101
		return $this->group;
102
	}
103
104
	public function getGroupId() {
105
		return $this->groupId;
106
	}
107
108
	/** @return Person */
109
	public function getPerson() {
110
		if (is_null($this->person)) {
111
			$pDAO = new PersonDAO();
112
			$this->person = $pDAO->fetchById($this->id);
113
		}
114
		return $this->person;
115
	}
116
117
	public function getName() {
118
		return $this->name;
119
	}
120
121
	public function getEmail() {
122
		return $this->email;
123
	}
124
125
	public function getConfirmEmail() {
126
		return $this->confirmEmail;
127
	}
128
129
	public function getPassword() {
130
		return $this->password;
131
	}
132
133
	public function getConfirmPassword() {
134
		return $this->confirmPassword;
135
	}
136
137
	public function getPasswordHash() {
138
		return $this->passwordHash;
139
	}
140
141
	public function getRecoreryHash() {
142
		return $this->recoreryHash;
143
	}
144
145
	public function getImage() {
146
		return $this->image;
147
	}
148
149
	public function getLoginDate() {
150
		return $this->loginDate;
151
	}
152
153
	public function setId($id) {
154
		$this->id = (int) $id;
155
	}
156
157
	public function setEnabled($enabled) {
158
		$this->isEnabled = (boolean) $enabled;
159
	}
160
161
	public function setAccessLevel($accessLevel) {
162
		if (in_array($accessLevel, static::$accessLevels)) {
0 ignored issues
show
Bug introduced by
Since $accessLevels is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $accessLevels to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
163
			$this->accessLevel = (int) $accessLevel;
164
		}
165
	}
166
167
	public function setGroup(Group $group) {
168
		$this->group = $group;
169
	}
170
171
	public function setGroupId($groupId) {
172
		$this->groupId = (int) $groupId;
173
	}
174
175
	public function setPerson(Person $person) {
176
		$this->person = $person;
177
	}
178
179
	public function setName($name) {
180
		$this->name = $name;
181
	}
182
183
	public function setEmail($email) {
184
		$this->email = strClear($email);
185
	}
186
187
	public function setConfirmEmail($confirmEmail) {
188
		$this->confirmEmail = strClear($confirmEmail);
189
	}
190
191
	public function setPassword($password) {
192
		$this->password = $password;
193
		$this->passwordHash = static::encryptPassword($password);
194
	}
195
196
	public function setConfirmPassword($confirmPassword) {
197
		$this->confirmPassword = $confirmPassword;
198
	}
199
200
	public function setPasswordHash($passwordHash) {
201
		$this->passwordHash = $passwordHash;
202
	}
203
204
	public function setRecoreryHash($recoreryHash) {
205
		$this->recoreryHash = $recoreryHash;
206
	}
207
208
	public function setLoginDate(Date $loginDate) {
209
		$this->loginDate = $loginDate;
210
	}
211
212
	public function setImage(Image $image) {
213
		$this->image = $image;
214
	}
215
216
	/**
217
	 * Tenta realizar login
218
	 * @return boolean
219
	 */
220
	public function login() {
221
		$filters = [
222
			'is_enabled = ?' => true,
223
			'access_level > ?' => 0,
224
			'email = ?' => $this->email,
225
			'password_hash = ?' => $this->passwordHash
226
		];
227
		$uDAO = new UserDAO();
228
		$user = $uDAO->fetch($filters);
0 ignored issues
show
Documentation introduced by
$filters is of type array<string,boolean|int...sh = ?":"null|string"}>, but the function expects a array<integer,string>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
229
230
		if ($user->getId() > 0) {
231
			$this->setCurrentUser($user);
232
			$uDAO->updateLoginDate($user);
233
		}
234
		return $user->isLogged;
235
	}
236
237
	/** Realiza logout */
238
	public function logout() {
239
		unset($_SESSION['user']);
240
	}
241
242
	/** Objeto > Sessão */
243
	private function setCurrentUser(User $user) {
244
		$_SESSION['user'] = $user;
245
		$user->isLogged = true;
246
		$this->isLogged = true;
247
		$this->id = $user->getId();
248
		$this->accessLevel = $user->getAccessLevel();
249
		$this->name = $user->getName();
250
		$this->loginDate = $user->getLoginDate();
251
		$this->image = $user->getImage();
252
	}
253
254
	/** Objeto < Sessão */
255
	public static function getCurrentUser() {
256
		return (isset($_SESSION['user'])) ? $_SESSION['user'] : new User();
257
	}
258
259
	/** Obriga o usuário a se logar */
260
	public function requireLogin() {
261
		if (!$this->isLogged) {
262
			Url::instance()->redirect('login');
263
		}
264
	}
265
266
	/** Obriga o usuário a logar como ADMIN */
267
	public function requireAdmin() {
268
		$this->requireLogin();
269
		if ($this->getAccessLevel() != static::ACCESS_ADMIN) {
270
			Application::app()->errorPage(403);
271
		}
272
	}
273
274
	/**
275
	 * Envia link de recuperacao de senha via Email
276
	 * @return string | null
277
	 */
278
	public function sendRecoveryHash() {
279
		$filters = ['is_enabled = ?' => true, 'access_level > ?' => 0, 'email = ?' => $this->email];
280
		$uDAO = new UserDAO();
281
		$user = $uDAO->fetch($filters);
0 ignored issues
show
Documentation introduced by
$filters is of type array<string,boolean|int...,"email = ?":"string"}>, but the function expects a array<integer,string>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
282
283
		if ($user->getId() > 0) {
284
			$uDAO->updateRecoveryHash($user);
285
			$content = new Block('email/content/recovery-password', ['user' => $user]);
286
287
			$mail = new Email();
288
			$mail->setFrom(EMAIL_FROM, Application::app()->getName());
289
			$mail->setSubject('Recuperação de Senha');
290
			$mail->addAddress($user->getEmail(), $user->getName());
291
			$mail->setContent($content);
292
			return $mail->send();
293
		} else {
294
			return 'Este E-mail não está cadastrado no sistema.';
295
		}
296
	}
297
298
	/** Define os atributos que são salvos na SESSAO */
299
	public function __sleep() {
300
		return ['id', 'isEnabled', 'isLogged', 'accessLevel', 'name', 'email', 'image', 'loginDate', 'groupId'];
301
	}
302
303
	/**
304
	 * Adiciona maior segura na senha/ utilizar esta função ao inves de um simples md5
305
	 * @param string $password
306
	 */
307
	public static function encryptPassword($password) {
308
		return md5($password . static::$passwordSalt);
0 ignored issues
show
Bug introduced by
Since $passwordSalt is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $passwordSalt to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
309
	}
310
311
	/**
312
	 * Retorna uma senha aleatoria
313
	 * A senha tem sempre pelo menos: 1 caracter especial e 2 numeros;
314
	 * @param int $length
315
	 * @return string
316
	 */
317
	public static function generatePassword($length = 6) {
318
		$letters = str_shuffle('abcdefghijkmnopqrstwxyzABCDEFGHJKLMNPQRSTWXY');
319
		$numbers = str_shuffle('23456789');
320
		$specials = str_shuffle('@#&');
321
322
		$password = substr($letters, 0, $length - 3)
323
				. substr($numbers, 0, 2)
324
				. substr($specials, 0, 1);
325
326
		return str_shuffle($password);
327
	}
328
329
}
330