Skip to content

Commit

Permalink
Merge pull request #1665 from ushahidi/1550-platform-api-receive
Browse files Browse the repository at this point in the history
1550 platform api receive [WIP]
  • Loading branch information
willdoran authored Feb 7, 2018
2 parents 708b522 + 6fca3c9 commit 50b6759
Show file tree
Hide file tree
Showing 49 changed files with 1,142 additions and 155 deletions.
18 changes: 18 additions & 0 deletions application/classes/Controller/Api/Apikeys.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');

/**
* Ushahidi API Keys Controller
*
* @author Ushahidi Team <team@ushahidi.com>
* @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';
}
}
67 changes: 67 additions & 0 deletions application/classes/Controller/Api/Webhooks/Posts.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');

/**
* Ushahidi API External Webhook Posts Controller
*
* @author Ushahidi Team <team@ushahidi.com>
* @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());
}
}
47 changes: 33 additions & 14 deletions application/classes/Ushahidi/Console/Webhook.php
Original file line number Diff line number Diff line change
Expand Up @@ -105,27 +105,46 @@ 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
$webhook = $this->webhookRepository->getByEventType($webhook_request->event_type);
$webhooks = $this->webhookRepository->getAllByEventType($webhook_request->event_type);

$this->signer = new Signer($webhook->shared_secret);
foreach ($webhooks as $webhook) {

$signature = $this->signer->sign($webhook->url, $json);
if ($post->form_id == $webhook['form_id']) {
$this->signer = new Signer($webhook['shared_secret']);

// 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()
]);
$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
]);

}
}
}
}
11 changes: 10 additions & 1 deletion application/classes/Ushahidi/Core.php
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,8 @@ public static function init()
];
$di->params['Ushahidi\Factory\ValidatorFactory']['map']['posts'] = [
'create' => $di->lazyNew('Ushahidi_Validator_Post_Create'),
'update' => $di->lazyNew('Ushahidi_Validator_Post_Create'),

This comment has been minimized.

Copy link
@rjmackay

rjmackay Feb 8, 2018

Contributor

@willdoran spotted this while merging to lumen. Any idea why this changed? I leaves up with duplicate entries for update but one points to create? Probably just merge failure...

This comment has been minimized.

Copy link
@willdoran

willdoran Mar 20, 2018

Author Contributor

This was already fixed, this merge appears to not include that fix.

'webhook-update' => $di->lazyNew('Ushahidi_Validator_Post_Create'),
'update' => $di->lazyNew('Ushahidi_Validator_Post_Update'),
'import' => $di->lazyNew('Ushahidi_Validator_Post_Import'),
];
Expand Down Expand Up @@ -287,6 +289,10 @@ 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'),
Expand Down Expand Up @@ -339,7 +345,8 @@ 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'),
'webhooks' => $di->lazyNew('Ushahidi_Formatter_Webhook'),
'apikeys' => $di->lazyNew('Ushahidi_Formatter_Apikey'),
'contacts' => $di->lazyNew('Ushahidi_Formatter_Contact'),
'csv' => $di->lazyNew('Ushahidi_Formatter_CSV'),
'roles' => $di->lazyNew('Ushahidi_Formatter_Role'),
Expand Down Expand Up @@ -368,6 +375,7 @@ public static function init()
'set_post',
'notification',
'webhook',
'apikey',
'contact',
'role',
'permission',
Expand Down Expand Up @@ -436,6 +444,7 @@ 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'));
Expand Down
4 changes: 2 additions & 2 deletions application/classes/Ushahidi/DataProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,15 @@ 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, $data_provider_message_id = NULL, Array $additional_data = NULL)
public function receive($type, $from, $message, $to = NULL, $title = NULL, $date = NULL, $data_provider_message_id = NULL, Array $additional_data = NULL)
{
$data_provider = $this->provider_name();
$contact_type = $this->contact_type;

$usecase = service('factory.usecase')->get('messages', 'receive');
try
{
$usecase->setPayload(compact(['type', 'from', 'message', 'to', 'title', 'data_provider_message_id', 'data_provider', 'contact_type', 'additional_data']))
$usecase->setPayload(compact(['type', 'from', 'message', 'to', 'title', 'date', 'data_provider_message_id', 'data_provider', 'contact_type', 'additional_data']))
->interact();
}
catch (Ushahidi\Core\Exception\NotFoundException $e)
Expand Down
17 changes: 17 additions & 0 deletions application/classes/Ushahidi/Formatter/Apikey.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');

/**
* Ushahidi API Formatter for Api Keys
*
* @author Ushahidi Team <team@ushahidi.com>
* @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;
}
88 changes: 88 additions & 0 deletions application/classes/Ushahidi/Repository/ApiKey.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');

/**
* Ushahidi ApiKey Repository
*
* @author Ushahidi Team <team@ushahidi.com>
* @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 [
];
}
}
Loading

0 comments on commit 50b6759

Please sign in to comment.