diff --git a/application/classes/Controller/Api/Apikeys.php b/application/classes/Controller/Api/Apikeys.php deleted file mode 100644 index 75c4047b60..0000000000 --- a/application/classes/Controller/Api/Apikeys.php +++ /dev/null @@ -1,18 +0,0 @@ - - * @package Ushahidi\Application\Controllers - * @copyright 2013 Ushahidi - * @license https://www.gnu.org/licenses/agpl-3.0.html GNU Affero General Public License Version 3 (AGPL3) - */ - -class Controller_Api_ApiKeys extends Ushahidi_Rest { - - protected function _scope() - { - return 'apikeys'; - } -} diff --git a/application/classes/Controller/Api/Webhooks/Posts.php b/application/classes/Controller/Api/Webhooks/Posts.php deleted file mode 100644 index 66f9f369a8..0000000000 --- a/application/classes/Controller/Api/Webhooks/Posts.php +++ /dev/null @@ -1,67 +0,0 @@ - - * @package Ushahidi\Application\Controllers - * @copyright 2013 Ushahidi - * @license https://www.gnu.org/licenses/agpl-3.0.html GNU Affero General Public License Version 3 (AGPL3) - */ - -use Ushahidi\Core\Tool\Signer; - -class Controller_Api_Webhooks_Posts extends Controller_Api_Posts { - - protected function _is_auth_required() - { - return false; - } - - public function checkApiKey($data) - { - - if (isset($data['api_key'])) { - // Get api key and compare - return service('repository.apikey')->apiKeyExists($data['api_key']); - } - - return false; - } - - public function checkSignature($data) - { - $signature = $this->request->headers('X-Ushahidi-Signature'); - - if (isset($data['webhook_uuid']) && $signature) { - - // Get webhook and validate signature - $webhook = service('repository.webhook')->getByUUID($data['webhook_uuid']); - $signer = new Signer($webhook->shared_secret); - $fullURL = URL::site(Request::detect_uri(), TRUE) . URL::query(); - - return $signer->validate($signature, $fullURL, $data); - } - return false; - } - - public function before() - { - parent::before(); - - $post = $this->_request_payload; - - if (!$this->checkApiKey($post) || !$this->checkSignature($post)) - { - throw HTTP_Exception::factory(403, 'Forbidden'); - } - } - - public function action_put_index() - { - $this->_usecase = service('factory.usecase') - ->get($this->_resource(), 'webhook-update') - ->setIdentifiers($this->_identifiers()) - ->setPayload($this->_payload()); - } -} diff --git a/application/classes/Ushahidi/Console/Webhook.php b/application/classes/Ushahidi/Console/Webhook.php index 98a6678d63..9386ff2e30 100644 --- a/application/classes/Ushahidi/Console/Webhook.php +++ b/application/classes/Ushahidi/Console/Webhook.php @@ -105,46 +105,27 @@ protected function executeSend(InputInterface $input, OutputInterface $output) private function generateRequest($webhook_request) { // Delete queued webhook request - $this->webhookJobRepository->delete($webhook_request); + //$this->webhookJobRepository->delete($webhook_request); // Get post data $post = $this->postRepository->get($webhook_request->post_id); + $json = json_encode($post->asArray()); // Get webhook data - $webhooks = $this->webhookRepository->getAllByEventType($webhook_request->event_type); + $webhook = $this->webhookRepository->getByEventType($webhook_request->event_type); - foreach ($webhooks as $webhook) { + $this->signer = new Signer($webhook->shared_secret); - if ($post->form_id == $webhook['form_id']) { - $this->signer = new Signer($webhook['shared_secret']); + $signature = $this->signer->sign($webhook->url, $json); - $data = $post->asArray(); - - // Attach Webhook Uuid so that service can subsequently identify itself - // when sending data to the Platform - $data['webhook_uuid'] = $webhook['webhook_uuid']; - - // If set append the source and destination fields to the request - // These fields identify the UUIDs of the Post fields which the remot service should - // treat as the source of data and the destination for any data to be posted back to the Platform - $data['source_field_key'] = $webhook['source_field_key'] ?: null; - $data['destination_field_key'] = $webhook['destination_field_key'] ?: null; - - $json = json_encode($data); - $signature = $this->signer->sign($webhook['url'], $json); - - // This is an asynchronous request, we don't expect a result - // this can be extended to allow for handling of the returned promise - //TODO: HANDLE HTTP ERRORS - $promise = $this->client->request('POST', $webhook['url'], [ - 'headers' => [ - 'X-Ushahidi-Signature' => $signature, - 'Accept' => 'application/json' - ], - 'json' => $data - ]); - - } - } + // This is an asynchronous request, we don't expect a result + // this can be extended to allow for handling of the returned promise + $promise = $this->client->request('POST', $webhook->url, [ + 'headers' => [ + 'X-Platform-Signature' => $signature, + 'Accept' => 'application/json' + ], + 'json' => $post->asArray() + ]); } } diff --git a/application/classes/Ushahidi/Core.php b/application/classes/Ushahidi/Core.php index 2cdb753a06..a6bec75b92 100644 --- a/application/classes/Ushahidi/Core.php +++ b/application/classes/Ushahidi/Core.php @@ -248,7 +248,6 @@ public static function init() ]; $di->params['Ushahidi\Factory\ValidatorFactory']['map']['posts'] = [ 'create' => $di->lazyNew('Ushahidi_Validator_Post_Create'), - 'webhook-update' => $di->lazyNew('Ushahidi_Validator_Post_Update'), 'update' => $di->lazyNew('Ushahidi_Validator_Post_Update'), 'import' => $di->lazyNew('Ushahidi_Validator_Post_Import'), ]; @@ -288,10 +287,6 @@ public static function init() 'create' => $di->lazyNew('Ushahidi_Validator_Notification_Create'), 'update' => $di->lazyNew('Ushahidi_Validator_Notification_Update'), ]; - $di->params['Ushahidi\Factory\ValidatorFactory']['map']['apikeys'] = [ - 'create' => $di->lazyNew('Ushahidi_Validator_ApiKey_Create'), - 'update' => $di->lazyNew('Ushahidi_Validator_ApiKey_Update'), - ]; $di->params['Ushahidi\Factory\ValidatorFactory']['map']['webhooks'] = [ 'create' => $di->lazyNew('Ushahidi_Validator_Webhook_Create'), 'update' => $di->lazyNew('Ushahidi_Validator_Webhook_Update'), @@ -344,8 +339,7 @@ public static function init() 'savedsearches_posts' => $di->lazyNew('Ushahidi_Formatter_Post'), 'users' => $di->lazyNew('Ushahidi_Formatter_User'), 'notifications' => $di->lazyNew('Ushahidi_Formatter_Notification'), - 'webhooks' => $di->lazyNew('Ushahidi_Formatter_Webhook'), - 'apikeys' => $di->lazyNew('Ushahidi_Formatter_Apikey'), + 'webhooks' => $di->lazyNew('Ushahidi_Formatter_Webhook'), 'contacts' => $di->lazyNew('Ushahidi_Formatter_Contact'), 'csv' => $di->lazyNew('Ushahidi_Formatter_CSV'), 'roles' => $di->lazyNew('Ushahidi_Formatter_Role'), @@ -374,7 +368,6 @@ public static function init() 'set_post', 'notification', 'webhook', - 'apikey', 'contact', 'role', 'permission', @@ -443,7 +436,6 @@ public static function init() $di->set('repository.role', $di->lazyNew('Ushahidi_Repository_Role')); $di->set('repository.notification', $di->lazyNew('Ushahidi_Repository_Notification')); $di->set('repository.webhook', $di->lazyNew('Ushahidi_Repository_Webhook')); - $di->set('repository.apikey', $di->lazyNew('Ushahidi_Repository_ApiKey')); $di->set('repository.csv', $di->lazyNew('Ushahidi_Repository_CSV')); $di->set('repository.notification.queue', $di->lazyNew('Ushahidi_Repository_Notification_Queue')); $di->set('repository.webhook.job', $di->lazyNew('Ushahidi_Repository_Webhook_Job')); diff --git a/application/classes/Ushahidi/DataProvider.php b/application/classes/Ushahidi/DataProvider.php index b77a137bbd..a30d73a11a 100644 --- a/application/classes/Ushahidi/DataProvider.php +++ b/application/classes/Ushahidi/DataProvider.php @@ -35,7 +35,7 @@ public function send($to, $message, $title = "") * @param string data_provider_message_id Message ID * @return void */ - public function receive($type, $from, $message, $to = NULL, $title = NULL, $date = NULL, $data_provider_message_id = NULL, Array $additional_data = NULL) + public function receive($type, $from, $message, $to = NULL, $title = NULL, $data_provider_message_id = NULL, Array $additional_data = NULL) { $data_provider = $this->provider_name(); $contact_type = $this->contact_type; @@ -43,7 +43,7 @@ public function receive($type, $from, $message, $to = NULL, $title = NULL, $date $usecase = service('factory.usecase')->get('messages', 'receive'); try { - $usecase->setPayload(compact(['type', 'from', 'message', 'to', 'title', 'date', 'data_provider_message_id', 'data_provider', 'contact_type', 'additional_data'])) + $usecase->setPayload(compact(['type', 'from', 'message', 'to', 'title', 'data_provider_message_id', 'data_provider', 'contact_type', 'additional_data'])) ->interact(); } catch (Ushahidi\Core\Exception\NotFoundException $e) diff --git a/application/classes/Ushahidi/Formatter/Apikey.php b/application/classes/Ushahidi/Formatter/Apikey.php deleted file mode 100644 index 6d1d35c31a..0000000000 --- a/application/classes/Ushahidi/Formatter/Apikey.php +++ /dev/null @@ -1,17 +0,0 @@ - - * @package Ushahidi\Application - * @copyright 2014 Ushahidi - * @license https://www.gnu.org/licenses/agpl-3.0.html GNU Affero General Public License Version 3 (AGPL3) - */ - -use Ushahidi\Core\Traits\FormatterAuthorizerMetadata; - -class Ushahidi_Formatter_Apikey extends Ushahidi_Formatter_API -{ - use FormatterAuthorizerMetadata; -} diff --git a/application/classes/Ushahidi/Repository/ApiKey.php b/application/classes/Ushahidi/Repository/ApiKey.php deleted file mode 100644 index 1e77413ea6..0000000000 --- a/application/classes/Ushahidi/Repository/ApiKey.php +++ /dev/null @@ -1,88 +0,0 @@ - - * @package Ushahidi\Application - * @copyright 2014 Ushahidi - * @license https://www.gnu.org/licenses/agpl-3.0.html GNU Affero General Public License Version 3 (AGPL3) - */ - -use Ushahidi\Core\Entity; -use Ushahidi\Core\SearchData; -use Ushahidi\Core\Entity\ApiKey; -use Ushahidi\Core\Entity\ApiKeyRepository; -use Ushahidi\Core\Traits\AdminAccess; - -use Ramsey\Uuid\Uuid; -use Ramsey\Uuid\Exception\UnsatisfiedDependencyException; - -class Ushahidi_Repository_ApiKey extends Ushahidi_Repository implements ApiKeyRepository -{ - use AdminAccess; - - protected function getTable() - { - return 'apikeys'; - } - - public function getEntity(Array $data = null) - { - return new ApiKey($data); - } - - // Ushahidi_Repository - public function setSearchConditions(SearchData $search) - { - $query = $this->search_query; - - return $query; - } - - // CreateRepository - public function create(Entity $entity) - { - - $record = $entity->asArray(); - try { - $uuid = Uuid::uuid4(); - $record['api_key'] = $uuid->toString(); - } catch (UnsatisfiedDependencyException $e) { - Kohana::$log->add(Log::ERROR, $e->getMessage()); - } - - $state = [ - 'created' => time(), - ]; - - return $this->executeInsert($this->removeNullValues($record)); - } - - // UpdateRepository - public function update(Entity $entity) - { - - $record = $entity->asArray(); - $record['updated'] = time(); - try { - $uuid = Uuid::uuid4(); - $record['api_key'] = $uuid->toString(); - } catch (UnsatisfiedDependencyException $e) { - Kohana::$log->add(Log::ERROR, $e->getMessage()); - } - - return $this->executeUpdate(['id' => $entity->id], $record); - } - - public function apiKeyExists($api_key) - { - return (bool) $this->selectCount(compact('api_key')); - } - - public function getSearchFields() - { - return [ - ]; - } -} diff --git a/application/classes/Ushahidi/Repository/Post.php b/application/classes/Ushahidi/Repository/Post.php index 07c0e72112..a2fe781540 100644 --- a/application/classes/Ushahidi/Repository/Post.php +++ b/application/classes/Ushahidi/Repository/Post.php @@ -987,12 +987,12 @@ public function update(Entity $entity) $count = $this->executeUpdate(['id' => $entity->id], $post); $values = $entity->values; - // Handle legacy post.tags attribute if ($entity->hasChanged('tags')) { // Find first tag attribute list($attr_id, $attr_key) = $this->getFirstTagAttr($entity->form_id); + // If we don't have tags in the values, use the post.tags value if ($attr_key && !isset($values[$attr_key])) { $values[$attr_key] = $entity->tags; @@ -1002,7 +1002,6 @@ public function update(Entity $entity) if ($entity->hasChanged('values')) { // Update post-values - $this->post_value_factory->proxy()->deleteAllForPost($entity->id); $this->updatePostValues($entity->id, $values); } @@ -1012,70 +1011,17 @@ public function update(Entity $entity) $this->updatePostStages($entity->id, $entity->form_id, $entity->completed_stages); } - // TODO: Revist post-Kohana - // This might be better placed in the usecase but - // given Kohana's future I've put it here - $this->emit($this->event, $entity->id, 'update'); - if ($this->post_lock_repo->isActive($entity->id)) { $this->post_lock_repo->releaseLock($entity->id); } - - return $count; - } - - // UpdateRepository - public function updateFromService(Entity $entity) - { - $post = $entity->getChanged(); - $post['updated'] = time(); - // Remove attribute values and tags - unset($post['values'], $post['tags'], $post['completed_stages'], $post['sets'], $post['source'], $post['color']); - // Convert post_date to mysql format - if(!empty($post['post_date'])) { - $post['post_date'] = $post['post_date']->format("Y-m-d H:i:s"); - } - $count = $this->executeUpdate(['id' => $entity->id], $post); - $values = $entity->values; - // Handle legacy post.tags attribute - if ($entity->hasChanged('tags')) - { - // Find first tag attribute - list($attr_id, $attr_key) = $this->getFirstTagAttr($entity->form_id); - // If we don't have tags in the values, use the post.tags value - if ($attr_key && !isset($values[$attr_key])) { - $values[$attr_key] = $entity->tags; - } - } - if ($entity->hasChanged('values') || $entity->hasChanged('tags')) - { - // Update post-values - $this->updatePostValues($entity->id, $values); - } - if ($entity->hasChanged('completed_stages')) - { - // Update post-stages - $this->updatePostStages($entity->id, $entity->form_id, $entity->completed_stages); - } - // TODO: Revist post-Kohana - // This might be better placed in the usecase but - // given Kohana's future I've put it here - $this->emit($this->event, $entity->id, 'update'); return $count; } - public function delete(Entity $entity) - { - parent::delete($entity); - // TODO: Revist post-Kohana - // This might be better placed in the usecase but - // given Kohana's future I've put it here - //$this->emit($this->event, $entity->id, 'delete'); - } - protected function updatePostValues($post_id, $attributes) { + $this->post_value_factory->proxy()->deleteAllForPost($post_id); + foreach ($attributes as $key => $values) { $attribute = $this->form_attribute_repo->getByKey($key); diff --git a/application/classes/Ushahidi/Repository/Webhook.php b/application/classes/Ushahidi/Repository/Webhook.php index b2132307b6..58c623012a 100644 --- a/application/classes/Ushahidi/Repository/Webhook.php +++ b/application/classes/Ushahidi/Repository/Webhook.php @@ -16,14 +16,19 @@ use Ushahidi\Core\Traits\UserContext; use Ushahidi\Core\Traits\AdminAccess; -use Ramsey\Uuid\Uuid; -use Ramsey\Uuid\Exception\UnsatisfiedDependencyException; - class Ushahidi_Repository_Webhook extends Ushahidi_Repository implements WebhookRepository { use UserContext; use AdminAccess; + protected function getId(Entity $entity) + { + $result = $this->selectQuery() + ->where('user_id', '=', $entity->user_id) + ->execute($this->db); + return $result->get('id', 0); + } + protected function getTable() { return 'webhooks'; @@ -63,47 +68,25 @@ public function getByEventType($event_type= null) return $this->getEntity($this->selectOne(compact('event_type'))); } - public function getAllByEventType($event_type= null) - { - $query = $this->selectQuery(compact('event_type')); - - $results = $query->execute($this->db); - return $results->as_array(); - } - - public function getByUUID($webhook_uuid= null) - { - return $this->getEntity($this->selectOne(compact('webhook_uuid'))); - } - // CreateRepository public function create(Entity $entity) { - try { - $uuid = Uuid::uuid4(); - $uuid = $uuid->toString(); - } catch (UnsatisfiedDependencyException $e) { - Kohana::$log->add(Log::ERROR, $e->getMessage()); + $id = $this->getId($entity); + + if ($id) { + // No need to insert a new record. + // Instead return the id of the Webhook that exists + return $id; } $state = [ 'user_id' => $entity->user_id, - 'webhook_uuid' => $uuid, 'created' => time(), ]; return parent::create($entity->setState($state)); } - // UpdateRepository - public function update(Entity $entity) - { - - $record = $entity->asArray(); - $record['updated'] = time(); - return $this->executeUpdate(['id' => $entity->id], $record); - } - public function getSearchFields() { return [ diff --git a/application/classes/Ushahidi/Signer/Signature.php b/application/classes/Ushahidi/Signer/Signature.php deleted file mode 100644 index 434b6741b8..0000000000 --- a/application/classes/Ushahidi/Signer/Signature.php +++ /dev/null @@ -1,67 +0,0 @@ - - * @package Ushahidi\Application - * @copyright 2014 Ushahidi - * @license https://www.gnu.org/licenses/agpl-3.0.html GNU Affero General Public License Version 3 (AGPL3) - */ - -use Ushahidi\Core\Tool\Signer; - -class Ushahidi_Signer_Signature implements Signer -{ - protected $authToken; - - public function __construct($authToken) - { - $this->authToken = $authToken; - } - - public function sign($fullUrl, $data) - { - return computeSignature($fullUrl, $data); - } - - public function computeSignature($url, $json) { - $url = $url . $json; - // This function calculates the HMAC hash of the data with the key - // passed in - // Note: hash_hmac requires PHP 5 >= 5.1.2 or PECL hash:1.1-1.5 - // Or http://pear.php.net/package/Crypt_HMAC/ - return base64_encode(hash_hmac("sha256", $url, $this->authToken, true)); - } - - public function validate($expectedSignature, $url, $json) { - return self::compare( - $this->computeSignature($url, $json), - $expectedSignature - ); - } - /** - * Time insensitive compare, function's runtime is governed by the length - * of the first argument, not the difference between the arguments. - * @param $a string First part of the comparison pair - * @param $b string Second part of the comparison pair - * @return bool True if $a == $b, false otherwise. - */ - public static function compare($a, $b) - { - $result = true; - if (strlen($a) != strlen($b)) { - return false; - } - if (!$a && !$b) { - return true; - } - $limit = strlen($a); - for ($i = 0; $i < $limit; ++$i) { - if ($a[$i] != $b[$i]) { - $result = false; - } - } - return $result; - } -} diff --git a/application/classes/Ushahidi/Validator/ApiKey/Create.php b/application/classes/Ushahidi/Validator/ApiKey/Create.php deleted file mode 100644 index f8d6433360..0000000000 --- a/application/classes/Ushahidi/Validator/ApiKey/Create.php +++ /dev/null @@ -1,15 +0,0 @@ - - * @package Ushahidi\Application - * @copyright 2014 Ushahidi - * @license https://www.gnu.org/licenses/agpl-3.0.html GNU Affero General Public License Version 3 (AGPL3) - */ - -class Ushahidi_Validator_ApiKey_Create extends Ushahidi_Validator_ApiKey_Update -{ - -} diff --git a/application/classes/Ushahidi/Validator/ApiKey/Update.php b/application/classes/Ushahidi/Validator/ApiKey/Update.php deleted file mode 100644 index 6b37f1df3a..0000000000 --- a/application/classes/Ushahidi/Validator/ApiKey/Update.php +++ /dev/null @@ -1,24 +0,0 @@ - - * @package Ushahidi\Application - * @copyright 2014 Ushahidi - * @license https://www.gnu.org/licenses/agpl-3.0.html GNU Affero General Public License Version 3 (AGPL3) - */ - -use Ushahidi\Core\Tool\Validator; - -class Ushahidi_Validator_ApiKey_Update extends Validator -{ - protected $default_error_source = 'apikey'; - - protected function getRules() - { - return [ - - ]; - } -} diff --git a/application/classes/Ushahidi/Validator/Webhook/Create.php b/application/classes/Ushahidi/Validator/Webhook/Create.php index c6be2fee6f..77f974c2ad 100644 --- a/application/classes/Ushahidi/Validator/Webhook/Create.php +++ b/application/classes/Ushahidi/Validator/Webhook/Create.php @@ -11,24 +11,5 @@ class Ushahidi_Validator_Webhook_Create extends Ushahidi_Validator_Webhook_Update { - protected function getRules() - { - return array_merge_recursive(parent::getRules(), [ - 'name' => [ - ['not_empty'], - ], - 'shared_secret' => [ - ['not_empty'], - ], - 'url' => [ - ['not_empty'], - ], - 'event_type' => [ - ['not_empty'], - ], - 'entity_type' => [ - ['not_empty'], - ], - ]); - } + } diff --git a/application/classes/Ushahidi/Validator/Webhook/Update.php b/application/classes/Ushahidi/Validator/Webhook/Update.php index b179235d61..12fd2688b0 100644 --- a/application/classes/Ushahidi/Validator/Webhook/Update.php +++ b/application/classes/Ushahidi/Validator/Webhook/Update.php @@ -42,7 +42,7 @@ protected function getRules() ['url'] ], 'event_type' => [ - ['in_array', [':value', ['create', 'delete', 'update']]], + ['in_array', [':value', ['create', 'delete', 'update', 'search']]], ], 'entity_type' => [ ['in_array', [':value', ['post']]], diff --git a/application/routes/default.php b/application/routes/default.php index 057b18cd6b..8e24a7c6e0 100644 --- a/application/routes/default.php +++ b/application/routes/default.php @@ -282,18 +282,6 @@ 'directory' => 'Api' )); - /** - * Dataproviders API Route - */ - Route::set('inbound-webhook-api', $apiBase . 'webhooks//()', - array( - 'id' => '\d+' - )) - ->defaults(array( - 'action' => 'index', - 'directory' => 'Api/Webhooks/' - )); - /** * Migration migrate Route */ diff --git a/application/tests/features/api.apikeys.feature b/application/tests/features/api.apikeys.feature deleted file mode 100644 index b5e1239da1..0000000000 --- a/application/tests/features/api.apikeys.feature +++ /dev/null @@ -1,60 +0,0 @@ -@apikeys -Feature: Testing the ApiKey API - - Scenario: Create an apikey - Given that I want to make a new "ApiKey" - And that the request "Authorization" header is "Bearer testadminuser" - And that the request "data" is: - """ - { - } - """ - When I request "/apikeys" - Then the response is JSON - And the response has a "id" property - And the type of the "id" property is "numeric" - Then the guzzle status code should be 200 - - Scenario: An anonymous user cannot create to a apikey - Given that I want to make a new "Apikey" - And that the request "Authorization" header is "Bearer testanon" - And that the request "data" is: - """ - { - "api_key": "myshadykey" - } - """ - When I request "/apikeys" - Then the guzzle status code should be 400 - - Scenario: Updating an apikey - Given that I want to update an "ApiKey" - And that its "id" is "2" - And that the request "Authorization" header is "Bearer testadminuser" - And that the request "data" is: - """ - { - "api_key": "mytestkeyisthislong" - } - """ - When I request "/apikeys" - Then the response is JSON - And the response has a "id" property - And the type of the "id" property is "numeric" - And the "id" property equals "2" - And the "api_key" property does not equal "mytestkeyisthislong" - Then the guzzle status code should be 200 - - @resetFixture - Scenario: Listing Apikeys for a user - Given that I want to get all "Apikeys" - And that the request "Authorization" header is "Bearer testadminuser" - And that the request "query string" is: - """ - """ - When I request "/apikeys" - Then the response is JSON - And the response has a "count" property - And the type of the "count" property is "numeric" - And the "count" property equals "1" - Then the guzzle status code should be 200 diff --git a/migrations/20170311004159_create_webhook_job.php b/migrations/20170311004159_create_webhook_job.php index 2fc3fff45b..7d4e308bb7 100644 --- a/migrations/20170311004159_create_webhook_job.php +++ b/migrations/20170311004159_create_webhook_job.php @@ -15,7 +15,8 @@ public function up() ->addColumn('event_type', 'string', ['null' => false]) ->addColumn('created', 'integer', ['default' => 0]) ->addForeignKey('post_id', 'posts', 'id', [ - 'delete' => 'CASCADE' + 'delete' => 'CASCADE', + 'update' => 'CASCADE', ]) ->create(); } diff --git a/migrations/20170330135806_add_api_key_table.php b/migrations/20170330135806_add_api_key_table.php deleted file mode 100644 index dc0d12cd9f..0000000000 --- a/migrations/20170330135806_add_api_key_table.php +++ /dev/null @@ -1,29 +0,0 @@ -table('apikeys') - ->addColumn('api_key', 'text', ['null' => false]) - ->addColumn('client_id', 'text', ['null' => true]) - ->addColumn('client_secret', 'text', ['null' => true]) - ->addColumn('created', 'integer', ['default' => 0]) - ->addColumn('updated', 'integer', ['null' => true]) - ->create() - ; - } - - /** - * Migrate Down. - */ - public function down() - { - $this->dropTable('apikeys'); - } -} diff --git a/migrations/20170330151759_add_api_key_to_oauth_table.php b/migrations/20170330151759_add_api_key_to_oauth_table.php deleted file mode 100644 index ce33092025..0000000000 --- a/migrations/20170330151759_add_api_key_to_oauth_table.php +++ /dev/null @@ -1,23 +0,0 @@ -execute("INSERT INTO oauth_scopes (scope, name) VALUES ('apikeys', 'apikeys')"); - } - - /** - * Migrate Down. - */ - public function down() - { - $this->execute("DELETE FROM oauth_scopes WHERE scope = 'apikeys'"); - } -} diff --git a/migrations/20170406132016_add_webhook_uuid_to_webhook_table.php b/migrations/20170406132016_add_webhook_uuid_to_webhook_table.php deleted file mode 100644 index 1be2170934..0000000000 --- a/migrations/20170406132016_add_webhook_uuid_to_webhook_table.php +++ /dev/null @@ -1,26 +0,0 @@ -table('webhooks') - ->addColumn('webhook_uuid', 'string', ['null' => false]) - ->update(); - } - - /** - * Migrate Down. - */ - public function down() - { - $this->table('webhooks') - ->removeColumn('webhook_uuid') - ->update(); - } -} diff --git a/migrations/20170406132136_add_form_source_destination_to_webhook_table.php b/migrations/20170406132136_add_form_source_destination_to_webhook_table.php deleted file mode 100644 index b271bbe33c..0000000000 --- a/migrations/20170406132136_add_form_source_destination_to_webhook_table.php +++ /dev/null @@ -1,37 +0,0 @@ -table('webhooks') - ->addColumn('form_id', 'integer', [ - 'default' => null, - 'null' => true - ]) - ->addColumn('source_field_uuid', 'string', ['null' => true]) - ->addColumn('destination_field_uuid', 'string', ['null' => true]) - ->addForeignKey('form_id', 'forms', 'id', [ - 'delete'=> 'CASCADE' - ]) - ->update(); - } - - /** - * Migrate Down. - */ - public function down() - { - $this->table('webhooks') - ->dropForeignKey('form_id') - ->removeColumn('form_id') - ->removeColumn('source_field_uuid') - ->removeColumn('destination_field_uuid') - ->update(); - } -} diff --git a/migrations/20170413163900_rename_source_destination_uuid_for_webhooks_table.php b/migrations/20170413163900_rename_source_destination_uuid_for_webhooks_table.php deleted file mode 100644 index ddaca2f746..0000000000 --- a/migrations/20170413163900_rename_source_destination_uuid_for_webhooks_table.php +++ /dev/null @@ -1,24 +0,0 @@ -table('webhooks'); - $attributes - ->renameColumn('source_field_uuid', 'source_field_key') - ->renameColumn('destination_field_uuid', 'destination_field_key') - ->update(); - } - - public function down() - { - $attributes = $this->table('webhooks'); - $attributes - ->renameColumn('source_field_key', 'source_field_uuid') - ->renameColumn('destination_field_key', 'destination_field_uuid') - ->update(); - } -} diff --git a/modules/data-provider/classes/DataProvider/Core.php b/modules/data-provider/classes/DataProvider/Core.php index 7947344784..03da899335 100644 --- a/modules/data-provider/classes/DataProvider/Core.php +++ b/modules/data-provider/classes/DataProvider/Core.php @@ -297,7 +297,7 @@ abstract public function send($to, $message, $title = ""); * @param string data_provider_message_id Message ID * @return void */ - abstract public function receive($type, $from, $message, $to = NULL, $title = NULL, $date = NULL, $data_provider_message_id = NULL, Array $additional_data = NULL); + abstract public function receive($type, $from, $message, $to = NULL, $title = NULL, $data_provider_message_id = NULL, Array $additional_data = NULL); /** * Get queued outgoing messages diff --git a/plugins/data-provider-email/classes/DataProvider/Email.php b/plugins/data-provider-email/classes/DataProvider/Email.php index 29e7151fd6..b0b0391cc2 100644 --- a/plugins/data-provider-email/classes/DataProvider/Email.php +++ b/plugins/data-provider-email/classes/DataProvider/Email.php @@ -169,12 +169,12 @@ public function fetch($limit = FALSE) // Process the email if (! empty($html_message)) { $html_message = imap_qprint($html_message); - $this->_process_incoming($email, $html_message, $options); + $this->_process_incoming($email, $html_message); } elseif (! empty($message)) { $message = imap_qprint($message); - $this->_process_incoming($email, $message, $options); + $this->_process_incoming($email, $message); } $count++; @@ -214,7 +214,7 @@ protected function _is_provider_available() * @param object $overview * @param string message - the email message */ - protected function _process_incoming($overview, $message, $options) + protected function _process_incoming($overview, $message) { $from = $this->_get_email($overview->from); $to = isset($overview->to) ? $this->_get_email($overview->to) : $this->from(); @@ -228,14 +228,8 @@ protected function _process_incoming($overview, $message, $options) $message = html_entity_decode($message, ENT_QUOTES, 'UTF-8'); if ($message) { - // Check if a form id is already associated with this data provider - $additional_data = []; - if (isset($options['form_id'])) { - $additional_data['form_id'] = $options['form_id']; - $additional_data['inbound_fields'] = isset($options['inbound_fields']) ? $options['inbound_fields'] : NULL; - } // Save the message - $this->receive(Message_Type::EMAIL, $from, $message, $to, $title, $date = NULL, $data_provider_message_id, $additional_data); + $this->receive(Message_Type::EMAIL, $from, $message, $to, $title, $data_provider_message_id); } return; diff --git a/plugins/data-provider-email/init.php b/plugins/data-provider-email/init.php index 4941ec1a7e..7a2edc036b 100644 --- a/plugins/data-provider-email/init.php +++ b/plugins/data-provider-email/init.php @@ -118,14 +118,7 @@ 'input' => 'text', 'description' => 'Appears in the \'from:\' field on outgoing emails', 'rules' => array('required') - ) - ), - 'inbound_fields' => array( - 'From' => 'text', - 'Subject' => 'text', - 'To' => 'text', - 'Date' => 'datetime', - 'Message' => 'text' + ), ), // Links @@ -135,3 +128,4 @@ // Register the plugin DataProvider::register_provider('email', $plugin); + diff --git a/plugins/frontlinesms/classes/Controller/Sms/Frontlinesms.php b/plugins/frontlinesms/classes/Controller/Sms/Frontlinesms.php index f391a2e907..0ac1a4018f 100644 --- a/plugins/frontlinesms/classes/Controller/Sms/Frontlinesms.php +++ b/plugins/frontlinesms/classes/Controller/Sms/Frontlinesms.php @@ -85,16 +85,7 @@ private function _incoming() // Allow for Alphanumeric sender $from = preg_replace("/[^0-9A-Za-z ]/", "", $from); - $options = $this->_provider->options(); - - $additional_data = []; - // Check if a form id is already associated with this data provider - if (isset($options['form_id'])) { - $additional_data['form_id'] = $options['form_id']; - $additional_data['inbound_fields'] = isset($options['inbound_fields']) ? $options['inbound_fields'] : NULL; - } - - $this->_provider->receive(Message_Type::SMS, $from, $message_text, $additional_data); + $this->_provider->receive(Message_Type::SMS, $from, $message_text); $this->_json['payload'] = [ 'success' => TRUE, diff --git a/plugins/frontlinesms/init.php b/plugins/frontlinesms/init.php index f7a6e1c5bb..d1195609ab 100644 --- a/plugins/frontlinesms/init.php +++ b/plugins/frontlinesms/init.php @@ -33,11 +33,6 @@ 'rules' => array('required') ) ), - 'inbound_fields' => array( - 'From' => 'text', - 'To' => 'text', - 'Message' => 'text' - ), // Links 'links' => array( diff --git a/plugins/nexmo/classes/Controller/Sms/Nexmo.php b/plugins/nexmo/classes/Controller/Sms/Nexmo.php index 4c74e75c85..524c066c90 100644 --- a/plugins/nexmo/classes/Controller/Sms/Nexmo.php +++ b/plugins/nexmo/classes/Controller/Sms/Nexmo.php @@ -115,7 +115,7 @@ public function action_reply() //Check if data provider is available $providers_available = Kohana::$config->load('features.data-providers'); - if ( !$providers_available['nexmo'] ) + if ( !$providers_available['nexmo'] ) { throw HTTP_Exception::factory(403, 'The Nexmo data source is not currently available. It can be accessed by upgrading to a higher Ushahidi tier.'); } @@ -157,13 +157,6 @@ public function action_reply() $to = preg_replace("/[^0-9,.]/", "", $sms->to); $from = preg_replace("/[^0-9,.]/", "", $sms->from); - // Check if a form id is already associated with this data provider - $additional_data = []; - if (isset($options['form_id'])) { - $additional_data['form_id'] = $options['form_id']; - $additional_data['inbound_fields'] = isset($options['inbound_fields']) ? $options['inbound_fields'] : NULL; - } - - $provider->receive(Message_Type::SMS, $from, $sms->text, $to, $date = NULL, NULL, $sms->message_id, $additional_data); + $provider->receive(Message_Type::SMS, $from, $sms->text, $to, NULL, $sms->message_id); } } diff --git a/plugins/nexmo/init.php b/plugins/nexmo/init.php index 8685cf86ac..50e4e390c4 100644 --- a/plugins/nexmo/init.php +++ b/plugins/nexmo/init.php @@ -48,11 +48,6 @@ 'rules' => array('required') ) ), - 'inbound_fields' => array( - 'From' => 'text', - 'To' => 'text', - 'Message' => 'text' - ), // Links 'links' => array( diff --git a/plugins/twilio/classes/Controller/Ivr/Twilio.php b/plugins/twilio/classes/Controller/Ivr/Twilio.php index 7aac6692a5..5cc6903b52 100644 --- a/plugins/twilio/classes/Controller/Ivr/Twilio.php +++ b/plugins/twilio/classes/Controller/Ivr/Twilio.php @@ -78,12 +78,7 @@ public function action_gather() Kohana::$log->add(Log::ERROR, __("':digits' is not a valid IVR response", array(":digits" => $digits))); return; } - // Check if a form id is already associated with this data provider - if (isset($options['form_id'])) { - $additional_data['form_id'] = $options['form_id']; - $additional_data['inbound_fields'] = isset($options['inbound_fields']) ? $options['inbound_fields'] : NULL; - } - $provider->receive(Message_Type::IVR, $from, $message_text, $to, $date = NULL, NULL, $message_sid, $additional_data); + $provider->receive(Message_Type::IVR, $from, $message_text, $to, NULL, $message_sid); } -} +} \ No newline at end of file diff --git a/plugins/twilio/classes/Controller/Sms/Twilio.php b/plugins/twilio/classes/Controller/Sms/Twilio.php index d519395b9c..b1b257bd44 100644 --- a/plugins/twilio/classes/Controller/Sms/Twilio.php +++ b/plugins/twilio/classes/Controller/Sms/Twilio.php @@ -19,7 +19,7 @@ public function action_reply() //Check if data provider is available $providers_available = Kohana::$config->load('features.data-providers'); - if ( !$providers_available['twilio'] ) + if ( !$providers_available['twilio'] ) { throw HTTP_Exception::factory(403, 'The Twilio data source is not currently available. It can be accessed by upgrading to a higher Ushahidi tier.'); } @@ -51,15 +51,9 @@ public function action_reply() $message_text = $this->request->post('Body'); $message_sid = $this->request->post('MessageSid'); - // Check if a form id is already associated with this data provider - $additional_data = []; - if (isset($options['form_id'])) { - $additional_data['form_id'] = $options['form_id']; - $additional_data['inbound_fields'] = isset($options['inbound_fields']) ? $options['inbound_fields'] : NULL; - } - // @todo use other info from twillio, ie: location, media - $provider->receive(Message_Type::SMS, $from, $message_text, $to, $date = NULL, NULL, $message_sid, $additional_data); + + $provider->receive(Message_Type::SMS, $from, $message_text, $to, NULL, $message_sid); // If we have an auto response configured, return the response messages if (! empty($options['sms_auto_response'])) diff --git a/plugins/twilio/init.php b/plugins/twilio/init.php index 931a1e050f..7f329ad988 100644 --- a/plugins/twilio/init.php +++ b/plugins/twilio/init.php @@ -48,11 +48,6 @@ 'rules' => array('required') ) ), - 'inbound_fields' => array( - 'From' => 'text', - 'To' => 'text', - 'Message' => 'text' - ), // Links 'links' => array( @@ -82,4 +77,4 @@ ->defaults(array( 'directory' => 'Ivr', 'controller' => 'Twilio', - )); + )); \ No newline at end of file diff --git a/plugins/twitter/classes/DataProvider/Twitter.php b/plugins/twitter/classes/DataProvider/Twitter.php index 387c607a89..9f63c088c8 100644 --- a/plugins/twitter/classes/DataProvider/Twitter.php +++ b/plugins/twitter/classes/DataProvider/Twitter.php @@ -28,7 +28,7 @@ class DataProvider_Twitter extends DataProvider { private $since_id; // highest id fetched private $request_count; // track requests per window - + public function fetch($limit = FALSE) { // XXX: Store state in database config for now $config = Kohana::$config; @@ -74,83 +74,72 @@ public function fetch($limit = FALSE) { // Store the highest id $this->since_id = $statuses[0]['id']; - if (is_array($statuses)) { - foreach ($statuses as $status) { - $id = $status['id']; - $user = $status['user']; - $screen_name = $user['screen_name']; - $text = $status['text']; - $date = $status['created_at']; + foreach ($statuses as $status) { + $id = $status['id']; + $user = $status['user']; + $screen_name = $user['screen_name']; + $text = $status['text']; + + $additional_data = []; - $additional_data = []; + // Skip retweets + if (array_key_exists('retweeted_status', $status) && array_key_exists('text', $status['retweeted_status'])) { + continue; + } - // Skip retweets - if (array_key_exists('retweeted_status', $status) && array_key_exists('text', $status['retweeted_status'])) { - continue; + if ($status['coordinates'] || $status['place']) { + $additional_data['location'] = []; + if ($status['coordinates']) { + $additional_data['location'][] = $status['coordinates']; } - if ($status['coordinates'] || $status['place']) { - $additional_data['location'] = []; - if ($status['coordinates']) { - $additional_data['location'][] = $status['coordinates']; + if ($status['place'] && $status['place']['bounding_box']) { + // Make a valid linear ring + $status['place']['bounding_box']['coordinates'][0][] = $status['place']['bounding_box']['coordinates'][0][0]; + + // If we don't already have a location + if (empty($additional_data['location'])) { + // Find center of bounding box + $geom = GeoJSON::geomFromText(json_encode($status['place']['bounding_box'])); + // Use mysql to run Centroid + $result = DB::select([ + DB::expr('AsText(Centroid(GeomFromText(:poly)))')->param(':poly', $geom->toWKT()), 'center'] + )->execute(service('kohana.db')); + + $centerGeom = WKT::geomFromText($result->get('center', 0)); + // Save center as location + $additional_data['location'][] = $centerGeom->toGeoArray(); } - if ($status['place'] && $status['place']['bounding_box']) { - // Make a valid linear ring - $status['place']['bounding_box']['coordinates'][0][] = $status['place']['bounding_box']['coordinates'][0][0]; - - // If we don't already have a location - if (empty($additional_data['location'])) { - // Find center of bounding box - $geom = GeoJSON::geomFromText(json_encode($status['place']['bounding_box'])); - // Use mysql to run Centroid - $result = DB::select([ - DB::expr('AsText(Centroid(GeomFromText(:poly)))')->param(':poly', $geom->toWKT()), 'center'] - )->execute(service('kohana.db')); - - $centerGeom = WKT::geomFromText($result->get('center', 0)); - // Save center as location - $additional_data['location'][] = $centerGeom->toGeoArray(); - } - - // Add that to location - // Also save the original bounding box - $additional_data['location'][] = $status['place']['bounding_box']; + // Add that to location + // Also save the original bounding box + $additional_data['location'][] = $status['place']['bounding_box']; + } + } else if ($status['user'] && $status['user']['location']) { + # Search the provided location for matches in twitter's geocoder + $results = $connection->get("geo/search", [ + "query" => $status['user']['location'] + ]); + # If there are results, get the centroid of the first one + if (!empty($results['result']['places'])) { + $geoloc = $results['result']['places'][0]; + if ($geoloc['centroid']) { + $additional_data['location'][] = array( + 'coordinates' => $geoloc['centroid'], + 'type' => 'Point' + ); } - } else if ($status['user'] && $status['user']['location']) { - # Search the provided location for matches in twitter's geocoder - $results = $connection->get("geo/search", [ - "query" => $status['user']['location'] - ]); - # If there are results, get the centroid of the first one - if (!empty($results['result']['places'])) { - $geoloc = $results['result']['places'][0]; - if ($geoloc['centroid']) { - $additional_data['location'][] = array( - 'coordinates' => $geoloc['centroid'], - 'type' => 'Point' - ); - } - # Add the bounding box too (if available) - if ($geoloc['bounding_box']) { - $additional_data['location'][] = $geoloc['bounding_box']; - } + # Add the bounding box too (if available) + if ($geoloc['bounding_box']) { + $additional_data['location'][] = $geoloc['bounding_box']; } } + } - // Check if a form id is already associated with this data provider - if (isset($options['form_id'])) { - $additional_data['form_id'] = $options['form_id']; - $additional_data['inbound_fields'] = isset($options['inbound_fields']) ? $options['inbound_fields'] : NULL; - } - - // @todo Check for similar messages in the database before saving - $title = "Twitter ID: " . $id; - - $this->receive(Message_Type::TWITTER, $screen_name, $text, $to = NULL, $title, $date, $id, $additional_data); + // @todo Check for similar messages in the database before saving + $this->receive(Message_Type::TWITTER, $screen_name, $text, $to = NULL, $title = NULL, $id, $additional_data); - $count++; - } + $count++; } $this->request_count++; //Increment for successful request @@ -170,7 +159,7 @@ public function fetch($limit = FALSE) { } public function send($to, $message, $title='') - { + { $connection = $this->_connect(); try @@ -180,7 +169,7 @@ public function send($to, $message, $title='') ]); if (!$response->id) { - return array(Message_Status::FAILED, FALSE); + return array(Message_Status::FAILED, FALSE); } return array(Message_Status::SENT, $response->id); } diff --git a/plugins/twitter/init.php b/plugins/twitter/init.php index fa6826aed2..b02af51c5e 100644 --- a/plugins/twitter/init.php +++ b/plugins/twitter/init.php @@ -69,13 +69,6 @@ 'rules' => array('required') ) ), - 'inbound_fields' => array( - 'From' => 'text', - 'Title' => 'text', - 'Date' => 'datetime', - 'Location' => 'location', - 'Message' => 'text' - ), // Links 'links' => array( diff --git a/src/Core/Entity/ApiKey.php b/src/Core/Entity/ApiKey.php deleted file mode 100644 index 7b940e7c4e..0000000000 --- a/src/Core/Entity/ApiKey.php +++ /dev/null @@ -1,40 +0,0 @@ - - * @package Ushahidi\Platform - * @copyright 2014 Ushahidi - * @license https://www.gnu.org/licenses/agpl-3.0.html GNU Affero General Public License Version 3 (AGPL3) - */ - -namespace Ushahidi\Core\Entity; - -use Ushahidi\Core\StaticEntity; - -class ApiKey extends StaticEntity -{ - protected $id; - protected $api_key; - protected $created; - protected $updated; - - - // DataTransformer - protected function getDefinition() - { - return [ - 'id' => 'int', - 'api_key' => 'string', - 'created' => 'int', - 'updated' => 'int', - ]; - } - - // Entity - public function getResource() - { - return 'apikey'; - } -} diff --git a/src/Core/Entity/ApiKeyRepository.php b/src/Core/Entity/ApiKeyRepository.php deleted file mode 100644 index 58de9cc998..0000000000 --- a/src/Core/Entity/ApiKeyRepository.php +++ /dev/null @@ -1,22 +0,0 @@ - - * @package Ushahidi\Platform - * @copyright 2014 Ushahidi - * @license https://www.gnu.org/licenses/agpl-3.0.html GNU Affero General Public License Version 3 (AGPL3) - */ - -namespace Ushahidi\Core\Entity; - -use Ushahidi\Core\Entity\Repository\EntityGet; -use Ushahidi\Core\Entity\Repository\EntityExists; - -interface ApiKeyRepository extends - EntityGet, - EntityExists -{ - -} diff --git a/src/Core/Entity/DataProvider.php b/src/Core/Entity/DataProvider.php index ef152a146f..e244402743 100644 --- a/src/Core/Entity/DataProvider.php +++ b/src/Core/Entity/DataProvider.php @@ -21,19 +21,17 @@ class DataProvider extends StaticEntity protected $services; protected $links; protected $options; - protected $inbound_fields; // DataTransformer protected function getDefinition() { return [ - 'id' => 'string', - 'name' => 'string', - 'version' => 'float', - 'services' => 'array', - 'links' => 'array', - 'options' => 'array', - 'inbound_fields' => 'array', + 'id' => 'string', + 'name' => 'string', + 'version' => 'float', + 'services' => 'array', + 'links' => 'array', + 'options' => 'array', ]; } diff --git a/src/Core/Entity/Webhook.php b/src/Core/Entity/Webhook.php index 0d988613b6..14500f5088 100644 --- a/src/Core/Entity/Webhook.php +++ b/src/Core/Entity/Webhook.php @@ -16,16 +16,12 @@ class Webhook extends StaticEntity { protected $id; - protected $form_id; protected $user_id; protected $url; protected $name; protected $shared_secret; - protected $webhook_uuid; protected $event_type; protected $entity_type; - protected $source_field_key; - protected $destination_field_key; protected $created; protected $updated; @@ -34,8 +30,7 @@ protected function getDerived() { // Foreign key alias return [ - 'user_id' => ['user', 'user.id'], - 'form_id' => ['form', 'form.id'] + 'user_id' => ['user', 'user.id'] ]; } @@ -43,21 +38,16 @@ protected function getDerived() protected function getDefinition() { return [ - 'id' => 'int', - 'name' => 'string', - 'url' => 'string', - 'shared_secret' => 'string', - 'webhook_uuid' => 'string', - 'event_type' => 'string', - 'entity_type' => 'string', - 'source_field_key' => 'string', - 'destination_field_key' => 'string', - 'user' => false, - 'user_id' => 'int', - 'form' => false, /* alias */ - 'form_id' => 'int', - 'created' => 'int', - 'updated' => 'int', + 'id' => 'int', + 'name' => 'string', + 'url' => 'string', + 'shared_secret' => 'string', + 'event_type' => 'string', + 'entity_type' => 'string', + 'user' => false, + 'user_id' => 'int', + 'created' => 'int', + 'updated' => 'int', ]; } diff --git a/src/Core/Tool/Authorizer/ApiKeyAuthorizer.php b/src/Core/Tool/Authorizer/ApiKeyAuthorizer.php deleted file mode 100644 index f7c0a51cc7..0000000000 --- a/src/Core/Tool/Authorizer/ApiKeyAuthorizer.php +++ /dev/null @@ -1,55 +0,0 @@ - - * @package Ushahidi\Application - * @copyright 2014 Ushahidi - * @license https://www.gnu.org/licenses/agpl-3.0.html GNU Affero General Public License Version 3 (AGPL3) - */ - -namespace Ushahidi\Core\Tool\Authorizer; - -use Ushahidi\Core\Entity; -use Ushahidi\Core\Tool\Authorizer; -use Ushahidi\Core\Traits\AdminAccess; -use Ushahidi\Core\Traits\UserContext; -use Ushahidi\Core\Traits\PrivAccess; -use Ushahidi\Core\Traits\PrivateDeployment; - -class ApiKeyAuthorizer implements Authorizer -{ - // The access checks are run under the context of a specific user - use UserContext; - - // To check whether the user has admin access - use AdminAccess; - - // It uses `PrivAccess` to provide the `getAllowedPrivs` method. - use PrivAccess; - - // It uses `PrivateDeployment` to check whether a deployment is private - use PrivateDeployment; - - /* Authorizer */ - public function isAllowed(Entity $entity, $privilege) - { - - // These checks are run within the user context. - $user = $this->getUser(); - - // Only logged in users have access if the deployment is private - if (!$this->canAccessDeployment($user)) { - return false; - } - - // Admin is allowed access to everything - if ($this->isUserAdmin($user)) { - return true; - } - - // If no other access checks succeed, we default to denying access - return false; - } -} diff --git a/src/Core/Tool/Signer.php b/src/Core/Tool/Signer.php index 43cbab9c97..de8def398a 100644 --- a/src/Core/Tool/Signer.php +++ b/src/Core/Tool/Signer.php @@ -37,7 +37,7 @@ public function computeSignature($url, $json) public function validate($expectedSignature, $url, $data = array()) { return self::compare( - $this->computeSignature($url, json_encode($data)), + $this->computeSignature($url, $data), $expectedSignature ); } diff --git a/src/Core/Traits/DataTransformer.php b/src/Core/Traits/DataTransformer.php index ae39305d99..7dc3dcb176 100644 --- a/src/Core/Traits/DataTransformer.php +++ b/src/Core/Traits/DataTransformer.php @@ -122,8 +122,6 @@ protected function transformDate($value) // If this is already a DateTime object clone it if ($value instanceof \DateTimeInterface) { $value = clone $value; - } elseif (is_array($value)) { - $value = new \DateTime($value['date'], new \DateTimeZone($value['timezone'])); } else { // Convert post_date to DateTime $trialValue = date_create($value, new \DateTimeZone('UTC')); diff --git a/src/Core/Usecase/Message/ReceiveMessage.php b/src/Core/Usecase/Message/ReceiveMessage.php index 11d2d33fa4..476994fec8 100644 --- a/src/Core/Usecase/Message/ReceiveMessage.php +++ b/src/Core/Usecase/Message/ReceiveMessage.php @@ -168,74 +168,30 @@ protected function createContact(Entity $contact) protected function createPost(Entity $message) { $values = []; - $form_id = null; - - $content = $message->message; + // Pull locations from extra metadata if ($message->additional_data) { - if (isset($message->additional_data['form_id'])) { - $form_id = $message->additional_data['form_id']; - // Check provider fields for form attribute mapping - $inbound_fields = $message->additional_data['inbound_fields']; - - if (isset($this->payload['title']) && isset($inbound_fields['Title'])) { - $values[$inbound_fields['Title']] = array($this->payload['title']); - } - - if (isset($this->payload['from']) && isset($inbound_fields['From'])) { - $values[$inbound_fields['From']] = array($this->payload['from']); - } - - if (isset($this->payload['to']) && isset($inbound_fields['To'])) { - $values[$inbound_fields['To']] = array($this->payload['to']); - } - - if (isset($this->payload['message']) && isset($inbound_fields['Message'])) { - $values[$inbound_fields['Message']] = array($this->payload['message']); - } - - if (isset($this->payload['date']) && isset($inbound_fields['Date'])) { - $timestamp = date("Y-m-d H:i:s", strtotime($this->payload['date'])); - $values[$inbound_fields['Date']] = array($timestamp); - } - - if (isset($message->additional_data['location']) && isset($inbound_fields['Location'])) { - foreach ($message->additional_data['location'] as $location) { - if (!empty($location['type']) && - !empty($location['coordinates']) && - ucfirst($location['type']) == 'Point' - ) { - $values[$inbound_fields['Location']][] = [ - 'lon' => $location['coordinates'][0], - 'lat' => $location['coordinates'][1] - ]; - } - } - } - } - // Pull locations from extra metadata $values['message_location'] = []; - if (isset($message->additional_data['location'])) { - foreach ($message->additional_data['location'] as $location) { - if (!empty($location['type']) && - !empty($location['coordinates']) && - ucfirst($location['type']) == 'Point' - ) { - $values['message_location'][] = [ - 'lon' => $location['coordinates'][0], - 'lat' => $location['coordinates'][1] - ]; - } + foreach ($message->additional_data['location'] as $location) { + if (!empty($location['type']) && + !empty($location['coordinates']) && + ucfirst($location['type']) == 'Point' + ) { + $values['message_location'][] = [ + 'lon' => $location['coordinates'][0], + 'lat' => $location['coordinates'][1] + ]; } } } + // First create a post $post = $this->postRepo->getEntity()->setState([ - 'title' => $message->title, - 'content' => $content, - 'values' => $values, - 'form_id' => $form_id + 'title' => $message->title, + 'content' => $message->message, + 'values' => $values ]); + return $this->postRepo->create($post); } diff --git a/src/Core/Usecase/Post/WebhookUpdatePost.php b/src/Core/Usecase/Post/WebhookUpdatePost.php deleted file mode 100644 index 685dbf3768..0000000000 --- a/src/Core/Usecase/Post/WebhookUpdatePost.php +++ /dev/null @@ -1,72 +0,0 @@ - - * @package Ushahidi\Platform - * @copyright 2014 Ushahidi - * @license https://www.gnu.org/licenses/agpl-3.0.html GNU Affero General Public License Version 3 (AGPL3) - */ - -namespace Ushahidi\Core\Usecase\Post; - -use Ushahidi\Core\Entity; -use Ushahidi\Core\Usecase\UpdateUsecase; - -class WebhookUpdatePost extends UpdateUsecase -{ - // This replaces the default getEntity() logic to allow loading - // posts by locale, parent id and id. - use FindPostEntity { - // In the case of updates, we have to apply the payload after fetch. - getEntity as private getEntityWithoutPayload; - } - - // Usecase - public function interact() - { - // Fetch the entity and apply the payload... - $entity = $this->getEntity()->setState($this->payload); - - // ... verify that the entity is in a valid state - $this->verifyValid($entity); - - // ... persist the changes - $this->repo->updateFromService($entity); - - // ... check that the entity can be read by the current user - if ($this->auth->isAllowed($entity, 'read')) { - // ... and either load the updated entity from the storage layer - $updated_entity = $this->getEntity(); - - // ... and return the updated, formatted entity - return $this->formatter->__invoke($updated_entity); - } else { - // ... or just return nothing - return; - } - } - - // UpdateUsecase - protected function getEntity() - { - return $this->getEntityWithoutPayload(); - } - - // UpdateUsecase - protected function verifyValid(Entity $entity) - { - $changed = $entity->getChanged(); - - // Always pass values to validation - - if (isset($entity->values)) { - $changed['values'] = $entity->values; - } - - if (!$this->validator->check($changed, $entity->asArray())) { - $this->validatorError($entity); - } - } -} diff --git a/src/Core/Usecase/Webhook/CreateWebhook.php b/src/Core/Usecase/Webhook/CreateWebhook.php index 7d816b102f..d0dfa7aaa4 100644 --- a/src/Core/Usecase/Webhook/CreateWebhook.php +++ b/src/Core/Usecase/Webhook/CreateWebhook.php @@ -21,7 +21,6 @@ protected function getEntity() $entity = parent::getEntity(); // Add user id if this is not provided - // TODO: throw this away if (empty($entity->user_id) && $this->auth->getUserId()) { $entity->setState(['user_id' => $this->auth->getUserId()]); } diff --git a/src/Init.php b/src/Init.php index 9c08d4f3d5..71cc91e3c9 100644 --- a/src/Init.php +++ b/src/Init.php @@ -143,7 +143,6 @@ function feature($name) 'users' => $di->lazyGet('authorizer.user'), 'notifications' => $di->lazyGet('authorizer.notification'), 'webhooks' => $di->lazyGet('authorizer.webhook'), - 'apikeys' => $di->lazyGet('authorizer.apikey'), 'contacts' => $di->lazyGet('authorizer.contact'), 'csv' => $di->lazyGet('authorizer.csv'), 'roles' => $di->lazyGet('authorizer.role'), @@ -175,7 +174,6 @@ function feature($name) 'users' => $di->lazyGet('repository.user'), 'notifications' => $di->lazyGet('repository.notification'), 'webhooks' => $di->lazyGet('repository.webhook'), - 'apikeys' => $di->lazyGet('repository.apikey'), 'contacts' => $di->lazyGet('repository.contact'), 'csv' => $di->lazyGet('repository.csv'), 'roles' => $di->lazyGet('repository.role'), @@ -291,14 +289,13 @@ function feature($name) // Add custom usecases for posts $di->params['Ushahidi\Factory\UsecaseFactory']['map']['posts'] = [ - 'create' => $di->lazyNew('Ushahidi\Core\Usecase\Post\CreatePost'), - 'read' => $di->lazyNew('Ushahidi\Core\Usecase\Post\ReadPost'), - 'update' => $di->lazyNew('Ushahidi\Core\Usecase\Post\UpdatePost'), - 'webhook-update' => $di->lazyNew('Ushahidi\Core\Usecase\Post\WebhookUpdatePost'), - 'delete' => $di->lazyNew('Ushahidi\Core\Usecase\Post\DeletePost'), - 'search' => $di->lazyNew('Ushahidi\Core\Usecase\Post\SearchPost'), - 'stats' => $di->lazyNew('Ushahidi\Core\Usecase\Post\StatsPost'), - 'import' => $di->lazyNew('Ushahidi\Core\Usecase\ImportUsecase'), + 'create' => $di->lazyNew('Ushahidi\Core\Usecase\Post\CreatePost'), + 'read' => $di->lazyNew('Ushahidi\Core\Usecase\Post\ReadPost'), + 'update' => $di->lazyNew('Ushahidi\Core\Usecase\Post\UpdatePost'), + 'delete' => $di->lazyNew('Ushahidi\Core\Usecase\Post\DeletePost'), + 'search' => $di->lazyNew('Ushahidi\Core\Usecase\Post\SearchPost'), + 'stats' => $di->lazyNew('Ushahidi\Core\Usecase\Post\StatsPost'), + 'import' => $di->lazyNew('Ushahidi\Core\Usecase\ImportUsecase'), ]; // Add custom create usecase for notifications @@ -426,7 +423,6 @@ function feature($name) $di->set('authorizer.set', $di->lazyNew('Ushahidi\Core\Tool\Authorizer\SetAuthorizer')); $di->set('authorizer.notification', $di->lazyNew('Ushahidi\Core\Tool\Authorizer\NotificationAuthorizer')); $di->set('authorizer.webhook', $di->lazyNew('Ushahidi\Core\Tool\Authorizer\WebhookAuthorizer')); -$di->set('authorizer.apikey', $di->lazyNew('Ushahidi\Core\Tool\Authorizer\ApiKeyAuthorizer')); $di->set('authorizer.contact', $di->lazyNew('Ushahidi\Core\Tool\Authorizer\ContactAuthorizer')); $di->set('authorizer.csv', $di->lazyNew('Ushahidi\Core\Tool\Authorizer\CSVAuthorizer')); $di->set('authorizer.role', $di->lazyNew('Ushahidi\Core\Tool\Authorizer\RoleAuthorizer')); diff --git a/tests/datasets/ushahidi/Base.yml b/tests/datasets/ushahidi/Base.yml index ff2ebff34c..0ffeb1aaf5 100644 --- a/tests/datasets/ushahidi/Base.yml +++ b/tests/datasets/ushahidi/Base.yml @@ -1,7 +1,3 @@ -apikeys: - - - id: 2 - api_key: "thisisatestapikeystring" roles: - name: "user" @@ -1415,10 +1411,6 @@ oauth_scopes: id: 21 scope: tos name: tos - - - id: 22 - scope: apikeys - name: apikeys oauth_session_token_scopes: # for testingtoken @@ -2054,7 +2046,6 @@ webhooks: - id: 2 user_id: 1 - webhook_uuid: "test-test-test" name: "test" shared_secret: "testestest" url: "https://test.test" @@ -2063,7 +2054,6 @@ webhooks: - id: 3 user_id: 1 - webhook_uuid: "test-test-test" name: "test" shared_secret: "testestest" url: "https://test.test" @@ -2072,7 +2062,6 @@ webhooks: - id: 4 user_id: 1 - webhook_uuid: "test-test-test" name: "test" shared_secret: "testestest" url: "https://test.test" @@ -2081,7 +2070,6 @@ webhooks: - id: 5 user_id: 1 - webhook_uuid: "test-test-test" name: "test" shared_secret: "testestest" url: "https://test.test" diff --git a/tests/integration/bootstrap/RestContext.php b/tests/integration/bootstrap/RestContext.php index 131e1cd606..2d435f3130 100644 --- a/tests/integration/bootstrap/RestContext.php +++ b/tests/integration/bootstrap/RestContext.php @@ -221,8 +221,8 @@ public function iRequest($pageUrl) ->post($this->requestUrl) ->addPostFields($this->postFields) ->addPostFiles($this->preparePostFileData($this->postFiles)); - } else { - // Otherwise assume we have JSON + } // Otherwise assume we have JSON + else { $http_request = $this->client ->post($this->requestUrl) ->setBody($request['data']); diff --git a/tests/integration/webhooks.feature b/tests/integration/webhooks.feature index 9dd3886016..f09271b604 100644 --- a/tests/integration/webhooks.feature +++ b/tests/integration/webhooks.feature @@ -61,28 +61,3 @@ Feature: Testing the Webhook API And the type of the "count" property is "numeric" And the "count" property equals "4" Then the guzzle status code should be 200 - -# @resetFixture -# Given that I want to update a "Post" -# And that its "id" is "1" -# And that the request "X-Ushahidi-Signature" header is "PqAl0200sE/hGYgGVyKis24c9p8RjYoLk9iMVxX3llk=" -# And that the request "data" is: -# """ -# { -# "id":"1", -# "title": "Update test post title", -# "webhook_uuid": "test-test-test", -# "api_key" : "thisisatestapikeystring" -# } -# """ -# When I request "/webhooks/posts" -# Then the response is JSON -# Then the guzzle status code should be 200 -# Given that I want to find a "Post" -# And that the request "Authorization" header is "Bearer testadminuser" -# And that its "id" is "1" -# When I request "/posts" -# Then the response is JSON -# And the response has a "id" property -# And the response has a "title" property -# And the "title" property equals "Update test post title" diff --git a/tests/spec/Core/Usecase/Message/ReceiveMessageSpec.php b/tests/spec/Core/Usecase/Message/ReceiveMessageSpec.php index 86a7d62e34..e69734d025 100644 --- a/tests/spec/Core/Usecase/Message/ReceiveMessageSpec.php +++ b/tests/spec/Core/Usecase/Message/ReceiveMessageSpec.php @@ -81,9 +81,7 @@ private function createPostEntity($payload, $postRepo, $post) $postRepo->getEntity()->willReturn($post); $post->setState(['title' => $payload['title'], 'content' => $payload['message'], - 'values' => [], - 'form_id' => null - ])->willReturn($post); + 'values' => []])->willReturn($post); //$postRepo->create($post)->willReturn($post_id); }