Example #1
0
 /**
  * Validates JSON data against a schema.
  *
  * The schema may be passed as file path or as object returned from
  * `json_decode($schemaFile)`.
  *
  * @param mixed              $data   The decoded JSON data
  * @param string|object|null $schema The schema file or object. If `null`,
  *                                   the validator will look for a `$schema`
  *                                   property
  *
  * @return string[] The errors found during validation. Returns an empty
  *                  array if no errors were found
  *
  * @throws InvalidSchemaException If the schema is invalid
  */
 public function validate($data, $schema = null)
 {
     if (null === $schema && isset($data->{'$schema'})) {
         $schema = $data->{'$schema'};
     }
     if (is_string($schema)) {
         $schema = $this->loadSchema($schema);
     } elseif (is_object($schema)) {
         $this->assertSchemaValid($schema);
     } else {
         throw new InvalidSchemaException(sprintf('The schema must be given as string, object or in the "$schema" ' . 'property of the JSON data. Got: %s', is_object($schema) ? get_class($schema) : gettype($schema)));
     }
     $this->validator->reset();
     try {
         $this->validator->check($data, $schema);
     } catch (InvalidArgumentException $e) {
         throw new InvalidSchemaException(sprintf('The schema is invalid: %s', $e->getMessage()), 0, $e);
     }
     $errors = array();
     if (!$this->validator->isValid()) {
         $errors = (array) $this->validator->getErrors();
         foreach ($errors as $key => $error) {
             $prefix = $error['property'] ? $error['property'] . ': ' : '';
             $errors[$key] = $prefix . $error['message'];
         }
     }
     return $errors;
 }
 /**
  * @param mixed $data
  * @param \stdClass $schema
  * @param string $location (possible values: query, path, body, headers)
  */
 protected function validate($data, $schema, $location)
 {
     $this->validator->check($data, $schema);
     if (!$this->validator->isValid()) {
         $violations = array_map(function ($error) use($location) {
             return new ConstraintViolation($error['property'], $error['message'], $error['constraint'], $location);
         }, $this->validator->getErrors());
         foreach ($violations as $violation) {
             $this->addViolation($violation);
         }
     }
     $this->validator->reset();
 }
Example #3
0
 /**
  * Validates JSON data against a schema.
  *
  * The schema may be passed as file path or as object returned from
  * `json_decode($schemaFile)`.
  *
  * @param mixed         $data   The decoded JSON data.
  * @param string|object $schema The schema file or object.
  *
  * @return string[] The errors found during validation. Returns an empty
  *                  array if no errors were found.
  *
  * @throws InvalidSchemaException If the schema is invalid.
  */
 public function validate($data, $schema)
 {
     if (is_string($schema)) {
         $schema = $this->loadSchema($schema);
     } else {
         $this->assertSchemaValid($schema);
     }
     $this->validator->reset();
     try {
         $this->validator->check($data, $schema);
     } catch (InvalidArgumentException $e) {
         throw new InvalidSchemaException(sprintf('The schema is invalid: %s', $e->getMessage()), 0, $e);
     }
     $errors = array();
     if (!$this->validator->isValid()) {
         $errors = (array) $this->validator->getErrors();
         foreach ($errors as $key => $error) {
             $prefix = $error['property'] ? $error['property'] . ': ' : '';
             $errors[$key] = $prefix . $error['message'];
         }
     }
     return $errors;
 }
Example #4
0
 /**
  * Handles all hooks.
  *
  * @param Request  $request HTTP request
  * @param Response $response HTTP response
  * @param array    $args URL args
  */
 public function handle(Request $request, Response $response, array $args)
 {
     $response->setHeader("content-type", "text/plain");
     $token = $request->getQueryVars()["token"] ?? "";
     if (!$token || !is_string($token)) {
         $response->setStatus(401);
         $response->send("Failure: No token was provided.");
         return;
     }
     // use @ so we don't have to check for invalid strings manually
     $token = (string) @hex2bin($token);
     $hook = (yield $this->hookRepository->get($args["id"]));
     if (!$hook) {
         $response->setStatus(404);
         $response->send("Failure: Hook does not exist.");
         return;
     }
     if (!hash_equals($hook->token, $token)) {
         $response->setStatus(403);
         $response->send("Failure: Provided token doesn't match.");
         return;
     }
     $name = $args["service"];
     if (!isset($this->services[$name])) {
         $response->setStatus(404);
         $response->send("Failure: Unknown service.");
         return;
     }
     $contentType = strtok($request->getHeader("content-type"), ";");
     $body = (yield $request->getBody());
     switch ($contentType) {
         case "application/json":
             $payload = json_decode($body);
             break;
         case "application/x-www-form-urlencoded":
             parse_str($body, $payload);
             $payload = json_decode(json_encode($payload));
             break;
         default:
             $response->setStatus(415);
             $response->send("Failure: Content-type not supported.");
             return;
     }
     $service = $this->services[$name];
     $headers = $request->getAllHeaders();
     $event = $service->getEventName($headers, $payload);
     if (!isset($this->schemas[$name][$event])) {
         $response->setStatus(400);
         $response->send("Failure: Event not supported.");
         return;
     }
     $schema = $this->schemas[$name][$event];
     $this->validator->reset();
     $this->validator->check($payload, $schema);
     if (!$this->validator->isValid()) {
         $errors = $this->validator->getErrors();
         $errors = array_reduce($errors, function (string $carry, array $item) : string {
             if ($item["property"]) {
                 return $carry . sprintf("\n%s: %s", $item["property"], $item["message"]);
             } else {
                 return $carry . "\n" . $item["message"];
             }
         }, "");
         $response->setStatus(400);
         $response->send("Failure: Payload validation failed." . $errors);
         return;
     }
     $message = $service->handle($headers, $payload);
     try {
         if ($message) {
             $req = (new HttpRequest())->setMethod("PUT")->setUri($this->config["api"] . "/messages")->setHeader("authorization", "Basic " . base64_encode("{$this->config['user_id']}:{$this->config['token']}"))->setBody(json_encode(["room_id" => $hook->room_id, "text" => $message->getText(), "data" => $message->getData()]));
             $resp = (yield $this->http->request($req));
             if (intval($resp->getStatus() / 100) !== 2) {
                 $message = "API request failed: " . $resp->getStatus();
                 if ($resp->getBody()) {
                     $message .= "\n" . $resp->getBody();
                 }
                 throw new Exception($message);
             }
         }
         $response->send("Success: " . ($message ? "Message sent." : "Message skipped."));
     } catch (Exception $e) {
         $response->setStatus(500);
         $response->send("Failure: Couldn't persist message.");
     }
 }