Skip to content

Commit

Permalink
Merge branch 'develop' into V5/improve-performance
Browse files Browse the repository at this point in the history
  • Loading branch information
tuxpiper authored Jun 28, 2022
2 parents 67df3b9 + 872c918 commit 97d5455
Show file tree
Hide file tree
Showing 7 changed files with 210 additions and 14 deletions.
35 changes: 26 additions & 9 deletions src/App/Repository/ConfigRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ public function get($group)
{
$this->verifyGroup($group);

if ($group == 'multisite') {
return $this->getMultisiteGroup();
if ($group == 'deployment_id') {
return $this->getDeploymentIdGroup();
}

$config = [];
Expand Down Expand Up @@ -112,20 +112,37 @@ public function get($group)
return $this->getEntity(['id' => $group] + $config);
}

protected function getMultisiteGroup()
protected function getDeploymentIdGroup()
{
// The multisite group is special in that it's not persisted in the deployment's database.
// The Deployment Id group is special in that it's not persisted in the deployment's database.
$config = [];

// Multisite IDs
if (app('multisite')->enabled()) {
$multi = app('multisite');
$config = [
$config['multisite'] = [
'enabled' => true,
'site_id' => $multi->getSiteId(),
'site_fqdn' => $multi->site->getClientUri(),
];
} else {
$config = [ 'enabled' => false ];
$config['multisite'] = [];
}
return $this->getEntity(['id' => 'multisite'] + $config);

$analytics_prefix = env('USH_ANALYTICS_PREFIX', null);
$analytics_id =
$config['multisite']['site_id'] ??
env('USH_ANALYTICS_ID', null);
if ($analytics_prefix && $analytics_id) {
$config['analytics'] = [
'prefix' => $analytics_prefix,
'id' => $analytics_id,
];
} else {
$config['analytics'] = [];
}

return $this->getEntity(['id' => 'deployment_id'] + $config);
}

// UpdateRepository
Expand All @@ -136,7 +153,7 @@ public function update(Entity $entity)

$this->verifyGroup($group);

if ($group == 'multisite') {
if ($group == 'deployment_id') {
return; /* noop */
}

Expand Down Expand Up @@ -205,7 +222,7 @@ public function groups()
return [
'features',
'site',
'multisite',
'deployment_id',
'test',
'data-provider',
'map',
Expand Down
4 changes: 2 additions & 2 deletions src/Core/Tools/Authorizer/ConfigAuthorizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,13 @@ class ConfigAuthorizer implements Authorizer
* Public config groups
* @var [string, ...]
*/
protected $public_groups = ['features', 'map', 'site', 'multisite'];
protected $public_groups = ['features', 'map', 'site', 'deployment_id'];

/**
* Public config groups
* @var [string, ...]
*/
protected $readonly_groups = ['features', 'multisite'];
protected $readonly_groups = ['features', 'deployment_id'];

/* Authorizer */
public function isAllowed(Entity $entity, $privilege)
Expand Down
153 changes: 153 additions & 0 deletions v5/Http/Controllers/USSDController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
<?php

namespace v5\Http\Controllers;

use Ramsey\Uuid\Uuid as UUID;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

use v5\Http\Resources\PostResource;
use v5\Models\Message;
use v5\Models\Contact;
use v5\Models\Post\Post;
use v5\Common\ValidatorRunner;

/**
* ---> WARNING: This is a crutch <---
*
* We are adding this specific controller for posts coming from USSD sources,
* so that incoming posts can have contact information attached, just like SMS.
*
* Eventually we should have a more evolved data source framework that allows
* bringing in structured posts with source metadata.
*/
class USSDController extends PostController
{
public function show(int $id)
{
throw new Exception("Invalid controller method");
}

public function index()
{
throw new Exception("Invalid controller method");
}

/**
* Overriding the POST method so as to handle contact information
*/
public function store(Request $request)
{
/* TODO: USSD-specific authorization?
*
* Presently the assumption is that these come in anonymously,
* because that's how ussd-engine operates.
* But what would happen if they came in as an authenticated user?
* What would be considered the source of the post? The user, or
* the detailed shource information.
*
* As we are thinking of more loosely coupled datasources, this
* should be taken into account.
*/

/* This method works on an additional property to the post body:
*
* {
* ...,
* source_info: {
* received: "YYYY-MM-DDTHH:MM:SSZ",
* data_source: "ussd",
* type: "phone",
* contact: "xxxxxxxxx"
* }
* ...
* }
*
* Validate this property from the request.
*/
$source_info = $request->input('source_info');
$val_rules = [
'source_info' => 'required',
// TODO: couldn't get this validation just right yet
// 'source_info.received' => 'required|string|date_format:' . \DateTime::ISO8601,
'source_info.data_source' => 'required|string|in:ussd',
'source_info.type' => 'required|string|in:phone',
'source_info.contact' => 'required|string|min:6'
];
$v = ValidatorRunner::runValidation(
['source_info' => $source_info],
$val_rules,
[] // TODO: custom messages?
);
if ($v->fails()) {
return self::make422($v->getErrors());
}

/* Call up the parent controller to get the post created */
$post = parent::store($request);
if (!($post instanceof PostResource)) {
/* An error has happened creating the post, shortcircuit to that */
return $post;
}

DB::beginTransaction();
try {
/* Lookup / create contact if not present */
/* assert type is phone */
$contact = Contact::firstOrCreate([
'data_source' => $source_info['data_source'],
'type' => $source_info['type'],
'contact' => $source_info['contact']
], [
'can_notify' => false
]);

/* Create message record */
$message = new Message;
$message->contact()->associate($contact)->save();
$message->post_id = $post->id; // this is not yet an eloquent-managed relationship
/* USSD doesn't technically come in with a message, we shall craft
* a stand-in. */
$message->title = "(Fulfilled USSD survey)";
/* TODO: anything more useful that could go here? */
$message->message = "(Fulfilled USSD survey)";
$message->datetime = \DateTime::createFromFormat(\DateTime::ISO8601, $source_info['received']);
$message->data_source = $source_info['data_source'];
/* TODO: anything useful from ussd-engine that could go here? */
$message->data_source_message_id = "random-" . UUID::uuid4()->toString();
$message->type = 'ussd';
$message->status = 'received';
$message->direction = 'incoming';
$message->notification_post_id = null;
$message->save();

DB::commit();

/* The post resource should now be re-rendered, because of the
* information added to it since creation in the parent.
* This is not ideal performance-wise, but we'll take the hit
* for now.
*/
return new PostResource($post->resource);
} catch (\Exception $e) {
DB::rollback();
return self::make500($e->getMessage());
}
}

public function patch(int $id, Request $request)
{
throw new Exception("Invalid controller method");
}

public function update(int $id, Request $request)
{
throw new Exception("Invalid controller method");
}

public function delete(int $id, Request $request)
{
throw new Exception("Invalid controller method");
}
}
6 changes: 5 additions & 1 deletion v5/Http/Middleware/V5GlobalScopes.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@ public function handle($request, Closure $next)
* @TODO more tests maybe????????
* @TODO remove the need for isSavingPost
*/
$isSavingPost = $request->path() === 'api/v5/posts' && $request->isMethod('post');
$isSavingPost = $request->isMethod('post') && \
in_array($request->path(), [
'api/v5/posts',
'api/v5/posts/_ussd'
]);

if (!$isSavingPost) {
Category::addGlobalScope(new CategoryAllowed);
Expand Down
12 changes: 11 additions & 1 deletion v5/Models/Contact.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,22 @@ class Contact extends BaseModel
'messages'
];

const CREATED_AT = 'created';
const UPDATED_AT = 'updated';

/**
* Add eloquent style timestamps
*
* @var boolean
*/
public $timestamps = false;
public $timestamps = true;

/**
* The storage format of the model's date columns.
*
* @var string
*/
protected $dateFormat = 'U';

/**
* Specify the table to load with Survey
Expand Down
13 changes: 12 additions & 1 deletion v5/Models/Message.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,24 @@ class Message extends BaseModel
public static $relationships = [
'contact'
];
# --> and relationship to Post?
const CREATED_AT = 'created';
const UPDATED_AT = null;

/**
* Add eloquent style timestamps
*
* @var boolean
*/
public $timestamps = false;
public $timestamps = true;

/**
* The storage format of the model's date columns.
*
* @var string
*/
protected $dateFormat = 'U';

/**
* Specify the table to load with Survey
Expand Down
1 change: 1 addition & 0 deletions v5/routes/api.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,5 +82,6 @@
], function () use ($router) {
// Public access
$router->post('/', 'PostController@store');
$router->post('/_ussd', 'USSDController@store');
});
});

0 comments on commit 97d5455

Please sign in to comment.