BurningFlipside /
CommonCode
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | namespace Flipside\Auth; |
||
| 3 | |||
| 4 | class SQLAuthenticator extends Authenticator |
||
| 5 | { |
||
| 6 | public $dataSet = null; |
||
| 7 | public $pendingDataSet = null; |
||
| 8 | private $dataTables = array(); |
||
| 9 | private $params; |
||
| 10 | |||
| 11 | public function __construct($params) |
||
| 12 | { |
||
| 13 | parent::__construct($params); |
||
| 14 | $this->params = $params; |
||
| 15 | if($this->current) |
||
| 16 | { |
||
| 17 | $this->dataSet = $this->getCurrentDataSet(); |
||
| 18 | } |
||
| 19 | if($this->pending) |
||
| 20 | { |
||
| 21 | $this->pendingDataSet = $this->getPendingDataSet(); |
||
| 22 | } |
||
| 23 | } |
||
| 24 | |||
| 25 | /** |
||
| 26 | * @SuppressWarnings("StaticAccess") |
||
| 27 | */ |
||
| 28 | private function getCurrentDataSet() |
||
| 29 | { |
||
| 30 | if(isset($this->params['current_data_set'])) |
||
| 31 | { |
||
| 32 | return \Flipside\DataSetFactory::getDataSetByName($this->params['current_data_set']); |
||
| 33 | } |
||
| 34 | return \Flipside\DataSetFactory::getDataSetByName('authentication'); |
||
| 35 | } |
||
| 36 | |||
| 37 | /** |
||
| 38 | * @SuppressWarnings("StaticAccess") |
||
| 39 | */ |
||
| 40 | private function getPendingDataSet() |
||
| 41 | { |
||
| 42 | if(isset($this->params['pending_data_set'])) |
||
| 43 | { |
||
| 44 | return \Flipside\DataSetFactory::getDataSetByName($this->params['pending_data_set']); |
||
| 45 | } |
||
| 46 | return \Flipside\DataSetFactory::getDataSetByName('pending_authentication'); |
||
| 47 | } |
||
| 48 | |||
| 49 | private function getDataTable($name, $pending = false) |
||
| 50 | { |
||
| 51 | if(isset($this->dataTables[$name]) && isset($this->dataTables[$name][$pending])) |
||
| 52 | { |
||
| 53 | return $this->dataTables[$name][$pending]; |
||
| 54 | } |
||
| 55 | $dataSet = $this->dataSet; |
||
| 56 | if($pending) |
||
| 57 | { |
||
| 58 | $dataSet = $this->pendingDataSet; |
||
| 59 | } |
||
| 60 | if($dataSet === null) |
||
| 61 | { |
||
| 62 | throw new \Exception('Unable to obtain dataset for SQL Authentication!'); |
||
| 63 | } |
||
| 64 | $dataTable = $dataSet[$name]; |
||
| 65 | if(!isset($this->dataTables[$name])) |
||
| 66 | { |
||
| 67 | $this->dataTables[$name] = array(); |
||
| 68 | } |
||
| 69 | $this->dataTables[$name][$pending] = $dataTable; |
||
| 70 | return $dataTable; |
||
| 71 | } |
||
| 72 | |||
| 73 | /** |
||
| 74 | * Get the data table for Pending Users |
||
| 75 | * |
||
| 76 | * @return boolean|\Data\DataTable The Pending User Data Table |
||
| 77 | */ |
||
| 78 | private function getPendingUserDataTable() |
||
| 79 | { |
||
| 80 | if(isset($this->params['pending_user_table'])) |
||
| 81 | { |
||
| 82 | return $this->getDataTable($this->params['pending_user_table'], true); |
||
| 83 | } |
||
| 84 | return $this->getDataTable('users', true); |
||
| 85 | } |
||
| 86 | |||
| 87 | public function login($username, $password) |
||
| 88 | { |
||
| 89 | if($this->current === false) |
||
| 90 | { |
||
| 91 | return false; |
||
| 92 | } |
||
| 93 | $userDataTable = $this->getDataTable('user'); |
||
| 94 | $filter = new \Flipside\Data\Filter("uid eq '$username'"); |
||
| 95 | $users = $userDataTable->read($filter); |
||
| 96 | if($users === false || !isset($users[0])) |
||
| 97 | { |
||
| 98 | return false; |
||
| 99 | } |
||
| 100 | if(password_verify($password, $users[0]['pass'])) |
||
| 101 | { |
||
| 102 | return array('res'=>true, 'extended'=>$users[0]); |
||
| 103 | } |
||
| 104 | return false; |
||
| 105 | } |
||
| 106 | |||
| 107 | public function isLoggedIn($data) |
||
| 108 | { |
||
| 109 | if(isset($data['res'])) |
||
| 110 | { |
||
| 111 | return $data['res']; |
||
| 112 | } |
||
| 113 | return false; |
||
| 114 | } |
||
| 115 | |||
| 116 | public function getUser($data) |
||
| 117 | { |
||
| 118 | if(isset($this->params['current_data_set'])) |
||
| 119 | { |
||
| 120 | $data['current_data_set'] = $this->params['current_data_set']; |
||
| 121 | } |
||
| 122 | return new SQLUser($data, $this); |
||
|
0 ignored issues
–
show
The return type of
return new \Flipside\Auth\SQLUser($data, $this); (Flipside\Auth\SQLUser) is incompatible with the return type of the parent method Flipside\Auth\Authenticator::getUser of type null|Auth\User.
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design. Let’s take a look at an example: class Author {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
abstract class Post {
public function getAuthor() {
return 'Johannes';
}
}
class BlogPost extends Post {
public function getAuthor() {
return new Author('Johannes');
}
}
class ForumPost extends Post { /* ... */ }
function my_function(Post $post) {
echo strtoupper($post->getAuthor());
}
Our function Loading history...
|
|||
| 123 | } |
||
| 124 | |||
| 125 | /** |
||
| 126 | * Get the specified entity from the specified database table |
||
| 127 | * |
||
| 128 | * @param string $tableName The name of the table to obtain data from |
||
| 129 | * @param string $filterStr The filter string to use to obtain the data |
||
| 130 | * @param string $className The class name to pass the data to |
||
| 131 | * |
||
| 132 | * @return stdClass The data as an object or null if not found |
||
| 133 | */ |
||
| 134 | private function getEntityByFilter($tableName, $filterStr, $className) |
||
| 135 | { |
||
| 136 | $dataTable = $this->getDataTable($tableName); |
||
| 137 | $filter = new \Flipside\Data\Filter($filterStr); |
||
| 138 | $entities = $dataTable->read($filter); |
||
| 139 | if(empty($entities)) |
||
| 140 | { |
||
| 141 | return null; |
||
| 142 | } |
||
| 143 | return new $className($entities[0], $this); |
||
| 144 | } |
||
| 145 | |||
| 146 | public function getGroupByName($name) |
||
| 147 | { |
||
| 148 | return $this->getEntityByFilter('group', "gid eq '$name'", '\Flipside\Auth\SQLGroup'); |
||
|
0 ignored issues
–
show
The expression
$this->getEntityByFilter...side\\Auth\\SQLGroup'); of type Flipside\Auth\stdClass|null adds the type Flipside\Auth\stdClass to the return on line 148 which is incompatible with the return type of the parent method Flipside\Auth\Authenticator::getGroupByName of type null|Auth\Group.
Loading history...
|
|||
| 149 | } |
||
| 150 | |||
| 151 | public function getUserByName($name) |
||
| 152 | { |
||
| 153 | return $this->getEntityByFilter('user', "uid eq '$name'", '\Flipside\Auth\SQLUser'); |
||
|
0 ignored issues
–
show
The expression
$this->getEntityByFilter...pside\\Auth\\SQLUser'); of type Flipside\Auth\stdClass|null adds the type Flipside\Auth\stdClass to the return on line 153 which is incompatible with the return type of the parent method Flipside\Auth\Authenticator::getUserByName of type Flipside\Auth\Auth\User|null.
Loading history...
|
|||
| 154 | } |
||
| 155 | |||
| 156 | /** |
||
| 157 | * Get the specified entities from the specified database table |
||
| 158 | * |
||
| 159 | * @param string $dataTableName The name of the table to obtain data from |
||
| 160 | * @param boolean|\Data\Filter $filter The filter to use while searching the table |
||
| 161 | * @param boolean|array $select The array of properties to read |
||
| 162 | * @param boolean|integer $top The number of records to read |
||
| 163 | * @param boolean|integer $skip The number of records to skip |
||
| 164 | * @param boolean|array $orderby The properties to sort on |
||
| 165 | * |
||
| 166 | * @return array The SQL data returned by the filter |
||
| 167 | */ |
||
| 168 | private function getDataByFilter($dataTableName, $filter, $select, $top, $skip, $orderby) |
||
| 169 | { |
||
| 170 | $dataTable = $this->getDataTable($dataTableName); |
||
| 171 | return $dataTable->read($filter, $select, $top, $skip, $orderby); |
||
| 172 | } |
||
| 173 | |||
| 174 | /** |
||
| 175 | * @param string $dataTableName The Data Table to serach |
||
| 176 | * @param string $className The class to obtain data in |
||
| 177 | * @param boolean|array $select The fields to read |
||
| 178 | * @param boolean|integer $top The number of entities to read |
||
| 179 | * @param boolean|integer $skip The number of entities to skip |
||
| 180 | * @param boolean|array $orderby The fields to sort by |
||
| 181 | */ |
||
| 182 | private function convertDataToClass($dataTableName, $className, $filter, $select, $top, $skip, $orderby) |
||
| 183 | { |
||
| 184 | $data = $this->getDataByFilter($dataTableName, $filter, $select, $top, $skip, $orderby); |
||
| 185 | if($data === false) |
||
| 186 | { |
||
| 187 | return false; |
||
| 188 | } |
||
| 189 | $count = count($data); |
||
| 190 | for($i = 0; $i < $count; $i++) |
||
| 191 | { |
||
| 192 | $data[$i] = new $className($data[$i], $this); |
||
| 193 | } |
||
| 194 | return $data; |
||
| 195 | } |
||
| 196 | |||
| 197 | /** |
||
| 198 | * @param boolean|array $select The fields to read |
||
| 199 | * @param boolean|integer $top The number of entities to read |
||
| 200 | * @param boolean|integer $skip The number of entities to skip |
||
| 201 | * @param boolean|array $orderby The fields to sort by |
||
| 202 | */ |
||
| 203 | public function getGroupsByFilter($filter, $select = false, $top = false, $skip = false, $orderby = false) |
||
| 204 | { |
||
| 205 | return $this->convertDataToClass('group', 'Flipside\Auth\SQLGroup', $filter, $select, $top, $skip, $orderby); |
||
|
0 ignored issues
–
show
|
|||
| 206 | } |
||
| 207 | |||
| 208 | /** |
||
| 209 | * @param boolean|array $select The fields to read |
||
| 210 | * @param boolean|integer $top The number of entities to read |
||
| 211 | * @param boolean|integer $skip The number of entities to skip |
||
| 212 | * @param boolean|array $orderby The fields to sort by |
||
| 213 | */ |
||
| 214 | public function getUsersByFilter($filter, $select = false, $top = false, $skip = false, $orderby = false) |
||
| 215 | { |
||
| 216 | return $this->convertDataToClass('user', 'Flipside\Auth\SQLUser', $filter, $select, $top, $skip, $orderby); |
||
|
0 ignored issues
–
show
|
|||
| 217 | } |
||
| 218 | |||
| 219 | public function getPendingUserCount() |
||
| 220 | { |
||
| 221 | if($this->pending === false) |
||
| 222 | { |
||
| 223 | return 0; |
||
| 224 | } |
||
| 225 | $dataTable = $this->getPendingUserDataTable(); |
||
| 226 | if($dataTable === null) |
||
| 227 | { |
||
| 228 | return 0; |
||
| 229 | } |
||
| 230 | return $dataTable->count(); |
||
| 231 | } |
||
| 232 | |||
| 233 | /** |
||
| 234 | * Search all the pending users |
||
| 235 | * |
||
| 236 | * @param boolean|\Data\Filter $filter The filter to use while searching the table |
||
| 237 | * @param boolean|array $select The array of properties to read |
||
| 238 | * @param boolean|integer $top The number of records to read |
||
| 239 | * @param boolean|integer $skip The number of records to skip |
||
| 240 | * @param boolean|array $orderby The properties to sort on |
||
| 241 | * |
||
| 242 | * @return array The SQL data returned by the filter |
||
| 243 | */ |
||
| 244 | private function searchPendingUsers($filter, $select, $top, $skip, $orderby) |
||
| 245 | { |
||
| 246 | $userDataTable = $this->getPendingUserDataTable(); |
||
| 247 | $clause = $filter->getClause('time'); |
||
| 248 | $fieldData = false; |
||
| 249 | if($clause === false) |
||
| 250 | { |
||
| 251 | $fieldData = $filter->to_mongo_filter(); |
||
| 252 | $filter = new \Flipside\Data\Filter('substringof(data,"'.implode($fieldData, ' ').'")'); |
||
| 253 | } |
||
| 254 | $users = $userDataTable->read($filter, $select, $top, $skip, $orderby); |
||
| 255 | if($users === false) |
||
| 256 | { |
||
| 257 | return false; |
||
| 258 | } |
||
| 259 | $ret = array(); |
||
| 260 | $count = count($users); |
||
| 261 | for($i = 0; $i < $count; $i++) |
||
| 262 | { |
||
| 263 | $user = new SQLPendingUser($users[$i], $userDataTable); |
||
| 264 | $err = false; |
||
| 265 | if($fieldData !== false) |
||
| 266 | { |
||
| 267 | foreach($fieldData as $field=>$data) |
||
| 268 | { |
||
| 269 | if(strcasecmp($user[$field], $data) !== 0) |
||
| 270 | { |
||
| 271 | $err = true; break; |
||
| 272 | } |
||
| 273 | } |
||
| 274 | } |
||
| 275 | if(!$err) |
||
| 276 | { |
||
| 277 | array_push($ret, $user); |
||
| 278 | } |
||
| 279 | } |
||
| 280 | return $ret; |
||
| 281 | } |
||
| 282 | |||
| 283 | /** |
||
| 284 | * @param \Data\Filter $filter The filter to read with |
||
| 285 | * @param boolean|array $select The fields to read |
||
| 286 | * @param boolean|integer $top The number of entities to read |
||
| 287 | * @param boolean|integer $skip The number of entities to skip |
||
| 288 | * @param boolean|array $orderby The fields to sort by |
||
| 289 | */ |
||
| 290 | public function getPendingUsersByFilter($filter, $select = false, $top = false, $skip = false, $orderby = false) |
||
| 291 | { |
||
| 292 | if($this->pending === false) |
||
| 293 | { |
||
| 294 | return false; |
||
| 295 | } |
||
| 296 | if($filter !== false && !$filter->contains('hash')) |
||
| 297 | { |
||
| 298 | return $this->searchPendingUsers($filter, $select, $top, $skip, $orderby); |
||
|
0 ignored issues
–
show
|
|||
| 299 | } |
||
| 300 | $userDataTable = $this->getPendingUserDataTable(); |
||
| 301 | $users = $userDataTable->read($filter, $select, $top, $skip, $orderby); |
||
| 302 | if($users === false) |
||
| 303 | { |
||
| 304 | return false; |
||
| 305 | } |
||
| 306 | $count = count($users); |
||
| 307 | for($i = 0; $i < $count; $i++) |
||
| 308 | { |
||
| 309 | $users[$i] = new SQLPendingUser($users[$i], $userDataTable); |
||
| 310 | } |
||
| 311 | return $users; |
||
| 312 | } |
||
| 313 | |||
| 314 | public function createPendingUser($user) |
||
| 315 | { |
||
| 316 | if($this->pending === false) |
||
| 317 | { |
||
| 318 | return false; |
||
| 319 | } |
||
| 320 | $userDataTable = $this->getPendingUserDataTable(); |
||
| 321 | if(isset($user->password2)) |
||
| 322 | { |
||
| 323 | unset($user->password2); |
||
| 324 | } |
||
| 325 | $json = json_encode($user); |
||
| 326 | $hash = hash('sha512', $json); |
||
| 327 | $array = array('hash'=>$hash, 'data'=>$json); |
||
| 328 | $ret = $userDataTable->create($array); |
||
| 329 | if($ret !== false) |
||
| 330 | { |
||
| 331 | $users = $this->getPendingUsersByFilter(new \Data\Filter("hash eq '$hash'")); |
||
| 332 | if($users === false || !isset($users[0])) |
||
| 333 | { |
||
| 334 | throw new \Exception('Error retreiving user object after successful create!'); |
||
| 335 | } |
||
| 336 | $users[0]->sendEmail(); |
||
| 337 | } |
||
| 338 | return $ret; |
||
| 339 | } |
||
| 340 | |||
| 341 | public function getTempUserByHash($hash) |
||
| 342 | { |
||
| 343 | $users = $this->getPendingUsersByFilter(new \Data\Filter("hash eq '$hash'")); |
||
| 344 | if($users === false || !isset($users[0])) |
||
| 345 | { |
||
| 346 | return false; |
||
| 347 | } |
||
| 348 | return $users[0]; |
||
| 349 | } |
||
| 350 | } |
||
| 351 | /* vim: set tabstop=4 shiftwidth=4 expandtab: */ |
||
| 352 |
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: