mirror of
https://github.com/CachetHQ/Cachet.git
synced 2025-01-16 21:18:19 +01:00
Introduce the Subscriber API. Closes #787
This commit is contained in:
parent
38257c6ae6
commit
71f5de8726
77
app/Http/Controllers/Api/SubscriberController.php
Normal file
77
app/Http/Controllers/Api/SubscriberController.php
Normal file
@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Http\Controllers\Api;
|
||||
|
||||
use CachetHQ\Cachet\Events\CustomerHasSubscribedEvent;
|
||||
use CachetHQ\Cachet\Models\Subscriber;
|
||||
use Exception;
|
||||
use GrahamCampbell\Binput\Facades\Binput;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
|
||||
class SubscriberController extends AbstractApiController
|
||||
{
|
||||
/**
|
||||
* Get all subscribers.
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public function getSubscribers(Request $request)
|
||||
{
|
||||
$subscribers = Subscriber::paginate(Binput::get('per_page', 20));
|
||||
|
||||
return $this->paginator($subscribers, $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new subscriber.
|
||||
*
|
||||
* @return \CachetHQ\Cachet\Models\Subscriber
|
||||
*/
|
||||
public function postSubscribers()
|
||||
{
|
||||
$subscriberData = Binput::except('verify');
|
||||
|
||||
try {
|
||||
$subscriber = Subscriber::create($subscriberData);
|
||||
} catch (Exception $e) {
|
||||
throw new BadRequestHttpException();
|
||||
}
|
||||
|
||||
if ($subscriber->isValid()) {
|
||||
// If we're auto-verifying the subscriber, don't bother with this event.
|
||||
if (!(Binput::get('verify'))) {
|
||||
event(new CustomerHasSubscribedEvent($subscriber));
|
||||
}
|
||||
|
||||
return $this->item($subscriber);
|
||||
}
|
||||
|
||||
throw new BadRequestHttpException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a subscriber.
|
||||
*
|
||||
* @param \CachetHQ\Cachet\Models\Subscriber $subscriber
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function deleteSubscriber(Subscriber $subscriber)
|
||||
{
|
||||
$subscriber->delete();
|
||||
|
||||
return $this->noContent();
|
||||
}
|
||||
}
|
@ -45,10 +45,13 @@ class ApiRoutes
|
||||
|
||||
// Api protected
|
||||
$router->group(['middleware' => 'auth.api'], function ($router) {
|
||||
$router->get('subscribers', 'SubscriberController@getSubscribers');
|
||||
|
||||
$router->post('components', 'ComponentController@postComponents');
|
||||
$router->post('incidents', 'IncidentController@postIncidents');
|
||||
$router->post('metrics', 'MetricController@postMetrics');
|
||||
$router->post('metrics/{metric}/points', 'MetricPointController@postMetricPoints');
|
||||
$router->post('subscribers', 'SubscriberController@postSubscribers');
|
||||
|
||||
$router->put('components/{component}', 'ComponentController@putComponent');
|
||||
$router->put('incidents/{incident}', 'IncidentController@putIncident');
|
||||
@ -59,6 +62,7 @@ class ApiRoutes
|
||||
$router->delete('incidents/{incident}', 'IncidentController@deleteIncident');
|
||||
$router->delete('metrics/{metric}', 'MetricController@deleteMetric');
|
||||
$router->delete('metrics/{metric}/points/{metric_point}', 'MetricPointController@deleteMetricPoint');
|
||||
$router->delete('subscribers/{subscriber}', 'SubscriberController@deleteSubscriber');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -11,11 +11,13 @@
|
||||
|
||||
namespace CachetHQ\Cachet\Models;
|
||||
|
||||
use CachetHQ\Cachet\Presenters\SubscriberPresenter;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use McCool\LaravelAutoPresenter\HasPresenter;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
|
||||
class Subscriber extends Model
|
||||
class Subscriber extends Model implements HasPresenter
|
||||
{
|
||||
use SoftDeletes, ValidatingTrait;
|
||||
|
||||
@ -75,4 +77,14 @@ class Subscriber extends Model
|
||||
{
|
||||
return str_random(42);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the presenter class.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPresenterClass()
|
||||
{
|
||||
return SubscriberPresenter::class;
|
||||
}
|
||||
}
|
||||
|
33
app/Presenters/SubscriberPresenter.php
Normal file
33
app/Presenters/SubscriberPresenter.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Cachet\Presenters;
|
||||
|
||||
use CachetHQ\Cachet\Presenters\Traits\TimestampsTrait;
|
||||
|
||||
class SubscriberPresenter extends AbstractPresenter
|
||||
{
|
||||
use TimestampsTrait;
|
||||
|
||||
/**
|
||||
* Convert the presenter instance to an array.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
return array_merge($this->wrappedObject->toArray(), [
|
||||
'created_at' => $this->created_at(),
|
||||
'updated_at' => $this->updated_at(),
|
||||
'verified_at' => $this->verified_at(),
|
||||
]);
|
||||
}
|
||||
}
|
@ -47,4 +47,15 @@ trait TimestampsTrait
|
||||
return (new Date($this->wrappedObject->deleted_at))
|
||||
->setTimezone($this->setting->get('app_timezone'))->toDateTimeString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Present formatted date time.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function verified_at()
|
||||
{
|
||||
return (new Date($this->wrappedObject->verified_at))
|
||||
->setTimezone($this->setting->get('app_timezone'))->toDateTimeString();
|
||||
}
|
||||
}
|
||||
|
@ -39,7 +39,8 @@
|
||||
"require-dev": {
|
||||
"fzaninotto/faker": "^1.5",
|
||||
"phpunit/phpunit": "^4.7.6",
|
||||
"laravel/homestead": "^2.1"
|
||||
"laravel/homestead": "^2.1",
|
||||
"mockery/mockery": "~0.9.4"
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
|
114
composer.lock
generated
114
composer.lock
generated
@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"hash": "94c9c02a89e02e83d24580aa8ac901bf",
|
||||
"hash": "8535c80a786ed3bcac0a4d7d77421697",
|
||||
"packages": [
|
||||
{
|
||||
"name": "alt-three/segment",
|
||||
@ -1546,7 +1546,7 @@
|
||||
"name": "Jeremy Lindblom",
|
||||
"email": "jeremeamia@gmail.com",
|
||||
"homepage": "https://github.com/jeremeamia",
|
||||
"role": "developer"
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "Serialize Closure objects, including their context and binding",
|
||||
@ -3376,6 +3376,51 @@
|
||||
],
|
||||
"time": "2015-05-29 06:29:14"
|
||||
},
|
||||
{
|
||||
"name": "hamcrest/hamcrest-php",
|
||||
"version": "v1.2.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/hamcrest/hamcrest-php.git",
|
||||
"reference": "b37020aa976fa52d3de9aa904aa2522dc518f79c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/b37020aa976fa52d3de9aa904aa2522dc518f79c",
|
||||
"reference": "b37020aa976fa52d3de9aa904aa2522dc518f79c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.2"
|
||||
},
|
||||
"replace": {
|
||||
"cordoval/hamcrest-php": "*",
|
||||
"davedevelopment/hamcrest-php": "*",
|
||||
"kodova/hamcrest-php": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/php-file-iterator": "1.3.3",
|
||||
"satooshi/php-coveralls": "dev-master"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"hamcrest"
|
||||
],
|
||||
"files": [
|
||||
"hamcrest/Hamcrest.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD"
|
||||
],
|
||||
"description": "This is the PHP port of Hamcrest Matchers",
|
||||
"keywords": [
|
||||
"test"
|
||||
],
|
||||
"time": "2015-05-11 14:41:42"
|
||||
},
|
||||
{
|
||||
"name": "laravel/homestead",
|
||||
"version": "v2.1.5",
|
||||
@ -3417,6 +3462,71 @@
|
||||
"description": "A virtual machine for web artisans.",
|
||||
"time": "2015-07-23 14:53:43"
|
||||
},
|
||||
{
|
||||
"name": "mockery/mockery",
|
||||
"version": "0.9.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/padraic/mockery.git",
|
||||
"reference": "70bba85e4aabc9449626651f48b9018ede04f86b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/padraic/mockery/zipball/70bba85e4aabc9449626651f48b9018ede04f86b",
|
||||
"reference": "70bba85e4aabc9449626651f48b9018ede04f86b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"hamcrest/hamcrest-php": "~1.1",
|
||||
"lib-pcre": ">=7.0",
|
||||
"php": ">=5.3.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "0.9.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Mockery": "library/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Pádraic Brady",
|
||||
"email": "padraic.brady@gmail.com",
|
||||
"homepage": "http://blog.astrumfutura.com"
|
||||
},
|
||||
{
|
||||
"name": "Dave Marshall",
|
||||
"email": "dave.marshall@atstsolutions.co.uk",
|
||||
"homepage": "http://davedevelopment.co.uk"
|
||||
}
|
||||
],
|
||||
"description": "Mockery is a simple yet flexible PHP mock object framework for use in unit testing with PHPUnit, PHPSpec or any other testing framework. Its core goal is to offer a test double framework with a succinct API capable of clearly defining all possible object operations and interactions using a human readable Domain Specific Language (DSL). Designed as a drop in alternative to PHPUnit's phpunit-mock-objects library, Mockery is easy to integrate with PHPUnit and can operate alongside phpunit-mock-objects without the World ending.",
|
||||
"homepage": "http://github.com/padraic/mockery",
|
||||
"keywords": [
|
||||
"BDD",
|
||||
"TDD",
|
||||
"library",
|
||||
"mock",
|
||||
"mock objects",
|
||||
"mockery",
|
||||
"stub",
|
||||
"test",
|
||||
"test double",
|
||||
"testing"
|
||||
],
|
||||
"time": "2015-04-02 19:54:00"
|
||||
},
|
||||
{
|
||||
"name": "phpdocumentor/reflection-docblock",
|
||||
"version": "2.0.4",
|
||||
|
@ -9,6 +9,8 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use Carbon\Carbon;
|
||||
|
||||
$factory->define('CachetHQ\Cachet\Models\User', function ($faker) {
|
||||
return [
|
||||
'username' => $faker->userName,
|
||||
@ -57,3 +59,11 @@ $factory->define('CachetHQ\Cachet\Models\MetricPoint', function ($faker) {
|
||||
'value' => rand(1, 100),
|
||||
];
|
||||
});
|
||||
|
||||
$factory->define('CachetHQ\Cachet\Models\Subscriber', function ($faker) {
|
||||
return [
|
||||
'email' => $faker->email,
|
||||
'verify_code' => 'Mqr80r2wJtxHCW5Ep4azkldFfIwHhw98M9HF04dn0z',
|
||||
'verified_at' => Carbon::now(),
|
||||
];
|
||||
});
|
||||
|
@ -26,7 +26,7 @@
|
||||
<php>
|
||||
<env name="APP_ENV" value="testing"/>
|
||||
<env name="APP_URL" value="http://localhost"/>
|
||||
<env name="APP_KEY" value="AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"/>
|
||||
<env name="APP_KEY" value="GCvcgDKMRIN498g52zfVEd9CxDs6PR7q"/>
|
||||
<env name="DB_DRIVER" value="sqlite"/>
|
||||
<env name="DB_HOST" value=":memory:"/>
|
||||
<env name="CACHE_DRIVER" value="array"/>
|
||||
|
75
tests/Api/SubscriberTest.php
Normal file
75
tests/Api/SubscriberTest.php
Normal file
@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Cachet.
|
||||
*
|
||||
* (c) Alt Three Services Limited
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace CachetHQ\Tests\Cachet\Api;
|
||||
|
||||
use CachetHQ\Tests\Cachet\AbstractTestCase;
|
||||
use Illuminate\Foundation\Testing\DatabaseMigrations;
|
||||
// use Illuminate\Foundation\Testing\WithoutEvents;
|
||||
|
||||
class SubscriberTest extends AbstractTestCase
|
||||
{
|
||||
use DatabaseMigrations;
|
||||
|
||||
public function testGetSubscribersUnauthenticated()
|
||||
{
|
||||
$this->get('/api/v1/subscribers');
|
||||
$this->assertResponseStatus(401);
|
||||
$this->seeHeader('Content-Type', 'application/json');
|
||||
}
|
||||
|
||||
public function testGetSubscribers()
|
||||
{
|
||||
$this->beUser();
|
||||
|
||||
$subscriber = factory('CachetHQ\Cachet\Models\Subscriber')->create();
|
||||
|
||||
$this->get('/api/v1/subscribers');
|
||||
$this->seeHeader('Content-Type', 'application/json');
|
||||
$this->assertResponseOk();
|
||||
}
|
||||
|
||||
public function testCreateSubscriber()
|
||||
{
|
||||
$this->beUser();
|
||||
|
||||
$this->expectsEvents('CachetHQ\Cachet\Events\CustomerHasSubscribedEvent');
|
||||
|
||||
$this->post('/api/v1/subscribers', [
|
||||
'email' => 'james@cachethq.io',
|
||||
]);
|
||||
$this->assertResponseOk();
|
||||
$this->seeHeader('Content-Type', 'application/json');
|
||||
$this->seeJson(['email' => 'james@cachethq.io']);
|
||||
}
|
||||
|
||||
public function testCreateSubscriberAutoVerified()
|
||||
{
|
||||
$this->beUser();
|
||||
|
||||
$this->post('/api/v1/subscribers', [
|
||||
'email' => 'james@cachethq.io',
|
||||
'verify' => true,
|
||||
]);
|
||||
$this->assertResponseOk();
|
||||
$this->seeHeader('Content-Type', 'application/json');
|
||||
$this->seeJson(['email' => 'james@cachethq.io']);
|
||||
}
|
||||
|
||||
public function testDeleteSubscriber()
|
||||
{
|
||||
$this->beUser();
|
||||
|
||||
$subscriber = factory('CachetHQ\Cachet\Models\Subscriber')->create();
|
||||
$this->delete("/api/v1/subscribers/{$subscriber->id}");
|
||||
$this->assertResponseStatus(204);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user