aboutsummaryrefslogtreecommitdiff
path: root/classes/user.php
blob: f6c6322b370d24c9c71b2e939fcd5444e929bdef (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
<?php
/**
 * Provides the user class, an interface to the user table in the database
 *
 * @author Camil Staps
 *
 * BusinessAdmin: administrative software for small companies
 * Copyright (C) 2015 Camil Staps (ViviSoft)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * An interface to the user table in the database
 */
class user {
	/**
	 * @var pdo $pdo                    The PDO class for database communication
	 * @var int $id                     The id of the user
	 * @var string $username            The username of the user
	 * @var string $password            The (hashed) password of the user
	 */
	protected $pdo, $id, $username, $password;

	/**
	 * Generate a random password
	 *
	 * @return string The password
	 */
	public static function generateRandomPassword() {
		return preg_replace('/[^\w]/', '',
			base64_encode(bin2hex(openssl_random_pseudo_bytes(4))));
	}

	/**
	 * Hash a password
	 *
	 * @param string $password          The password to be hashed
	 * @param int $cost                 The password cost
	 *
	 * @return string The hashed password
	 */
	public static function hash($password, $cost=null) {
		return password_hash(
			$password,
			constants::password_algo,
			['cost' => is_null($cost) ? constants::password_cost : $cost]
		);
	}

	/**
	 * Create a new instance
	 *
	 * @param PDO $pdo                  The PDO class, to access the database
	 * @param int $id                   The id of the user to fetch
	 *
	 * @throws PDOException             If something went wrong with the database
	 * @throws Exception                If the user could not be found
	 */
	public function __construct($pdo, $id) {
		$this->pdo = $pdo;

		$stmt = $this->pdo->prepare("SELECT * FROM `".constants::db_prefix."user` WHERE `id`=?");
		$stmt->execute(array($id));
		if ($stmt->rowCount() == 0) {
			throw new Exception("The user with id '$id' could not be found.");
		}
		$user = $stmt->fetch(PDO::FETCH_ASSOC);

		$this->id = $user['id'];
		$this->username = $user['username'];
		$this->password = $user['password'];
	}

	//------------------------------------------------------------------------------
	// Getters and setters
	//------------------------------------------------------------------------------

	/**
	 * Get the ID of the user
	 *
	 * @return int                      The ID
	 */
	public function getId() {
		return $this->id;
	}

	/**
	 * Get the username of the user
	 *
	 * @return string The username
	 */
	public function getUsername() {
		return $this->username;
	}

	/**
	 * Set the username of the user
	 *
	 * @param string $username          The new username for the user
	 *
	 * @throws PDOException             If something went wrong with the database
	 *
	 * @return bool                     True on succes, false on failure
	 */
	public function setName($username) {
		$stmt = $this->pdo->prepare("UPDATE `".constants::db_prefix."user` SET `username`=? WHERE `id`=?");
		$stmt->execute(array($username, $this->id));
		if ($stmt->rowCount() == 1) {
			$this->username = $username;
			return true;
		} else {
			return false;
		}
	}

	/**
	 * Set the password of the user
	 *
	 * @param string $password          The new password for the user
	 *
	 * @throws PDOException             If something went wrong with the database
	 *
	 * @return bool                     True on succes, false on failure
	 */
	public function setPassword($password) {
		$password = self::hash($password);
		$stmt = $this->pdo->prepare("UPDATE `".constants::db_prefix."user` SET `password`=? WHERE `id`=?");
		$stmt->execute(array($password, $this->id));
		if ($stmt->rowCount() == 1) {
			$this->password = $password;
			return true;
		} else {
			return false;
		}
	}

	//------------------------------------------------------------------------------
	// Other functions
	//------------------------------------------------------------------------------

	/**
	 * Check if a user has administrator rights
	 *
	 * @return bool                     True iff the user has administrator rights
	 */
	public function isAdmin() {
		return in_array($this->getId(), constants::user_admins);
	}

	/**
	 * Verify a password
	 *
	 * @param string $password          The password to verify
	 *
	 * @return bool                     True iff the password can be accepted
	 */
	public function verifyPassword($password) {
		if (!password_verify($password, $this->password)) {
			return false;
		}
		if (password_needs_rehash($this->password, constants::password_algo,
				['cost' => constants::password_cost])) {
			$this->setPassword($password);
		}
		return true;
	}

	/**
	 * Remove this user from the database
	 *
	 * If this doesn't succeed (i.e. false is returned), that means the user was removed manually or by another instance of this class
	 *
	 * @throws PDOException             If something went wrong with the database
	 *
	 * @return bool                     True on success, false on failure
	 */
	public function delete() {
		$stmt = $this->pdo->prepare("DELETE FROM `".constants::db_prefix."user` WHERE `id`=?");
		$stmt->execute(array($this->id));
		if ($stmt->rowCount() != 1) {
			return false;
		} else {
			return true;
		}
	}
}