Merge branch 'release/0.9'

This commit is contained in:
Jonny Barnes 2017-10-06 16:05:21 +01:00
commit b33c0cca08
27 changed files with 480 additions and 93 deletions

View file

@ -0,0 +1,20 @@
<?php
namespace App\Http\Controllers;
use App\Like;
class LikesController extends Controller
{
public function index()
{
$likes = Like::latest()->paginate(20);
return view('likes.index', compact('likes'));
}
public function show(Like $like)
{
return view('likes.show', compact('like'));
}
}

View file

@ -6,8 +6,9 @@ use Storage;
use Monolog\Logger; use Monolog\Logger;
use Ramsey\Uuid\Uuid; use Ramsey\Uuid\Uuid;
use App\Jobs\ProcessImage; use App\Jobs\ProcessImage;
use App\{Media, Note, Place}; use App\Services\LikeService;
use Monolog\Handler\StreamHandler; use Monolog\Handler\StreamHandler;
use App\{Like, Media, Note, Place};
use Intervention\Image\ImageManager; use Intervention\Image\ImageManager;
use Illuminate\Http\{Request, Response}; use Illuminate\Http\{Request, Response};
use App\Exceptions\InvalidTokenException; use App\Exceptions\InvalidTokenException;
@ -73,6 +74,14 @@ class MicropubController extends Controller
if (stristr($tokenData->getClaim('scope'), 'create') === false) { if (stristr($tokenData->getClaim('scope'), 'create') === false) {
return $this->returnInsufficientScopeResponse(); return $this->returnInsufficientScopeResponse();
} }
if ($request->has('properties.like-of') || $request->has('like-of')) {
$like = (new LikeService())->createLike($request);
return response()->json([
'response' => 'created',
'location' => config('app.url') . "/likes/$like->id",
], 201)->header('Location', config('app.url') . "/likes/$like->id");
}
$data = []; $data = [];
$data['client-id'] = $tokenData->getClaim('client_id'); $data['client-id'] = $tokenData->getClaim('client_id');
if ($request->header('Content-Type') == 'application/json') { if ($request->header('Content-Type') == 'application/json') {

View file

@ -22,14 +22,13 @@ class NotesController extends Controller
return (new ActivityStreamsService)->siteOwnerResponse(); return (new ActivityStreamsService)->siteOwnerResponse();
} }
$notes = Note::orderBy('id', 'desc') $notes = Note::latest()
->with('place', 'media', 'client') ->with('place', 'media', 'client')
->withCount(['webmentions As replies' => function ($query) { ->withCount(['webmentions As replies' => function ($query) {
$query->where('type', 'in-reply-to'); $query->where('type', 'in-reply-to');
}])->paginate(10); }])->paginate(10);
$aslink = config('app.url');
return view('notes.index', compact('notes', 'aslink')); return view('notes.index', compact('notes'));
} }
/** /**
@ -46,9 +45,7 @@ class NotesController extends Controller
return (new ActivityStreamsService)->singleNoteResponse($note); return (new ActivityStreamsService)->singleNoteResponse($note);
} }
$aslink = $note->longurl; return view('notes.show', compact('note'));
return view('notes.show', compact('note', 'aslink'));
} }
/** /**

View file

@ -38,6 +38,7 @@ class Kernel extends HttpKernel
\App\Http\Middleware\LinkHeadersMiddleware::class, \App\Http\Middleware\LinkHeadersMiddleware::class,
//\App\Http\Middleware\DevTokenMiddleware::class, //\App\Http\Middleware\DevTokenMiddleware::class,
\App\Http\Middleware\LocalhostSessionMiddleware::class, \App\Http\Middleware\LocalhostSessionMiddleware::class,
\App\Http\Middleware\ActivityStreamLinks::class,
], ],
'api' => [ 'api' => [

View file

@ -0,0 +1,28 @@
<?php
namespace App\Http\Middleware;
use Closure;
class ActivityStreamLinks
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$response = $next($request);
if ($request->path() === '/') {
$response->header('Link', '<' . config('app.url') . '>; rel="application/activity+json"', false);
}
if ($request->is('notes/*')) {
$response->header('Link', '<' . $request->url() . '>; rel="application/activity+json"', false);
}
return $response;
}
}

59
app/Jobs/ProcessLike.php Normal file
View file

@ -0,0 +1,59 @@
<?php
namespace App\Jobs;
use App\Like;
use GuzzleHttp\Client;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Jonnybarnes\WebmentionsParser\Authorship;
use Jonnybarnes\WebmentionsParser\Exceptions\AuthorshipParserException;
class ProcessLike implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $like;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct(Like $like)
{
$this->like = $like;
}
/**
* Execute the job.
*
* @return void
*/
public function handle(Client $client, Authorship $authorship)
{
$response = $client->request('GET', $this->like->url);
$mf2 = \Mf2\parse((string) $response->getBody(), $this->like->url);
if (array_has($mf2, 'items.0.properties.content')) {
$this->like->content = $mf2['items'][0]['properties']['content'][0]['html'];
}
try {
$author = $authorship->findAuthor($mf2);
if (is_array($author)) {
$this->like->author_name = $author['name'];
$this->like->author_url = $author['url'];
}
if (is_string($author) && $author !== '') {
$this->like->author_name = $author;
}
} catch (AuthorshipParserException $exception) {
return;
}
$this->like->save();
}
}

View file

@ -40,6 +40,7 @@ class SyndicateToFacebook implements ShouldQueue
'form_params' => [ 'form_params' => [
'source' => $this->note->longurl, 'source' => $this->note->longurl,
'target' => 'https://brid.gy/publish/facebook', 'target' => 'https://brid.gy/publish/facebook',
'bridgy_omit_link' => 'maybe',
], ],
] ]
); );

View file

@ -41,6 +41,7 @@ class SyndicateToTwitter implements ShouldQueue
'form_params' => [ 'form_params' => [
'source' => $this->note->longurl, 'source' => $this->note->longurl,
'target' => 'https://brid.gy/publish/twitter', 'target' => 'https://brid.gy/publish/twitter',
'bridgy_omit_link' => 'maybe',
], ],
] ]
); );

44
app/Like.php Normal file
View file

@ -0,0 +1,44 @@
<?php
namespace App;
use Mf2;
use HTMLPurifier;
use HTMLPurifier_Config;
use Illuminate\Database\Eloquent\Model;
class Like extends Model
{
protected $fillable = ['url'];
public function setUrlAttribute($value)
{
$this->attributes['url'] = normalize_url($value);
}
public function setAuthorUrlAttribute($value)
{
$this->attributes['author_url'] = normalize_url($value);
}
public function getContentAttribute($value)
{
if ($value === null) {
return $this->url;
}
$mf2 = Mf2\parse($value, $this->url);
return $this->filterHTML($mf2['items'][0]['properties']['content'][0]['html']);
}
public function filterHTML($html)
{
$config = HTMLPurifier_Config::createDefault();
$config->set('Cache.SerializerPath', storage_path() . '/HTMLPurifier');
$config->set('HTML.TargetBlank', true);
$purifier = new HTMLPurifier($config);
return $purifier->purify($html);
}
}

View file

@ -0,0 +1,37 @@
<?php
declare(strict_types=1);
namespace App\Services;
use App\Like;
use App\Jobs\ProcessLike;
use Illuminate\Http\Request;
class LikeService
{
/**
* Create a new Like.
*
* @param Request $request
*/
public function createLike(Request $request): Like
{
if ($request->header('Content-Type') == 'application/json') {
//micropub request
$url = normalize_url($request->input('properties.like-of.0'));
}
if (
($request->header('Content-Type') == 'x-www-url-formencoded')
||
($request->header('Content-Type') == 'multipart/form-data')
) {
$url = normalize_url($request->input('like-of'));
}
$like = Like::create(['url' => $url]);
ProcessLike::dispatch($like);
return $like;
}
}

View file

@ -1,5 +1,13 @@
# Changelog # Changelog
## Version 0.9 (2017-10-06)
- Add support for `likes` (issue#69)
- Only included links on truncated syndicated notes https://brid.gy/about#omit-link
## Version 0.8.1 (2017-09-16)
- Order notes by latest (issue#70)
- AcitivtyStream support is now indicated with HTTP Link headers
## Version 0.8 (2017-09-16) ## Version 0.8 (2017-09-16)
- Improve embedding of tweets (issue#66) - Improve embedding of tweets (issue#66)
- Allow for “responsive” images (issue#62) - Allow for “responsive” images (issue#62)

20
composer.lock generated
View file

@ -8,16 +8,16 @@
"packages": [ "packages": [
{ {
"name": "aws/aws-sdk-php", "name": "aws/aws-sdk-php",
"version": "3.36.7", "version": "3.36.9",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/aws/aws-sdk-php.git", "url": "https://github.com/aws/aws-sdk-php.git",
"reference": "421088947540b1c7956cd693b032124e2c74eb76" "reference": "7b89fa65cccb966da1599b715dcea8c09eafc175"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/421088947540b1c7956cd693b032124e2c74eb76", "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/7b89fa65cccb966da1599b715dcea8c09eafc175",
"reference": "421088947540b1c7956cd693b032124e2c74eb76", "reference": "7b89fa65cccb966da1599b715dcea8c09eafc175",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -84,7 +84,7 @@
"s3", "s3",
"sdk" "sdk"
], ],
"time": "2017-09-13T18:56:17+00:00" "time": "2017-09-15T19:12:04+00:00"
}, },
{ {
"name": "barnabywalters/mf-cleaner", "name": "barnabywalters/mf-cleaner",
@ -2085,16 +2085,16 @@
}, },
{ {
"name": "laravel/scout", "name": "laravel/scout",
"version": "v3.0.9", "version": "v3.0.10",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/laravel/scout.git", "url": "https://github.com/laravel/scout.git",
"reference": "84762c8ed51cb57f09b5f465e09993e48baf9d55" "reference": "681c15a26bbc973528af2e77e0bb61981dc07206"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/laravel/scout/zipball/84762c8ed51cb57f09b5f465e09993e48baf9d55", "url": "https://api.github.com/repos/laravel/scout/zipball/681c15a26bbc973528af2e77e0bb61981dc07206",
"reference": "84762c8ed51cb57f09b5f465e09993e48baf9d55", "reference": "681c15a26bbc973528af2e77e0bb61981dc07206",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -2146,7 +2146,7 @@
"laravel", "laravel",
"search" "search"
], ],
"time": "2017-09-13T18:24:31+00:00" "time": "2017-09-14T12:32:30+00:00"
}, },
{ {
"name": "laravel/tinker", "name": "laravel/tinker",

View file

@ -0,0 +1,12 @@
<?php
use Faker\Generator as Faker;
$factory->define(App\Like::class, function (Faker $faker) {
return [
'url' => $faker->url,
'author_name' => $faker->name,
'author_url' => $faker->url,
'content' => '<html><body><div class="h-entry"><div class="e-content">' . $faker->realtext() . '</div></div></body></html>',
];
});

View file

@ -0,0 +1,35 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateLikesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('likes', function (Blueprint $table) {
$table->increments('id');
$table->string('url');
$table->string('author_name')->nullable();
$table->string('author_url')->nullable();
$table->text('content')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('likes');
}
}

View file

@ -18,5 +18,6 @@ class DatabaseSeeder extends Seeder
$this->call(NotesTableSeeder::class); $this->call(NotesTableSeeder::class);
$this->call(WebMentionsTableSeeder::class); $this->call(WebMentionsTableSeeder::class);
$this->call(IndieWebUserTableSeeder::class); $this->call(IndieWebUserTableSeeder::class);
$this->call(LikesTableSeeder::class);
} }
} }

View file

@ -0,0 +1,16 @@
<?php
use Illuminate\Database\Seeder;
class LikesTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
factory(App\Like::class, 10)->create();
}
}

View file

@ -12,6 +12,7 @@ class NotesTableSeeder extends Seeder
public function run() public function run()
{ {
factory(App\Note::class, 10)->create(); factory(App\Note::class, 10)->create();
sleep(1);
$noteWithPlace = App\Note::create([ $noteWithPlace = App\Note::create([
'note' => 'Having a #beer at the local. 🍺', 'note' => 'Having a #beer at the local. 🍺',
'tweet_id' => '123456789', 'tweet_id' => '123456789',
@ -19,17 +20,21 @@ class NotesTableSeeder extends Seeder
$place = App\Place::find(1); $place = App\Place::find(1);
$noteWithPlace->place()->associate($place); $noteWithPlace->place()->associate($place);
$noteWithPlace->save(); $noteWithPlace->save();
sleep(1);
$noteWithContact = App\Note::create([ $noteWithContact = App\Note::create([
'note' => 'Hi @tantek' 'note' => 'Hi @tantek'
]); ]);
sleep(1);
$noteWithContactPlusPic = App\Note::create([ $noteWithContactPlusPic = App\Note::create([
'note' => 'Hi @aaron', 'note' => 'Hi @aaron',
'client_id' => 'https://jbl5.dev/notes/new' 'client_id' => 'https://jbl5.dev/notes/new'
]); ]);
sleep(1);
$noteWithoutContact = App\Note::create([ $noteWithoutContact = App\Note::create([
'note' => 'Hi @bob', 'note' => 'Hi @bob',
'client_id' => 'https://quill.p3k.io' 'client_id' => 'https://quill.p3k.io'
]); ]);
sleep(1);
//copy aarons profile pic in place //copy aarons profile pic in place
$spl = new SplFileInfo(public_path() . '/assets/profile-images/aaronparecki.com'); $spl = new SplFileInfo(public_path() . '/assets/profile-images/aaronparecki.com');
if ($spl->isDir() === false) { if ($spl->isDir() === false) {
@ -40,6 +45,7 @@ class NotesTableSeeder extends Seeder
'note' => 'Note from somehwere', 'note' => 'Note from somehwere',
'location' => '53.499,-2.379' 'location' => '53.499,-2.379'
]); ]);
sleep(1);
$noteSyndicated = App\Note::create([ $noteSyndicated = App\Note::create([
'note' => 'This note has all the syndication targets', 'note' => 'This note has all the syndication targets',
'tweet_id' => '123456', 'tweet_id' => '123456',

View file

@ -0,0 +1,27 @@
@extends('master')
@section('title')
Likes «
@stop
@section('content')
<div class="h-feed">
@foreach($likes as $like)
<div class="h-entry">
<div class="h-cite u-like-of">
Liked <a class="u-url" href="{{ $like->url }}">a post</a> by
<span class="p-author h-card">
@isset($like->author_url)
<a class="u-url p-name" href="{{ $like->author_url }}">{{ $like->author_name }}</a>
@else
<span class="p-name">{{ $like->author_name }}</span>
@endisset
</span>:
<blockquote class="e-content">
{!! $like->content !!}
</blockquote>
</div>
</div>
@endforeach
</div>
@stop

View file

@ -0,0 +1,23 @@
@extends('master')
@section('title')
Like «
@stop
@section('content')
<div class="h-entry">
<div class="h-cite u-like-of">
Liked <a class="u-url" href="{{ $like->url }}">a post</a> by
<span class="p-author h-card">
@isset($like->author_url)
<a class="u-url p-name" href="{{ $like->author_url }}">{{ $like->author_name }}</a>
@else
<span class="p-name">{{ $like->author_name }}</span>
@endisset
</span>:
<blockquote class="e-content">
{!! $like->content !!}
</blockquote>
</div>
</div>
@stop

View file

@ -12,8 +12,6 @@
<link rel="alternate" type="application/rss+xml" title="Notes RSS Feed" href="/notes/feed.rss"> <link rel="alternate" type="application/rss+xml" title="Notes RSS Feed" href="/notes/feed.rss">
<link rel="alternate" type="application/atom+xml" title="Notes Atom Feed" href="/notes/feed.atom"> <link rel="alternate" type="application/atom+xml" title="Notes Atom Feed" href="/notes/feed.atom">
<link rel="alternate" type="application/json" title="Notes JSON Feed" href="/notes/feed.json"> <link rel="alternate" type="application/json" title="Notes JSON Feed" href="/notes/feed.json">
@isset($aslink) <link rel="alternate" type="application/activity+json" href="{{ $aslink }}">
@endisset
<link rel="openid.server" href="https://indieauth.com/openid"> <link rel="openid.server" href="https://indieauth.com/openid">
<link rel="openid.delegate" href="{{ config('app.url') }}"> <link rel="openid.delegate" href="{{ config('app.url') }}">
<link rel="authorization_endpoint" href="https://indieauth.com/auth"> <link rel="authorization_endpoint" href="https://indieauth.com/auth">

View file

@ -108,6 +108,12 @@ Route::group(['domain' => config('url.longurl')], function () {
}); });
Route::get('note/{id}', 'NotesController@redirect'); // for legacy note URLs Route::get('note/{id}', 'NotesController@redirect'); // for legacy note URLs
// Likes
Route::group(['prefix' => 'likes'], function () {
Route::get('/', 'LikesController@index');
Route::get('/{like}', 'LikesController@show');
});
// Micropub Client // Micropub Client
Route::group(['prefix' => 'micropub'], function () { Route::group(['prefix' => 'micropub'], function () {
Route::get('/create', 'MicropubClientController@create')->name('micropub-client'); Route::get('/create', 'MicropubClientController@create')->name('micropub-client');

View file

@ -0,0 +1,88 @@
<?php
namespace Tests\Feature;
use Queue;
use App\Like;
use Tests\TestCase;
use Tests\TestToken;
use GuzzleHttp\Client;
use App\Jobs\ProcessLike;
use Lcobucci\JWT\Builder;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Psr7\Response;
use GuzzleHttp\Handler\MockHandler;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Jonnybarnes\WebmentionsParser\Authorship;
use Illuminate\Foundation\Testing\DatabaseTransactions;
class LikesTest extends TestCase
{
use DatabaseTransactions, TestToken;
public function test_likes_page()
{
$response = $this->get('/likes');
$response->assertViewIs('likes.index');
}
public function test_single_like_page()
{
$response = $this->get('/likes');
$response->assertViewIs('likes.index');
}
public function test_like_micropub_request()
{
Queue::fake();
$response = $this->withHeaders([
'Authorization' => 'Bearer ' . $this->getToken(),
])->json('POST', '/api/post', [
'type' => ['h-entry'],
'properties' => [
'like-of' => ['https://example.org/blog-post'],
],
]);
$response->assertJson(['response' => 'created']);
Queue::assertPushed(ProcessLike::class);
$this->assertDatabaseHas('likes', ['url' => 'https://example.org/blog-post']);
}
public function test_process_like_job()
{
$like = new Like();
$like->url = 'http://example.org/note/id';
$like->save();
$id = $like->id;
$job = new ProcessLike($like);
$content = <<<END
<html>
<body>
<div class="h-entry">
<div class="e-content">
A post that I like.
</div>
by <span class="p-author">Fred Bloggs</span>
</div>
</body>
</html>
END;
$mock = new MockHandler([
new Response(200, [], $content),
new Response(200, [], $content),
]);
$handler = HandlerStack::create($mock);
$client = new Client(['handler' => $handler]);
$this->app->bind(Client::class, $client);
$authorship = new Authorship();
$job->handle($client, $authorship);
$this->assertEquals('Fred Bloggs', Like::find($id)->author_name);
}
}

View file

@ -38,6 +38,7 @@ class MicropubClientControllerTest extends TestCase
'mp-syndicate-to' => ['https://twitter.com/jonnybarnes', 'https://facebook.com/jonnybarnes'], 'mp-syndicate-to' => ['https://twitter.com/jonnybarnes', 'https://facebook.com/jonnybarnes'],
] ]
); );
$expected = '{"type":["h-entry"],"properties":{"content":["Hello Fred"],"in-reply-to":["https:\/\/fredbloggs.com\/note\/abc"],"mp-syndicate-to":["https:\/\/twitter.com\/jonnybarnes","https:\/\/facebook.com\/jonnybarnes"]}}'; $expected = '{"type":["h-entry"],"properties":{"content":["Hello Fred"],"in-reply-to":["https:\/\/fredbloggs.com\/note\/abc"],"mp-syndicate-to":["https:\/\/twitter.com\/jonnybarnes","https:\/\/facebook.com\/jonnybarnes"]}}';
foreach ($container as $transaction) { foreach ($container as $transaction) {

View file

@ -3,13 +3,14 @@
namespace Tests\Feature; namespace Tests\Feature;
use Tests\TestCase; use Tests\TestCase;
use Tests\TestToken;
use Lcobucci\JWT\Builder; use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Signer\Hmac\Sha256; use Lcobucci\JWT\Signer\Hmac\Sha256;
use Illuminate\Foundation\Testing\DatabaseTransactions; use Illuminate\Foundation\Testing\DatabaseTransactions;
class MicropubControllerTest extends TestCase class MicropubControllerTest extends TestCase
{ {
use DatabaseTransactions; use DatabaseTransactions, TestToken;
/** /**
* Test a GET request for the micropub endpoint without a token gives a * Test a GET request for the micropub endpoint without a token gives a
@ -314,42 +315,4 @@ class MicropubControllerTest extends TestCase
'swarm_url' => 'https://www.swarmapp.com/checkin/123' 'swarm_url' => 'https://www.swarmapp.com/checkin/123'
]); ]);
} }
/**
* Generate a valid token to be used in the tests.
*
* @return Lcobucci\JWT\Token\Plain $token
*/
private function getToken()
{
$signer = new Sha256();
$token = (new Builder())
->set('client_id', 'https://quill.p3k.io')
->set('me', 'https://jonnybarnes.localhost')
->set('scope', 'create update')
->set('issued_at', time())
->sign($signer, env('APP_KEY'))
->getToken();
return $token;
}
/**
* Generate an invalid token to be used in the tests.
*
* @return Lcobucci\JWT\Token\Plain $token
*/
private function getInvalidToken()
{
$signer = new Sha256();
$token = (new Builder())
->set('client_id', 'https://quill.p3k.io')
->set('me', 'https://jonnybarnes.localhost')
->set('scope', 'view') //error here
->set('issued_at', time())
->sign($signer, env('APP_KEY'))
->getToken();
return $token;
}
} }

View file

@ -3,13 +3,14 @@
namespace Tests\Feature; namespace Tests\Feature;
use Tests\TestCase; use Tests\TestCase;
use Tests\TestToken;
use Lcobucci\JWT\Builder; use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Signer\Hmac\Sha256; use Lcobucci\JWT\Signer\Hmac\Sha256;
use Illuminate\Foundation\Testing\DatabaseTransactions; use Illuminate\Foundation\Testing\DatabaseTransactions;
class OwnYourGramTest extends TestCase class OwnYourGramTest extends TestCase
{ {
use DatabaseTransactions; use DatabaseTransactions, TestToken;
public function test_ownyourgram_post() public function test_ownyourgram_post()
{ {
@ -40,18 +41,4 @@ class OwnYourGramTest extends TestCase
'instagram_url' => 'https://www.instagram.com/p/BVC_nVTBFfi/' 'instagram_url' => 'https://www.instagram.com/p/BVC_nVTBFfi/'
]); ]);
} }
private function getToken()
{
$signer = new Sha256();
$token = (new Builder())
->set('client_id', 'https://ownyourgram.com')
->set('me', config('app.url'))
->set('scope', 'create')
->set('issued_at', time())
->sign($signer, env('APP_KEY'))
->getToken();
return $token;
}
} }

View file

@ -3,13 +3,14 @@
namespace Tests\Feature; namespace Tests\Feature;
use Tests\TestCase; use Tests\TestCase;
use Tests\TestToken;
use Lcobucci\JWT\Builder; use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Signer\Hmac\Sha256; use Lcobucci\JWT\Signer\Hmac\Sha256;
use Illuminate\Foundation\Testing\DatabaseTransactions; use Illuminate\Foundation\Testing\DatabaseTransactions;
class SwarmTest extends TestCase class SwarmTest extends TestCase
{ {
use DatabaseTransactions; use DatabaseTransactions, TestToken;
public function test_faked_ownyourswarm_request() public function test_faked_ownyourswarm_request()
{ {
@ -82,23 +83,4 @@ class SwarmTest extends TestCase
'swarm_url' => 'https://www.swarmapp.com/checkin/def' 'swarm_url' => 'https://www.swarmapp.com/checkin/def'
]); ]);
} }
/**
* Generate a valid token to be used in the tests.
*
* @return Lcobucci\JWT\Token\Plain $token
*/
private function getToken()
{
$signer = new Sha256();
$token = (new Builder())
->set('client_id', 'https://ownyourswarm.p3k.io')
->set('me', 'https://jonnybarnes.localhost')
->set('scope', 'create update')
->set('issued_at', time())
->sign($signer, env('APP_KEY'))
->getToken();
return $token;
}
} }

37
tests/TestToken.php Normal file
View file

@ -0,0 +1,37 @@
<?php
namespace Tests;
use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Signer\Hmac\Sha256;
trait TestToken
{
public function getToken()
{
$signer = new Sha256();
$token = (new Builder())
->set('client_id', 'https://quill.p3k.io')
->set('me', 'https://jonnybarnes.localhost')
->set('scope', 'create update')
->set('issued_at', time())
->sign($signer, env('APP_KEY'))
->getToken();
return $token;
}
public function getInvalidToken()
{
$signer = new Sha256();
$token = (new Builder())
->set('client_id', 'https://quill.p3k.io')
->set('me', 'https://jonnybarnes.localhost')
->set('scope', 'view') //error here
->set('issued_at', time())
->sign($signer, env('APP_KEY'))
->getToken();
return $token;
}
}