This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | /** |
||
4 | * Admin Class |
||
5 | * Admin Class inherits from User. |
||
6 | * |
||
7 | * @license http://opensource.org/licenses/MIT The MIT License (MIT) |
||
8 | * @author Omar El Gabry <[email protected]> |
||
9 | */ |
||
10 | |||
11 | class Admin extends User{ |
||
0 ignored issues
–
show
|
|||
12 | |||
13 | /** |
||
14 | * get all users in the database |
||
15 | * |
||
16 | * @access public |
||
17 | * @param string $name |
||
18 | * @param string $email |
||
19 | * @param string $role |
||
20 | * @param integer $pageNum |
||
21 | * @return array |
||
22 | * |
||
23 | */ |
||
24 | public function getUsers($name = null, $email = null, $role = null, $pageNum = 1){ |
||
25 | |||
26 | // validate user inputs |
||
27 | $validation = new Validation(); |
||
28 | View Code Duplication | if(!$validation->validate([ |
|
0 ignored issues
–
show
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. ![]() |
|||
29 | 'User Name' => [$name, 'alphaNumWithSpaces|maxLen(30)'], |
||
30 | 'Email' => [$email, 'email|maxLen(50)'], |
||
31 | 'Role' => [$role, 'inArray(admin, user)']])){ |
||
32 | $this->errors = $validation->errors(); |
||
33 | return false; |
||
34 | } |
||
35 | |||
36 | // in $options array, add all possible values from user, and their name parameters |
||
37 | // then applyOptions() method will see if value is not empty, then add it to our query |
||
38 | $options = [ |
||
39 | $name => "name LIKE :name ", |
||
40 | $email => "email = :email ", |
||
41 | $role => "role = :role " |
||
42 | ]; |
||
43 | |||
44 | // get options query |
||
45 | $options = $this->applyOptions($options, "AND "); |
||
46 | $options = empty($options)? "": "WHERE " . $options; |
||
47 | |||
48 | $values = []; |
||
49 | if (!empty($name)) $values[":name"] = "%". $name ."%"; |
||
50 | if (!empty($email)) $values[":email"] = $email; |
||
51 | if (!empty($role)) $values[":role"] = $role; |
||
52 | |||
53 | // get pagination object so that we can add offset and limit in our query |
||
54 | $pagination = Pagination::pagination("users", $options, $values, $pageNum); |
||
55 | $offset = $pagination->getOffset(); |
||
56 | $limit = $pagination->perPage; |
||
57 | |||
58 | $database = Database::openConnection(); |
||
59 | $query = "SELECT id, name, email, role, is_email_activated FROM users "; |
||
60 | $query .= $options; |
||
61 | $query .= "LIMIT $limit OFFSET $offset"; |
||
62 | |||
63 | $database->prepare($query); |
||
64 | $database->execute($values); |
||
65 | $users = $database->fetchAllAssociative(); |
||
66 | |||
67 | return array("users" => $users, "pagination" => $pagination); |
||
68 | } |
||
69 | |||
70 | /** |
||
71 | * Update info of a passed user id |
||
72 | * |
||
73 | * @access public |
||
74 | * @param integer $userId |
||
75 | * @param integer $adminId |
||
76 | * @param string $name |
||
77 | * @param string $password |
||
78 | * @param string $role |
||
79 | * @return bool |
||
80 | * @throws Exception If password couldn't be updated |
||
81 | * |
||
82 | */ |
||
83 | public function updateUserInfo($userId, $adminId, $name, $password, $role){ |
||
84 | |||
85 | $user = $this->getProfileInfo($userId); |
||
86 | |||
87 | $name = (!empty($name) && $name !== $user["name"])? $name: null; |
||
88 | $role = (!empty($role) && $role !== $user["role"])? $role: null; |
||
89 | |||
90 | // current admin can't change his role, |
||
91 | // changing the role requires to logout or reset session, |
||
92 | // because role is stored in the session |
||
93 | if(!empty($role) && $adminId === $user["id"]){ |
||
94 | $this->errors[] = "You can't change your role"; |
||
95 | return false; |
||
96 | } |
||
97 | |||
98 | $validation = new Validation(); |
||
99 | View Code Duplication | if(!$validation->validate([ |
|
0 ignored issues
–
show
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. ![]() |
|||
100 | "Name" => [$name, "alphaNumWithSpaces|minLen(4)|maxLen(30)"], |
||
101 | "Password" => [$password, "minLen(6)|password"], |
||
102 | 'Role' => [$role, "inArray(admin, user)"]])){ |
||
103 | $this->errors = $validation->errors(); |
||
104 | return false; |
||
105 | } |
||
106 | |||
107 | if($password || $name || $role) { |
||
0 ignored issues
–
show
The expression
$name of type string|null is loosely compared to true ; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.
In PHP, under loose comparison (like For '' == false // true
'' == null // true
'ab' == false // false
'ab' == null // false
// It is often better to use strict comparison
'' === false // false
'' === null // false
![]() The expression
$role of type string|null is loosely compared to true ; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.
In PHP, under loose comparison (like For '' == false // true
'' == null // true
'ab' == false // false
'ab' == null // false
// It is often better to use strict comparison
'' === false // false
'' === null // false
![]() |
|||
108 | |||
109 | $options = [ |
||
110 | $name => "name = :name ", |
||
111 | $password => "hashed_password = :hashed_password ", |
||
112 | $role => "role = :role " |
||
113 | ]; |
||
114 | |||
115 | $database = Database::openConnection(); |
||
116 | $query = "UPDATE users SET "; |
||
117 | $query .= $this->applyOptions($options, ", "); |
||
118 | $query .= "WHERE id = :id LIMIT 1 "; |
||
119 | $database->prepare($query); |
||
120 | |||
121 | if($name) { |
||
0 ignored issues
–
show
The expression
$name of type string|null is loosely compared to true ; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.
In PHP, under loose comparison (like For '' == false // true
'' == null // true
'ab' == false // false
'ab' == null // false
// It is often better to use strict comparison
'' === false // false
'' === null // false
![]() |
|||
122 | $database->bindValue(':name', $name); |
||
123 | } |
||
124 | View Code Duplication | if($password) { |
|
0 ignored issues
–
show
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. ![]() |
|||
125 | $database->bindValue(':hashed_password', password_hash($password, PASSWORD_DEFAULT, array('cost' => Config::get('HASH_COST_FACTOR')))); |
||
126 | } |
||
127 | if($role){ |
||
0 ignored issues
–
show
The expression
$role of type string|null is loosely compared to true ; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.
In PHP, under loose comparison (like For '' == false // true
'' == null // true
'ab' == false // false
'ab' == null // false
// It is often better to use strict comparison
'' === false // false
'' === null // false
![]() |
|||
128 | $database->bindValue(':role', $role); |
||
129 | } |
||
130 | |||
131 | $database->bindValue(':id', $userId); |
||
132 | $result = $database->execute(); |
||
133 | |||
134 | if(!$result){ |
||
135 | throw new Exception("Couldn't update profile"); |
||
136 | } |
||
137 | } |
||
138 | |||
139 | return true; |
||
140 | } |
||
141 | |||
142 | /** |
||
143 | * Delete a user. |
||
144 | * |
||
145 | * @param string $adminId |
||
146 | * @param integer $userId |
||
147 | * @throws Exception |
||
148 | */ |
||
149 | public function deleteUser($adminId, $userId){ |
||
150 | |||
151 | // current admin can't delete himself |
||
152 | $validation = new Validation(); |
||
153 | if(!$validation->validate([ 'User ID' => [$userId, "notEqual(".$adminId.")"]])) { |
||
154 | $this->errors = $validation->errors(); |
||
155 | return false; |
||
156 | } |
||
157 | |||
158 | $database = Database::openConnection(); |
||
159 | $database->deleteById("users", $userId); |
||
160 | |||
161 | if ($database->countRows() !== 1) { |
||
162 | throw new Exception ("Couldn't delete user"); |
||
163 | } |
||
164 | } |
||
165 | |||
166 | /** |
||
167 | * Counting the number of users in the database. |
||
168 | * |
||
169 | * @access public |
||
170 | * @static static method |
||
171 | * @return integer number of users |
||
172 | * |
||
173 | */ |
||
174 | public function countUsers(){ |
||
175 | return $this->countAll("users"); |
||
0 ignored issues
–
show
The call to
Admin::countAll() has too many arguments starting with 'users' .
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue. If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. In this case you can add the ![]() |
|||
176 | } |
||
177 | |||
178 | /** |
||
179 | * Get the backup file from the backup directory in file system |
||
180 | * |
||
181 | * @access public |
||
182 | * @return array |
||
183 | */ |
||
184 | public function getBackups() { |
||
185 | |||
186 | $files = scandir(APP . "backups/"); |
||
187 | $basename = $filename = $unixTimestamp = null; |
||
188 | |||
189 | foreach ($files as $file) { |
||
190 | if ($file != "." && $file != "..") { |
||
191 | |||
192 | $filename_array = explode('-', pathinfo($file, PATHINFO_FILENAME)); |
||
193 | if(count($filename_array) !== 2){ |
||
194 | continue; |
||
195 | } |
||
196 | |||
197 | // backup file has name with something like this: backup-1435788336 |
||
198 | list($filename, $unixTimestamp) = $filename_array; |
||
199 | $basename = $file; |
||
200 | break; |
||
201 | } |
||
202 | } |
||
203 | |||
204 | $data = array("basename" => $basename, "filename" => $filename, "date" => "On " . date("F j, Y", $unixTimestamp)); |
||
205 | return $data; |
||
206 | } |
||
207 | |||
208 | /** |
||
209 | * Update the backup file from the backup directory in file system |
||
210 | * The user of the database MUST be assigned privilege of ADMINISTRATION -> LOCK TABLES. |
||
211 | * |
||
212 | * @access public |
||
213 | * @return bool |
||
214 | */ |
||
215 | public function updateBackup(){ |
||
216 | |||
217 | $dir = APP . "backups/"; |
||
218 | $files = scandir($dir); |
||
219 | |||
220 | // delete and clean all current files in backup directory |
||
221 | foreach ($files as $file) { |
||
222 | if ($file != "." && $file != "..") { |
||
223 | if (is_file("$dir/$file")) { |
||
224 | Uploader::deleteFile("$dir/$file"); |
||
225 | } |
||
226 | } |
||
227 | } |
||
228 | |||
229 | // you can use another username and password only for this function, while the main user has limited privileges |
||
230 | $windows = true; |
||
231 | if($windows){ |
||
232 | exec('C:\wamp\bin\mysql\mysql5.6.17\bin\mysqldump --user=' . escapeshellcmd(Config::get('DB_USER')) . ' --password=' . escapeshellcmd(Config::get('DB_PASS')) . ' ' . escapeshellcmd(Config::get('DB_NAME')) . ' > '. APP.'backups\backup-' . time() . '.sql'); |
||
233 | View Code Duplication | }else{ |
|
0 ignored issues
–
show
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. ![]() |
|||
234 | exec('mysqldump --user=' . escapeshellcmd(Config::get('DB_USER')) . ' --password=' .escapeshellcmd(Config::get('DB_PASS')). ' '. escapeshellcmd(Config::get('DB_NAME')) .' > '. APP . 'backups/backup-' . time() . '.sql'); |
||
235 | } |
||
236 | |||
237 | return true; |
||
238 | } |
||
239 | |||
240 | /** |
||
241 | * Restore the backup file |
||
242 | * The user of the database MUST assigned all privileges of SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, INDEX, DROP, LOCK TABLES, & TRIGGER. |
||
243 | * |
||
244 | * @access public |
||
245 | * @return bool |
||
246 | * |
||
247 | */ |
||
248 | public function restoreBackup(){ |
||
249 | |||
250 | $basename = $this->getBackups()["basename"]; |
||
251 | |||
252 | $validation = new Validation(); |
||
253 | $validation->addRuleMessage("required", "Please update backups first!"); |
||
254 | |||
255 | if(!$validation->validate(["Backup" => [$basename, "required"]])) { |
||
256 | $this->errors = $validation->errors(); |
||
257 | return false; |
||
258 | } |
||
259 | |||
260 | $windows = true; |
||
261 | if($windows){ |
||
262 | exec('C:\wamp\bin\mysql\mysql5.6.17\bin\mysql --user=' . escapeshellcmd(Config::get('DB_USER')) . ' --password=' . escapeshellcmd(Config::get('DB_PASS')) . ' ' . escapeshellcmd(Config::get('DB_NAME')) . ' < '.APP.'\backups\\' . $basename); |
||
263 | View Code Duplication | }else{ |
|
0 ignored issues
–
show
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. ![]() |
|||
264 | exec('mysql --user='.escapeshellcmd(Config::get('DB_USER')).' --password='.escapeshellcmd(Config::get('DB_PASS')).' '.escapeshellcmd(Config::get('DB_NAME')).' < '. APP . 'backups/' . $basename); |
||
265 | } |
||
266 | |||
267 | return true; |
||
268 | } |
||
269 | |||
270 | /** |
||
271 | * get users data. |
||
272 | * Use this method to download users info in database as csv file. |
||
273 | * |
||
274 | * @access public |
||
275 | * @return array |
||
276 | */ |
||
277 | public function getUsersData(){ |
||
278 | |||
279 | $database = Database::openConnection(); |
||
280 | |||
281 | $database->prepare("SELECT name, role, email, is_email_activated FROM users"); |
||
282 | $database->execute(); |
||
283 | |||
284 | $users = $database->fetchAllAssociative(); |
||
285 | $cols = array("User Name", "Role", "Email", "is Email Activated?"); |
||
286 | |||
287 | return ["rows" => $users, "cols" => $cols, "filename" => "users"]; |
||
288 | } |
||
289 | |||
290 | } |
||
291 |
You can fix this by adding a namespace to your class:
When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.