andela-araimi /
Emoji-REST-API
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 | * @author: Raimi Ademola <[email protected]> |
||
| 5 | * @copyright: 2016 Andela |
||
| 6 | */ |
||
| 7 | namespace Demo; |
||
| 8 | |||
| 9 | |||
| 10 | use Exception; |
||
| 11 | use Carbon\Carbon; |
||
| 12 | use Firebase\JWT\JWT; |
||
| 13 | use Illuminate\Database\Capsule\Manager as Capsule; |
||
| 14 | use Psr\Http\Message\ResponseInterface as Response; |
||
| 15 | |||
| 16 | class EmojiController |
||
| 17 | { |
||
| 18 | public $authController; |
||
| 19 | |||
| 20 | /** |
||
| 21 | * This is a constructor; a default method that will be called automatically during class instantiation. |
||
| 22 | */ |
||
| 23 | public function __construct() |
||
| 24 | { |
||
| 25 | $this->authController = new AuthController(); |
||
| 26 | } |
||
| 27 | |||
| 28 | /** |
||
| 29 | * Get all emojis. |
||
| 30 | * |
||
| 31 | * @param Slim\Http\Request $request |
||
| 32 | * @param Slim\Http\Response $response |
||
| 33 | * @param array $args |
||
|
0 ignored issues
–
show
|
|||
| 34 | * |
||
| 35 | * @return Slim\Http\Response |
||
| 36 | */ |
||
| 37 | public function getAllEmojis($request, $response) |
||
|
0 ignored issues
–
show
|
|||
| 38 | { |
||
| 39 | $emojis = Emoji::all(); |
||
| 40 | |||
| 41 | if (!count($emojis) > 0) { |
||
| 42 | return $response->withJson(['message' => 'Oops, No Emoji to display'], 404); |
||
| 43 | } |
||
| 44 | |||
| 45 | $emojiArray = []; |
||
| 46 | |||
| 47 | foreach($emojis as $emoji) { |
||
| 48 | $emojiProperty = [ |
||
| 49 | 'id' => $emoji->id, |
||
| 50 | 'name' => $emoji->name, |
||
| 51 | 'chars' => $emoji->chars, |
||
| 52 | 'category' => $emoji->category, |
||
| 53 | 'created_by' => $emoji->created_by |
||
| 54 | ]; |
||
| 55 | |||
| 56 | $keywords = []; |
||
| 57 | |||
| 58 | foreach($emoji->keywords as $keyword) { |
||
| 59 | array_push($keywords, $keyword->name); |
||
| 60 | } |
||
| 61 | |||
| 62 | $emojiProperty['keywords'] = $keywords; |
||
| 63 | $emojiArray[] = $emojiProperty; |
||
| 64 | } |
||
| 65 | |||
| 66 | return $response->withJson($emojiArray); |
||
| 67 | } |
||
| 68 | |||
| 69 | /** |
||
| 70 | * Get a single emoji. |
||
| 71 | * |
||
| 72 | * @param Slim\Http\Request $request |
||
| 73 | * @param Slim\Http\Response $response |
||
| 74 | * @param array $args |
||
| 75 | * |
||
| 76 | * @return Slim\Http\Response |
||
| 77 | */ |
||
| 78 | public function getSingleEmoji($request, $response, $args) |
||
|
0 ignored issues
–
show
|
|||
| 79 | { |
||
| 80 | if (!is_numeric($args['id'])) { |
||
| 81 | return $response->withJson(['message' => 'The id supplied must be an integer.'], 401); |
||
| 82 | } |
||
| 83 | |||
| 84 | $emoji = Emoji::find($args['id']); |
||
| 85 | |||
| 86 | if (count($emoji) < 1) { |
||
| 87 | return $response->withJson(['message' => 'The requested Emoji is not found.'], 404); |
||
| 88 | } |
||
| 89 | |||
| 90 | $keywords = []; |
||
| 91 | |||
| 92 | foreach ($emoji->keywords as $keyword) { |
||
| 93 | array_push($keywords, $keyword->name); |
||
| 94 | } |
||
| 95 | |||
| 96 | $emoji = ['id'=> $emoji->id, 'name' => $emoji->name, 'chars' => $emoji->chars, 'category' => $emoji->category, 'created_by' => $emoji->created_by, 'keywords' => $keywords]; |
||
| 97 | |||
| 98 | return $response->withJson($emoji); |
||
| 99 | } |
||
| 100 | |||
| 101 | /** |
||
| 102 | * This method creates emoji and keywords associated with it. |
||
| 103 | * |
||
| 104 | * @param $request |
||
| 105 | * @param $response |
||
| 106 | * @param $requestParams |
||
| 107 | * |
||
| 108 | * @return json response |
||
| 109 | */ |
||
| 110 | public function CreateEmoji($request, $response, $requestParams) |
||
|
0 ignored issues
–
show
|
|||
| 111 | { |
||
| 112 | $requestParams = $request->getParsedBody(); |
||
| 113 | $validateUserData = $this->authController->validateUserData(['name', 'chars', 'category', 'keywords'], $requestParams); |
||
| 114 | |||
| 115 | if (is_array($validateUserData)) { |
||
| 116 | return $response->withJson($validateUserData, 400); |
||
| 117 | } |
||
| 118 | |||
| 119 | $validateEmptyInput = $this->checkEmptyInput($requestParams['name'], $requestParams['chars'], $requestParams['category'], $requestParams['keywords']); |
||
| 120 | |||
| 121 | if (is_array($validateEmptyInput)) { |
||
| 122 | return $response->withJson($validateEmptyInput, 401); |
||
| 123 | } |
||
| 124 | |||
| 125 | $validateEmojiDuplicate = $this->checkDuplicateEmoji($requestParams['name'], $requestParams['chars']); |
||
| 126 | |||
| 127 | if (is_array($validateEmojiDuplicate)) { |
||
| 128 | return $response->withJson($validateEmojiDuplicate, 400); |
||
| 129 | } |
||
| 130 | |||
| 131 | $emoji = Emoji::create([ |
||
| 132 | 'name' => strtolower($requestParams['name']), |
||
| 133 | 'chars' => $requestParams['chars'], |
||
| 134 | 'category' => $requestParams['category'], |
||
| 135 | 'created_at' => Carbon::now()->toDateTimeString(), |
||
| 136 | 'updated_at' => Carbon::now()->toDateTimeString(), |
||
| 137 | 'created_by' => $this->getUsername($request, $response), |
||
| 138 | ]); |
||
| 139 | |||
| 140 | $this->createEmojiKeywords($emoji->id, $requestParams['keywords']); |
||
|
0 ignored issues
–
show
The property
id does not exist on object<Demo\Emoji>. Since you implemented __get, maybe consider adding a @property annotation.
Since your code implements the magic getter <?php
/**
* @property int $x
* @property int $y
* @property string $text
*/
class MyLabel
{
private $properties;
private $allowedProperties = array('x', 'y', 'text');
public function __get($name)
{
if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
return $properties[$name];
} else {
return null;
}
}
public function __set($name, $value)
{
if (in_array($name, $this->allowedProperties)) {
$properties[$name] = $value;
} else {
throw new \LogicException("Property $name is not defined.");
}
}
}
If the property has read access only, you can use the @property-read annotation instead. Of course, you may also just have mistyped another name, in which case you should fix the error. See also the PhpDoc documentation for @property. Loading history...
|
|||
| 141 | |||
| 142 | return $response->withJson(['message' => 'Emoji has been created successfully'], 201); |
||
| 143 | } |
||
| 144 | |||
| 145 | /** |
||
| 146 | * This method updates an emoji by using Patch. |
||
| 147 | * |
||
| 148 | * @param $request |
||
| 149 | * @param $response |
||
| 150 | * @param $args |
||
| 151 | * |
||
| 152 | * @return json $response |
||
| 153 | */ |
||
| 154 | public function updateEmojiByPatch($request, $response, $args) |
||
| 155 | { |
||
| 156 | $updateParams = $request->getParsedBody(); |
||
| 157 | $validateUserData = $this->authController->validateUserData(['name'], $updateParams); |
||
| 158 | |||
| 159 | if (is_array($validateUserData)) { |
||
| 160 | return $response->withJson($validateUserData, 400); |
||
| 161 | } |
||
| 162 | |||
| 163 | $validateArgs = $this->validateArgs($request, $response, $args); |
||
| 164 | |||
| 165 | if (is_array($validateArgs)) { |
||
| 166 | return $response->withJson($validateArgs, 401); |
||
| 167 | } |
||
| 168 | |||
| 169 | Emoji::where('id', '=', $args['id']) |
||
| 170 | ->update(['name' => strtolower($updateParams['name']), 'updated_at' => Carbon::now()->toDateTimeString()]); |
||
| 171 | |||
| 172 | return $response->withJson(['message' => 'Emoji has been updated successfully'], 200); |
||
| 173 | } |
||
| 174 | |||
| 175 | /** |
||
| 176 | * This method updates an emoji by using put. |
||
| 177 | * |
||
| 178 | * @param $request |
||
| 179 | * @param $response |
||
| 180 | * @param $args |
||
| 181 | * |
||
| 182 | * @return json $response |
||
| 183 | */ |
||
| 184 | public function updateEmojiByPut($request, $response, $args) |
||
| 185 | { |
||
| 186 | $updateParams = $request->getParsedBody(); |
||
| 187 | $validateUserData = $this->authController->validateUserData(['name', 'chars', 'category'], $updateParams); |
||
| 188 | |||
| 189 | if (is_array($validateUserData)) { |
||
| 190 | return $response->withJson($validateUserData, 400); |
||
| 191 | } |
||
| 192 | |||
| 193 | $validateArgs = $this->validateArgs($request, $response, $args); |
||
| 194 | |||
| 195 | if (is_array($validateArgs)) { |
||
| 196 | return $response->withJson($validateArgs, 401); |
||
| 197 | } |
||
| 198 | |||
| 199 | Emoji::where('id', '=', $args['id']) |
||
| 200 | ->update(['name' => strtolower($updateParams['name']), 'chars' => $updateParams['chars'], 'category' => $updateParams['category'], 'updated_at' => Carbon::now()->toDateTimeString()]); |
||
| 201 | |||
| 202 | return $response->withJson(['message' => 'Emoji has been updated successfully'], 200); |
||
| 203 | } |
||
| 204 | |||
| 205 | /** |
||
| 206 | * This method deletes an emoji. |
||
| 207 | * |
||
| 208 | * @param Slim\Http\Request $request |
||
| 209 | * @param Slim\Http\Response $response |
||
| 210 | * @param array $args |
||
| 211 | * |
||
| 212 | * @return json response |
||
| 213 | */ |
||
| 214 | public function deleteEmoji($request, $response, $args) |
||
| 215 | { |
||
| 216 | $validateArgs = $this->validateArgs($request, $response, $args); |
||
| 217 | if (is_array($validateArgs)) { |
||
| 218 | return $response->withJson($validateArgs, 401); |
||
| 219 | } |
||
| 220 | |||
| 221 | Emoji::where('id', '=', $args['id'])->delete(); |
||
| 222 | |||
| 223 | return $response->withJson(['message' => 'Emoji successfully deleted.'], 200); |
||
| 224 | } |
||
| 225 | |||
| 226 | /** |
||
| 227 | * This method authenticate and returns user id. |
||
| 228 | * |
||
| 229 | * @param $response |
||
| 230 | * @param $request |
||
| 231 | * |
||
| 232 | * @return user id |
||
| 233 | */ |
||
| 234 | private function getUsername($request, $response) |
||
| 235 | { |
||
| 236 | $jwtoken = $request->getHeader('HTTP_AUTHORIZATION'); |
||
| 237 | |||
| 238 | try { |
||
| 239 | if (isset($jwtoken)) { |
||
| 240 | $appSecret = getenv('APP_SECRET'); |
||
| 241 | $jwt = $jwtoken[0]; |
||
| 242 | $decodedToken = JWT::decode($jwt, $appSecret, ['HS512']); |
||
| 243 | $tokenInfo = (array) $decodedToken; |
||
| 244 | $userInfo = (array) $tokenInfo['data']; |
||
| 245 | |||
| 246 | return $userInfo['username']; |
||
| 247 | } |
||
| 248 | } catch (Exception $e) { |
||
| 249 | return $response->withJson(['status: fail, msg: Unauthorized']); |
||
| 250 | } |
||
| 251 | } |
||
| 252 | |||
| 253 | /** |
||
| 254 | * This method solves for rightful owner of a record. |
||
| 255 | * |
||
| 256 | * @param $response |
||
| 257 | * @param $request |
||
| 258 | * @param $args |
||
| 259 | * |
||
| 260 | * @return user id |
||
| 261 | */ |
||
| 262 | private function getTheOwner($request, $response, $args) |
||
| 263 | { |
||
| 264 | return Capsule::table('emojis') |
||
| 265 | ->where('id', '=', $args['id']) |
||
| 266 | ->where('created_by', '=', $this->getUsername($request, $response)); |
||
| 267 | } |
||
| 268 | |||
| 269 | /** |
||
| 270 | * This method creates emoji keywords. |
||
| 271 | * |
||
| 272 | * @param $emoji_id |
||
| 273 | * @param $keywords |
||
| 274 | * |
||
| 275 | * @return keyword id |
||
| 276 | */ |
||
| 277 | public function createEmojiKeywords($emoji_id, $keywords) |
||
| 278 | { |
||
| 279 | if (isset($keywords)) { |
||
| 280 | $splittedKeywords = explode(',', $keywords); |
||
| 281 | $created_at = Carbon::now()->toDateTimeString(); |
||
| 282 | $updated_at = Carbon::now()->toDateTimeString(); |
||
| 283 | |||
| 284 | foreach ($splittedKeywords as $keyword) { |
||
| 285 | $emojiKeyword = Keyword::create([ |
||
| 286 | 'emoji_id' => $emoji_id, |
||
| 287 | 'name' => $keyword, |
||
| 288 | 'created_at' => $created_at, |
||
| 289 | 'updated_at' => $updated_at, |
||
| 290 | ]); |
||
| 291 | } |
||
| 292 | |||
| 293 | return $emojiKeyword->name; |
||
|
0 ignored issues
–
show
The property
name does not exist on object<Demo\Keyword>. Since you implemented __get, maybe consider adding a @property annotation.
Since your code implements the magic getter <?php
/**
* @property int $x
* @property int $y
* @property string $text
*/
class MyLabel
{
private $properties;
private $allowedProperties = array('x', 'y', 'text');
public function __get($name)
{
if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
return $properties[$name];
} else {
return null;
}
}
public function __set($name, $value)
{
if (in_array($name, $this->allowedProperties)) {
$properties[$name] = $value;
} else {
throw new \LogicException("Property $name is not defined.");
}
}
}
If the property has read access only, you can use the @property-read annotation instead. Of course, you may also just have mistyped another name, in which case you should fix the error. See also the PhpDoc documentation for @property. Loading history...
The variable
$emojiKeyword does not seem to be defined for all execution paths leading up to this point.
If you define a variable conditionally, it can happen that it is not defined for all execution paths. Let’s take a look at an example: function myFunction($a) {
switch ($a) {
case 'foo':
$x = 1;
break;
case 'bar':
$x = 2;
break;
}
// $x is potentially undefined here.
echo $x;
}
In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined. Available Fixes
Loading history...
|
|||
| 294 | } |
||
| 295 | |||
| 296 | return true; |
||
| 297 | } |
||
| 298 | |||
| 299 | /** |
||
| 300 | * This method checks for empty input from user. |
||
| 301 | * |
||
| 302 | * @param $inputName |
||
| 303 | * @param $inputChars |
||
| 304 | * @param $inputCategory |
||
| 305 | * @param $inputKeywords |
||
| 306 | * |
||
| 307 | * @return bool |
||
| 308 | */ |
||
| 309 | public function checkEmptyInput($inputName, $inputChars, $inputCategory, $inputKeywords) |
||
| 310 | { |
||
| 311 | if (empty($inputName) || empty($inputChars) || empty($inputCategory) || empty($inputKeywords)) { |
||
| 312 | return ['message' => 'All fields must be provided.']; |
||
| 313 | } |
||
| 314 | |||
| 315 | return true; |
||
| 316 | } |
||
| 317 | |||
| 318 | /** |
||
| 319 | * This method checks for duplicate emoji. |
||
| 320 | * |
||
| 321 | * @param $inputName |
||
| 322 | * @param $inputChars |
||
| 323 | * |
||
| 324 | * @return bool |
||
| 325 | */ |
||
| 326 | public function checkDuplicateEmoji($inputName, $inputChars) |
||
| 327 | { |
||
| 328 | $nameCheck = Capsule::table('emojis')->where('name', '=', strtolower($inputName))->get(); |
||
| 329 | $charsCheck = Capsule::table('emojis')->where('chars', '=', $inputChars)->get(); |
||
| 330 | |||
| 331 | if ($nameCheck || $charsCheck) { |
||
|
0 ignored issues
–
show
The expression
$nameCheck of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using Loading history...
The expression
$charsCheck of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using Loading history...
|
|||
| 332 | |||
| 333 | return ['message' => 'The emoji already exist in the database.']; |
||
| 334 | } |
||
| 335 | |||
| 336 | return true; |
||
| 337 | } |
||
| 338 | |||
| 339 | /** |
||
| 340 | * This method checks for empty input from user. |
||
| 341 | * |
||
| 342 | * @param $request |
||
| 343 | * @param $response |
||
| 344 | * @param $args |
||
| 345 | * |
||
| 346 | * @return bool |
||
| 347 | */ |
||
| 348 | public function validateArgs($request, $response, $args) |
||
| 349 | { |
||
| 350 | if (!is_numeric($args['id'])) { |
||
| 351 | return ['message' => 'The id supplied must be an integer.']; |
||
| 352 | } |
||
| 353 | |||
| 354 | $emoji = Emoji::find($args['id']); |
||
| 355 | |||
| 356 | if (count($emoji) < 1) { |
||
| 357 | return ['message' => 'Action cannot be performed because the id supplied must be an integer']; |
||
| 358 | } |
||
| 359 | |||
| 360 | if (is_null($this->getTheOwner($request, $response, $args)->first())) { |
||
|
0 ignored issues
–
show
The method
first does not exist on object<Demo\User>? Since you implemented __call, maybe consider adding a @method annotation.
If you implement This is often the case, when class ParentClass {
private $data = array();
public function __call($method, array $args) {
if (0 === strpos($method, 'get')) {
return $this->data[strtolower(substr($method, 3))];
}
throw new \LogicException(sprintf('Unsupported method: %s', $method));
}
}
/**
* If this class knows which fields exist, you can specify the methods here:
*
* @method string getName()
*/
class SomeClass extends ParentClass { }
Loading history...
|
|||
| 361 | return ['message' => 'Action cannot be performed because you are not the creator']; |
||
| 362 | } |
||
| 363 | |||
| 364 | return true; |
||
| 365 | } |
||
| 366 | } |
||
| 367 |
This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.
Consider the following example. The parameter
$italyis not defined by the methodfinale(...).The most likely cause is that the parameter was removed, but the annotation was not.