PasswordTrait   A
last analyzed

Complexity

Total Complexity 8

Size/Duplication

Total Lines 88
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 4
Bugs 0 Features 0
Metric Value
wmc 8
c 4
b 0
f 0
lcom 1
cbo 1
dl 0
loc 88
rs 10

4 Methods

Rating   Name   Duplication   Size   Complexity  
A hash_password() 0 4 1
A set_password() 0 11 2
A get_has_legacy_password_hash() 0 9 2
A verify_password() 0 20 3
1
<?php
2
3
/*
4
 * This file is part of the Icybee package.
5
 *
6
 * (c) Olivier Laviale <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Icybee\Modules\Users;
13
14
/**
15
 * A trait to handle a password.
16
 *
17
 * The trait adds support for a `password` and `password_hash` property. The `password` property
18
 * is white-only, and the `password_hash` property is private and only accessible by the class
19
 * using the trait. The {@link verify_password()} and {@link hash_password()} method must be
20
 * used for password Operation.
21
 *
22
 * Currently, for the trait to work properly the `password` property needs to be unset during
23
 * `__construct()` and the `password_hash` property needs to be added during `to_array()`:
24
 *
25
 * <pre>
26
 * <?php
27
 *
28
 * class User extends \ICanBoogie\ActiveRecord
29
 * {
30
 *     public function __construct($model=self::MODEL_ID)
31
 *     {
32
 *         if (isset($this->password))
33
 *         {
34
 *             $this->set_password($this->password);
35
 *
36
 *             unset($this->password);
37
 *         }
38
 *
39
 *         parent::__construct($model);
40
 *     }
41
 *
42
 *     // …
43
 *
44
 *     public function to_array()
45
 *     {
46
 *         return parent::to_array() + [
47
 *
48
 *             'password_hash' => $this->password_hash
49
 *         ];
50
 *     }
51
 *
52
 *     // …
53
 * }
54
 * </pre>
55
 *
56
 * @property-write string $password
57
 */
58
trait PasswordTrait
59
{
60
	/**
61
	 * User password.
62
	 *
63
	 * The property is only used to update the {@link $password_hash} property when the
64
	 * record is saved.
65
	 *
66
	 * @var string
67
	 */
68
	protected function set_password($password)
69
	{
70
		if (!$password)
71
		{
72
			$this->password_hash = null;
73
74
			return;
75
		}
76
77
		$this->password_hash = $this->hash_password($password);
78
	}
79
80
	/**
81
	 * User password hash.
82
	 *
83
	 * @var string
84
	 */
85
	private $password_hash;
86
87
	/**
88
	 * Checks if the password hash is a legacy hash, and not a hash created by
89
	 * the {@link \password_hash()} function.
90
	 *
91
	 * @return bool|null `true` if the password hash is a legacy hash, `false` if the password
92
	 * hash was created by the {@link \password_hash()} function, and `null` if the password hash
93
	 * is empty.
94
	 */
95
	protected function get_has_legacy_password_hash()
96
	{
97
		if (!$this->password_hash)
98
		{
99
			return null;
100
		}
101
102
		return $this->password_hash[0] != '$';
103
	}
104
105
	/**
106
	 * Hashes a password.
107
	 *
108
	 * @param string $password
109
	 *
110
	 * @return string
111
	 */
112
	static public function hash_password($password)
113
	{
114
		return password_hash($password, \PASSWORD_BCRYPT);
115
	}
116
117
	/**
118
	 * Compares a password to the user's password hash.
119
	 *
120
	 * @param string $password
121
	 *
122
	 * @return bool `true` if the hashed password matches the user's password hash,
123
	 * `false` otherwise.
124
	 */
125
	public function verify_password($password)
126
	{
127
		if (password_verify($password, $this->password_hash))
128
		{
129
			return true;
130
		}
131
132
		#
133
		# Trying old hashing
134
		#
135
136
		$config = \ICanBoogie\Core::get()->configs['user'];
137
138
		if (empty($config['password_salt']))
139
		{
140
			return false;
141
		}
142
143
		return sha1(hash_pbkdf2('sha1', $password, $config['password_salt'], 1000)) == $this->password_hash;
144
	}
145
}
146