Micropub Update and “Swarm” Support

Much better micropub client/endpoint and the ability
to support ownyourswarm.

Squashed commit of the following:

commit b5be117b852b7a598da72325a4eaf831526c700a
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Thu May 18 15:02:00 2017 +0100

    Add a token endpoint test

commit 71b7ff68d088180770ca8c2fb43e33bf4b385a96
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Thu May 18 13:49:00 2017 +0100

    Fix phpcs issue

commit 54d96d32f280127061254e7bc6dfe196e2e35a39
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Thu May 18 13:47:08 2017 +0100

    Move token code into its own controller

commit 3ed2b4d36d57a9b3bf2a532eb262ec71fc9aa046
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Thu May 18 13:01:09 2017 +0100

    Improve/fix code for issuing a token

commit 8c411a1df1d59f12dd1c1a4ac884f53dbd1b9351
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Thu May 18 12:59:33 2017 +0100

    Remove sprurious comment

commit 1b8a3b6502a2b982f737fb4b58602995451e38b9
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Mon May 15 11:57:03 2017 +0100

    Wrap helper functions in check for existence

commit 75c706b5a6c1fca7bf45038409689416a3b5ba4d
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Mon May 15 11:40:17 2017 +0100

    Fix a test error, array_key_exists must be run on an array

commit 685e96501b8dc906c6945fca39721fb79fa34a8b
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Mon May 15 11:11:51 2017 +0100

    Remove errant dd()

commit 02536ebaa6daec2a78bc79c44392ac5a82c3200e
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Sun May 14 21:37:17 2017 +0100

    Test a typical ownyourswarm request

commit 31d959e35ccec9dac5986f93732d928c08e246c8
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Sun May 14 21:36:37 2017 +0100

    Better tagging of notes

commit e3d4ff8b050ba41febed4d3ab0d30898f0056b33
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Sun May 14 21:35:35 2017 +0100

    When a note has a “checkin” try and create the place if it doesn’t already exist

commit 4fc0dd0121ca09915a13f3c21c97611db1d744a6
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Fri May 12 12:26:25 2017 +0100

    better handling of exceptions, `return` the exctacted response method

commit 2e3ca3297d2f494eb88af732519bd7ea8bcc3611
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Fri May 12 11:22:52 2017 +0100

    compser update and minor style tweak

commit b883d03cc349798230986a5cb50e23e370ce5a09
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Thu May 11 19:03:52 2017 +0100

    Improve artisan tinker; see https://blog.tighten.co/supercharge-your-laravel-tinker-workflow

commit 8de63172fc7d367870624ff25d1ada92af2d61a7
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Thu May 11 17:28:16 2017 +0100

    Tweak code, make it slightly more readable by catching custom exception, and moving a repeated response into its own function

commit 8ff0a1196d254d8788477d26b548f2ecff0a7986
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Thu May 11 17:21:39 2017 +0100

    Add a custom exception to catch

commit 3a568da65ef22b1b676ea8378cd51ce88750b6af
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Thu May 11 17:21:11 2017 +0100

    composer update && yarn upgrade

commit b70242e616827eab6a2132f3e691ec91be689fb5
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Wed May 10 20:00:03 2017 +0100

    modify some returns for style purposes

commit b65170ba1515cbb07beb66fcb3358d69d86cf3a2
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Wed May 10 19:39:46 2017 +0100

    composer update

commit cb6198db03a8e8c5c365e88d565401dd6420be13
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Wed May 10 17:07:33 2017 +0100

    composer update

commit 91cdd9e17ba192b833da76e0243829cd037170f3
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Fri Apr 28 21:41:12 2017 +0100

    verify input array contains necessary data

commit 6b230278bfcf2707b7ea1af8e15acd0d7cd27623
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Fri Apr 28 21:40:30 2017 +0100

    pass the right input content to the data array

commit 96f30d25810751328f75964e81899496add7292e
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Fri Apr 28 21:19:28 2017 +0100

    Add support for the published property

commit 8168a14969711ff5f84d29eca73036980f9b5a6b
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Fri Apr 28 18:48:23 2017 +0100

    Fix some bugs in the `normalize_url()` function and add some tests for the helpers functions

commit 34adcebefa7cafec8d26d438b0046120751780be
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Fri Apr 28 15:12:08 2017 +0100

    Fix PSR-2 issues, exluding group use declarations

commit 4b6651c318d534db1fcb83e1b66562c6dd560165
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Fri Apr 28 12:36:54 2017 +0100

    composer update

commit a0788ffb6bd4d24245986bf83fe349b8e39786cd
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Wed Apr 26 12:44:06 2017 +0100

    Make the retreived a Note a model instance instead of collection, update the content of JSON resposes for updating a note

commit f444cfd570a8316a8bb961b901ca2beb3ba74cd2
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Wed Apr 26 12:43:23 2017 +0100

    Add tests for updating a post

commit ada7e513263b1b0519600538a8a2cb757c74d520
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Wed Apr 26 12:42:50 2017 +0100

    Add swarm_url column

commit f4e1dba1b315b3d923049f9f5c7a47a730267cb7
Merge: 7208ec5 400857a
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Tue Apr 25 15:33:28 2017 +0100

    Merge pull request #50 from jonnybarnes/analysis-XNDLxp

    Apply fixes from StyleCI

commit 400857af57f873bf63b452fdf65ed2632eef9311
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Tue Apr 25 14:33:06 2017 +0000

    Apply fixes from StyleCI

commit 7208ec53ff51f0c5d002c222c465767c46c275b2
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Tue Apr 25 15:30:02 2017 +0100

    Correct some tests, for example the error returned for the specific mistake in `getInvalidToken()` has changed

commit 60550667156d7306cf750768b89fa329742c3927
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Tue Apr 25 15:29:06 2017 +0100

    Fix some typos

commit 0324cb010e77606e0f99e8bb68376b79995abffc
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Tue Apr 25 15:20:27 2017 +0100

    Allow notes to be updated by a micropub client endpoint

commit b3b3170b359548d21ddae9a9572c182d2a7d51be
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Tue Apr 25 15:18:48 2017 +0100

    When a note with a photo is being created, adjust for if URL is on my own endpoint, or somehwere else

commit a2437879b000728a2e7d2b91fa642f7cdfd1e698
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Tue Apr 25 15:17:25 2017 +0100

    Modify method that returns URL to check if path is already a fully qualified URL

commit 64eb53e0f87cb5ee55013de5ed8e2487eee36f0c
Author: Jonny Barnes <jonny@jonnybarnes.uk>
Date:   Tue Apr 25 15:16:12 2017 +0100

    Add a method to find notes based on NewBase60 id
This commit is contained in:
Jonny Barnes 2017-05-18 15:15:53 +01:00
parent f9a133e727
commit 05d42467cf
25 changed files with 1283 additions and 698 deletions

View file

@ -52,3 +52,5 @@ TWITTER_ACCESS_TOKEN_SECRET=
SCOUT_DRIVER=pgsql
PIWIK=false
PSYSH_CONFIG=tinker.config.php

View file

@ -0,0 +1,13 @@
<?php
namespace App\Exceptions;
use Exception;
class InvalidTokenException extends Exception
{
public function __construct($message, $code = 0, Exception $previous = null)
{
parent::__construct($message, $code, $previous);
}
}

View file

@ -5,7 +5,6 @@ namespace App\Http\Controllers;
use App\IndieWebUser;
use IndieAuth\Client;
use Illuminate\Http\Request;
use App\Services\TokenService;
class IndieAuthController extends Controller
{
@ -15,23 +14,14 @@ class IndieAuthController extends Controller
protected $client;
/**
* The Token handling service.
*/
protected $tokenService;
/**
* Inject the dependencies.
* Inject the dependency.
*
* @param \IndieAuth\Client $client
* @param \App\Services\TokenService $tokenService
* @return void
*/
public function __construct(
Client $client = null,
TokenService $tokenService = null
) {
public function __construct(Client $client = null)
{
$this->client = $client ?? new Client();
$this->tokenService = $tokenService ?? new TokenService();
}
/**
@ -90,37 +80,6 @@ class IndieAuthController extends Controller
return redirect(route('micropub-client'));
}
/*
$tokenEndpoint = $this->indieAuthService->getTokenEndpoint($request->input('me'));
if ($tokenEndpoint === false) {
return redirect(route('micropub-client'))->with(
'error',
'Unable to determine token endpoint'
);
}
$data = [
'endpoint' => $tokenEndpoint,
'code' => $request->input('code'),
'me' => $request->input('me'),
'redirect_url' => route('indieauth-callback'),
'client_id' => route('micropub-client'),
'state' => $request->input('state'),
];
$token = $this->indieAuthService->getAccessToken($data);
if (array_key_exists('access_token', $token)) {
$request->session()->put('me', $token['me']);
$request->session()->put('token', $token['access_token']);
return redirect(route('micropub-client'));
}
return redirect(route('micropub-client'))->with(
'error',
'Unable to get a token from the endpoint'
);
*/
/**
* Log out the user, flush the session data.
*
@ -132,42 +91,4 @@ class IndieAuthController extends Controller
return redirect(route('micropub-client'));
}
/**
* If the user has authd via IndieAuth, issue a valid token.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function tokenEndpoint(Request $request)
{
$authData = [
'code' => $request->input('code'),
'me' => $request->input('me'),
'redirect_url' => $request->input('redirect_uri'),
'client_id' => $request->input('client_id'),
'state' => $request->input('state'),
];
$auth = $this->indieAuthService->verifyIndieAuthCode($authData);
if (array_key_exists('me', $auth)) {
$scope = $auth['scope'] ?? '';
$tokenData = [
'me' => $request->input('me'),
'client_id' => $request->input('client_id'),
'scope' => $auth['scope'],
];
$token = $this->tokenService->getNewToken($tokenData);
$content = http_build_query([
'me' => $request->input('me'),
'scope' => $scope,
'access_token' => $token,
]);
return response($content)
->header('Content-Type', 'application/x-www-form-urlencoded');
}
$content = 'There was an error verifying the authorisation code.';
return response($content, 400);
}
}

View file

@ -3,8 +3,9 @@
namespace App\Http\Controllers;
use Ramsey\Uuid\Uuid;
use App\{Media, Place};
use App\{Media, Note, Place};
use Illuminate\Http\{Request, Response};
use App\Exceptions\InvalidTokenException;
use Ramsey\Uuid\Exception\UnsatisfiedDependencyException;
use App\Services\{NoteService, PlaceService, TokenService};
@ -49,7 +50,7 @@ class MicropubController extends Controller
{
try {
$tokenData = $this->tokenService->validateToken($request->bearerToken());
} catch (\Exception $e) {
} catch (InvalidTokenException $e) {
return response()->json([
'response' => 'error',
'error' => 'invalid_token',
@ -57,106 +58,203 @@ class MicropubController extends Controller
], 400);
}
if ($tokenData->hasClaim('scope')) {
$scopes = explode(' ', $tokenData->getClaim('scope'));
if (array_search('create', $scopes) !== false) {
$clientId = $tokenData->getClaim('client_id');
if (($request->input('h') == 'entry') || ($request->input('type')[0] == 'h-entry')) {
$data = [];
$data['client-id'] = $clientId;
if ($request->header('Content-Type') == 'application/json') {
$data['content'] = $request->input('properties.content')[0];
$data['in-reply-to'] = $request->input('properties.in-reply-to')[0];
$data['location'] = $request->input('properties.location');
//flatten location if array
if (is_array($data['location'])) {
$data['location'] = $data['location'][0];
}
} else {
$data['content'] = $request->input('content');
$data['in-reply-to'] = $request->input('in-reply-to');
$data['location'] = $request->input('location');
}
$data['syndicate'] = [];
$targets = array_pluck(config('syndication.targets'), 'uid', 'service.name');
if (is_string($request->input('mp-syndicate-to'))) {
$service = array_search($request->input('mp-syndicate-to'));
if ($service == 'Twitter') {
$data['syndicate'][] = 'twitter';
}
if ($service == 'Facebook') {
$data['syndicate'][] = 'facebook';
}
}
if (is_array($request->input('mp-syndicate-to'))) {
foreach ($targets as $service => $target) {
if (in_array($target, $request->input('mp-syndicate-to'))) {
if ($service == 'Twitter') {
$data['syndicate'][] = 'twitter';
}
if ($service == 'Facebook') {
$data['syndicate'][] = 'facebook';
}
}
}
}
$data['photo'] = [];
if (is_array($request->input('photo'))) {
foreach ($request->input('photo') as $photo) {
if (is_string($photo)) {
//only supporting media URLs for now
$data['photo'][] = $photo;
}
}
}
try {
$note = $this->noteService->createNote($data);
} catch (Exception $exception) {
return response()->json(['error' => true], 400);
}
return response()->json([
'response' => 'created',
'location' => $note->longurl,
], 201)->header('Location', $note->longurl);
if (($request->input('h') == 'entry') || ($request->input('type')[0] == 'h-entry')) {
if (stristr($tokenData->getClaim('scope'), 'create') === false) {
return $this->returnInsufficientScopeResponse();
}
if ($request->input('h') == 'card' || $request->input('type')[0] == 'h-card') {
$data = [];
if ($request->header('Content-Type') == 'application/json') {
$data['name'] = $request->input('properties.name');
$data['description'] = $request->input('properties.description') ?? null;
if ($request->has('properties.geo')) {
$data['geo'] = $request->input('properties.geo');
}
} else {
$data['name'] = $request->input('name');
$data['description'] = $request->input('description');
if ($request->has('geo')) {
$data['geo'] = $request->input('geo');
}
if ($request->has('latitude')) {
$data['latitude'] = $request->input('latitude');
$data['longitude'] = $request->input('longitude');
$data = [];
$data['client-id'] = $tokenData->getClaim('client_id');
if ($request->header('Content-Type') == 'application/json') {
if (is_string($request->input('properties.content')[0])) {
$data['content'] = $request->input('properties.content')[0]; //plaintext content
}
if (is_array($request->input('properties.content')[0])
&& array_key_exists('html', $request->input('properties.content')[0])
) {
$data['content'] = $request->input('properties.content')[0]['html'];
}
$data['in-reply-to'] = $request->input('properties.in-reply-to')[0];
$data['location'] = $request->input('properties.location');
//flatten location if array
if (is_array($data['location'])) {
$data['location'] = $data['location'][0];
}
$data['published'] = $request->input('properties.published')[0];
//create checkin place
if (array_key_exists('checkin', $request->input('properties'))) {
$data['checkin'] = $request->input('properties.checkin.0.properties.url.0');
try {
$this->placeService->createPlaceFromCheckin($request->input('properties.checkin.0'));
} catch (\Exception $e) {
$data['checkin'] = null;
}
}
try {
$place = $this->placeService->createPlace($data);
} catch (Exception $exception) {
return response()->json(['error' => true], 400);
} else {
$data['content'] = $request->input('content');
$data['in-reply-to'] = $request->input('in-reply-to');
$data['location'] = $request->input('location');
$data['published'] = $request->input('published');
}
$data['syndicate'] = [];
$targets = array_pluck(config('syndication.targets'), 'uid', 'service.name');
if (is_string($request->input('mp-syndicate-to'))) {
$service = array_search($request->input('mp-syndicate-to'));
if ($service == 'Twitter') {
$data['syndicate'][] = 'twitter';
}
if ($service == 'Facebook') {
$data['syndicate'][] = 'facebook';
}
}
if (is_array($request->input('mp-syndicate-to'))) {
foreach ($targets as $service => $target) {
if (in_array($target, $request->input('mp-syndicate-to'))) {
if ($service == 'Twitter') {
$data['syndicate'][] = 'twitter';
}
if ($service == 'Facebook') {
$data['syndicate'][] = 'facebook';
}
}
}
}
$data['photo'] = [];
if (is_array($request->input('photo'))) {
foreach ($request->input('photo') as $photo) {
if (is_string($photo)) {
//only supporting media URLs for now
$data['photo'][] = $photo;
}
}
}
try {
$note = $this->noteService->createNote($data);
} catch (\Exception $exception) {
return response()->json(['error' => true], 400);
}
return response()->json([
'response' => 'created',
'location' => $place->longurl,
], 201)->header('Location', $place->longurl);
return response()->json([
'response' => 'created',
'location' => $note->longurl,
], 201)->header('Location', $note->longurl);
}
if ($request->input('h') == 'card' || $request->input('type')[0] == 'h-card') {
if (stristr($tokenData->getClaim('scope'), 'create') === false) {
return $this->returnInsufficientScopeResponse();
}
$data = [];
if ($request->header('Content-Type') == 'application/json') {
$data['name'] = $request->input('properties.name');
$data['description'] = $request->input('properties.description') ?? null;
if ($request->has('properties.geo')) {
$data['geo'] = $request->input('properties.geo');
}
} else {
$data['name'] = $request->input('name');
$data['description'] = $request->input('description');
if ($request->has('geo')) {
$data['geo'] = $request->input('geo');
}
if ($request->has('latitude')) {
$data['latitude'] = $request->input('latitude');
$data['longitude'] = $request->input('longitude');
}
}
try {
$place = $this->placeService->createPlace($data);
} catch (\Exception $exception) {
return response()->json(['error' => true], 400);
}
return response()->json([
'response' => 'created',
'location' => $place->longurl,
], 201)->header('Location', $place->longurl);
}
if ($request->input('action') == 'update') {
if (stristr($tokenData->getClaim('scope'), 'update') === false) {
return $this->returnInsufficientScopeResponse();
}
$urlPath = parse_url($request->input('url'), PHP_URL_PATH);
//is it a note we are updating?
if (mb_substr($urlPath, 1, 5) === 'notes') {
try {
$note = Note::nb60(basename($urlPath))->first();
} catch (\Exception $exception) {
return response()->json([
'error' => 'invalid_request',
'error_description' => 'No known note with given ID',
]);
}
//got the note, are we dealing with a “replace” request?
if ($request->has('replace')) {
foreach ($request->input('replace') as $property => $value) {
if ($property == 'content') {
$note->note = $value[0];
}
if ($property == 'syndication') {
foreach ($value as $syndicationURL) {
if (starts_with($syndicationURL, 'https://www.facebook.com')) {
$note->facebook_url = $syndicationURL;
}
if (starts_with($syndicationURL, 'https://www.swarmapp.com')) {
$note->swarm_url = $syndicationURL;
}
if (starts_with($syndicationURL, 'https://twitter.com')) {
$note->tweet_id = basename(parse_url($syndicationURL, PHP_URL_PATH));
}
}
}
}
$note->save();
return response()->json([
'response' => 'updated',
]);
}
//how about “add”
if ($request->has('add')) {
foreach ($request->input('add') as $property => $value) {
if ($property == 'syndication') {
foreach ($value as $syndicationURL) {
if (starts_with($syndicationURL, 'https://www.facebook.com')) {
$note->facebook_url = $syndicationURL;
}
if (starts_with($syndicationURL, 'https://www.swarmapp.com')) {
$note->swarm_url = $syndicationURL;
}
if (starts_with($syndicationURL, 'https://twitter.com')) {
$note->tweet_id = basename(parse_url($syndicationURL, PHP_URL_PATH));
}
}
}
if ($property == 'photo') {
foreach ($value as $photoURL) {
if (start_with($photo, 'https://')) {
$media = new Media();
$media->path = $photoURL;
$media->type = 'image';
$media->save();
$note->media()->save($media);
}
}
}
}
$note->save();
return response()->json([
'response' => 'updated',
]);
}
}
}
}
return response()->json([
'response' => 'error',
'error' => 'invalid_token',
'error_description' => 'The token provided is not valid or does not have the necessary scope',
], 400);
'error' => 'forbidden',
'error_description' => 'The token has no scopes',
], 403);
}
/**
@ -172,7 +270,7 @@ class MicropubController extends Controller
{
try {
$tokenData = $this->tokenService->validateToken($request->bearerToken());
} catch (\Exception $e) {
} catch (InvalidTokenException $e) {
return response()->json([
'response' => 'error',
'error' => 'invalid_token',
@ -232,8 +330,9 @@ class MicropubController extends Controller
*/
public function media(Request $request)
{
$tokenData = $this->tokenService->validateToken($request->bearerToken());
if ($tokenData === null) {
try {
$tokenData = $this->tokenService->validateToken($request->bearerToken());
} catch (InvalidTokenException $e) {
return response()->json([
'response' => 'error',
'error' => 'invalid_token',
@ -243,54 +342,54 @@ class MicropubController extends Controller
//check post scope
if ($tokenData->hasClaim('scope')) {
$scopes = explode(' ', $tokenData->getClaim('scope'));
if (array_search('post', $scopes) !== false) {
//check media valid
if ($request->hasFile('file') && $request->file('file')->isValid()) {
$type = $this->getFileTypeFromMimeType($request->file('file')->getMimeType());
try {
$filename = Uuid::uuid4() . '.' . $request->file('file')->extension();
} catch (UnsatisfiedDependencyException $e) {
return response()->json([
'response' => 'error',
'error' => 'internal_server_error',
'error_description' => 'A problem occured handling your request',
], 500);
}
try {
$path = $request->file('file')->storeAs('media', $filename, 's3');
} catch (Exception $e) { // which exception?
return response()->json([
'response' => 'error',
'error' => 'service_unavailable',
'error_description' => 'Unable to save media to S3',
], 503);
}
$media = new Media();
$media->token = $request->bearerToken();
$media->path = $path;
$media->type = $type;
$media->save();
if (stristr($token->getClaim('scope'), 'post') === false) {
return $this->returnInsufficientScopeResponse();
}
//check media valid
if ($request->hasFile('file') && $request->file('file')->isValid()) {
$type = $this->getFileTypeFromMimeType($request->file('file')->getMimeType());
try {
$filename = Uuid::uuid4() . '.' . $request->file('file')->extension();
} catch (UnsatisfiedDependencyException $e) {
return response()->json([
'response' => 'created',
'location' => $media->url,
], 201)->header('Location', $media->url);
'response' => 'error',
'error' => 'internal_server_error',
'error_description' => 'A problem occured handling your request',
], 500);
}
try {
$path = $request->file('file')->storeAs('media', $filename, 's3');
} catch (Exception $e) { // which exception?
return response()->json([
'response' => 'error',
'error' => 'service_unavailable',
'error_description' => 'Unable to save media to S3',
], 503);
}
$media = new Media();
$media->token = $request->bearerToken();
$media->path = $path;
$media->type = $type;
$media->save();
return response()->json([
'response' => 'error',
'error' => 'invalid_request',
'error_description' => 'The uploaded file failed validation',
], 400);
'response' => 'created',
'location' => $media->url,
], 201)->header('Location', $media->url);
}
return response()->json([
'response' => 'error',
'error' => 'invalid_request',
'error_description' => 'The uploaded file failed validation',
], 400);
}
return response()->json([
'response' => 'error',
'error' => 'insufficient_scope',
'error_description' => 'The provided token has insufficient scopes',
], 401);
'error' => 'invalid_request',
'error_description' => 'The provided token has no scopes',
], 400);
}
/**
@ -336,4 +435,13 @@ class MicropubController extends Controller
return 'download';
}
private function returnInsufficientScopeResponse()
{
return response()->json([
'response' => 'error',
'error' => 'insufficient_scope',
'error_description' => 'The tokens scope does not have the necessary requirements.',
], 401);
}
}

View file

@ -0,0 +1,79 @@
<?php
namespace App\Http\Controllers;
use IndieAuth\Client;
use Illuminate\Http\Request;
use App\Services\TokenService;
class TokenEndpointController extends Controller
{
/**
* The IndieAuth Client.
*/
protected $client;
/**
* The Token handling service.
*/
protected $tokenService;
/**
* Inject the dependencies.
*
* @param \IndieAuth\Client $client
* @param \App\Services\TokenService $tokenService
* @return void
*/
public function __construct(
Client $client = null,
TokenService $tokenService = null
) {
$this->client = $client ?? new Client();
$this->tokenService = $tokenService ?? new TokenService();
}
/**
* If the user has authd via the IndieAuth protocol, issue a valid token.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function create(Request $request)
{
$authorizationEndpoint = $this->client->discoverAuthorizationEndpoint(normalize_url($request->input('me')));
if ($authorizationEndpoint) {
$auth = $this->client->verifyIndieAuthCode(
$authorizationEndpoint,
$request->input('code'),
$request->input('me'),
$request->input('redirect_uri'),
$request->input('client_id'),
$request->input('state')
);
if (array_key_exists('me', $auth)) {
$scope = $auth['scope'] ?? '';
$tokenData = [
'me' => $request->input('me'),
'client_id' => $request->input('client_id'),
'scope' => $scope,
];
$token = $this->tokenService->getNewToken($tokenData);
$content = http_build_query([
'me' => $request->input('me'),
'scope' => $scope,
'access_token' => $token,
]);
return response($content)->header(
'Content-Type',
'application/x-www-form-urlencoded'
);
}
return response('There was an error verifying the authorisation code.', 400);
}
return response('Cant determine the authorisation endpoint.', 400);
}
}

View file

@ -28,6 +28,10 @@ class Media extends Model
*/
public function getUrlAttribute()
{
if (starts_with($this->path, 'https://')) {
return $this->path;
}
return config('filesystems.disks.s3.url') . '/' . $this->path;
}
}

View file

@ -191,6 +191,20 @@ class Note extends Model
return $name;
}
/**
* Scope a query to select a note via a NewBase60 id.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param string $nb60id
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeNb60($query, $nb60id)
{
$numbers = new Numbers();
return $query->where('id', $numbers->b60tonum($nb60id));
}
/**
* Take note that this method does two things, given @username (NOT [@username](URL)!)
* we try to create a fancy hcard from our contact info. If this is not possible

View file

@ -33,7 +33,7 @@ class AppServiceProvider extends ServiceProvider
//Add tags for notes
Note::created(function ($note) {
$tagsToAdd = [];
preg_match_all('/#([^\s<>]+)\b/', $note, $tags);
preg_match_all('/#([^\s<>]+)\b/', $note->note, $tags);
foreach ($tags[1] as $tag) {
$tag = Tag::normalizeTag($tag);
}

View file

@ -17,6 +17,16 @@ class NoteService
*/
public function createNote(array $data): Note
{
//check the input
if (array_key_exists('content', $data) === false) {
throw new \Exception('No content defined'); //we cant fudge the data
}
if (array_key_exists('in-reply-to', $data) === false) {
$data['in-reply-to'] = null;
}
if (array_key_exists('client-id', $data) === false) {
$data['client-id'] = null;
}
$note = Note::create(
[
'note' => $data['content'],
@ -25,6 +35,11 @@ class NoteService
]
);
if (array_key_exists('published', $data) && empty($data['published']) === false) {
$carbon = new \Carbon\Carbon($data['published']);
$note->created_at = $note->updated_at = $carbon->toDateTimeString();
}
if (array_key_exists('location', $data) && $data['location'] !== null && $data['location'] !== 'no-location') {
if (starts_with($data['location'], config('app.url'))) {
//uri of form http://host/places/slug, we want slug
@ -44,6 +59,13 @@ class NoteService
}
}
if (array_key_exists('checkin', $data) && $data['checkin'] !== null) {
$place = Place::where('foursquare', $data['checkin'])->first();
if ($place !== null) {
$note->place()->associate($place);
}
}
/* drop image support for now
//add images to media library
if ($request->hasFile('photo')) {
@ -55,12 +77,17 @@ class NoteService
*/
//add support for media uploaded as URLs
foreach ($data['photo'] as $photo) {
// check the media was uploaded to my endpoint
// check the media was uploaded to my endpoint, and use path
if (starts_with($photo, config('filesystems.disks.s3.url'))) {
$path = substr($photo, strlen(config('filesystems.disks.s3.url')));
$media = Media::where('path', ltrim($path, '/'))->firstOrFail();
$note->media()->save($media);
} else {
$media = Media::firstOrNew(['path' => $photo]);
// currently assuming this is a photo from Swarm
$media->type = 'image';
$media->save();
}
$note->media()->save($media);
}
$note->save();

View file

@ -36,4 +36,39 @@ class PlaceService
return $place;
}
/**
* Create a place from a h-card checkin, for exameple from OwnYourSwarm.
*
* @param array
* @return bool
*/
public function createPlaceFromCheckin(array $checkin): bool
{
//check if the place exists if from swarm
if (array_key_exists('url', $checkin['properties'])) {
$search = Place::where('foursquare', $checkin['properties']['url'][0])->count();
if ($search === 1) {
return true;
}
}
if (array_key_exists('name', $checkin['properties']) === false) {
throw new \InvalidArgumentException('Missing required name');
}
if (array_key_exists('latitude', $checkin['properties']) === false) {
throw new \InvalidArgumentException('Missing required longitude/latitude');
}
$place = new Place();
$place->name = $checkin['properties']['name'][0];
if (starts_with($checkin['properties']['url'][0], 'https://foursquare.com')) {
$place->foursquare = $checkin['properties']['url'][0];
}
$place->location = new Point(
(float) $checkin['properties']['latitude'][0],
(float) $checkin['properties']['longitude'][0]
);
$place->save();
return true;
}
}

View file

@ -4,10 +4,9 @@ declare(strict_types=1);
namespace App\Services;
use Lcobucci\JWT\Token;
use Lcobucci\JWT\Parser;
use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use App\Exceptions\InvalidTokenException;
use Lcobucci\JWT\{Builder, Parser, Token};
class TokenService
{
@ -40,9 +39,13 @@ class TokenService
public function validateToken(string $bearerToken): ?Token
{
$signer = new Sha256();
$token = (new Parser())->parse((string) $bearerToken);
try {
$token = (new Parser())->parse((string) $bearerToken);
} catch (\InvalidArgumentException $e) {
throw new InvalidTokenException('Token could not be parsed');
}
if (! $token->verify($signer, config('app.key'))) {
throw new \Exception('Token not verified');
throw new InvalidTokenException('Token failed verification');
}
return $token;

View file

@ -1,191 +0,0 @@
<?php
declare(strict_types=1);
/*
helpers.php
*/
// sourced from https://github.com/flattr/normalize-url/blob/master/normalize_url.php
function normalize_url(?string $url): ?string
{
if ($url === null) {
return null;
}
$newUrl = '';
$url = parse_url($url);
$defaultSchemes = ['http' => 80, 'https' => 443];
if (isset($url['scheme'])) {
$url['scheme'] = strtolower($url['scheme']);
// Strip scheme default ports
if (
isset($defaultSchemes[$url['scheme']]) &&
isset($url['port']) &&
$defaultSchemes[$url['scheme']] == $url['port']
) {
unset($url['port']);
}
$newUrl .= "{$url['scheme']}://";
}
if (isset($url['host'])) {
$url['host'] = mb_strtolower($url['host']);
$newUrl .= $url['host'];
}
if (isset($url['port'])) {
$newUrl .= ":{$url['port']}";
}
// here we only want to drop a slash for the root domain
// e.g. http://example.com/ -> http://example.com
// but http://example.com/path/ -/-> http://example.com/path
if (isset($url['path']) && $url['path'] == '/') {
unset($url['path']);
}
if (isset($url['path'])) {
// Case normalization
$url['path'] = normalizer_normalize($url['path'], Normalizer::FORM_C);
// Strip duplicate slashes
while (preg_match("/\/\//", $url['path'])) {
$url['path'] = preg_replace('/\/\//', '/', $url['path']);
}
/*
* Decode unreserved characters, http://www.apps.ietf.org/rfc/rfc3986.html#sec-2.3
* Heavily rewritten version of urlDecodeUnreservedChars() in Glen Scott's url-normalizer.
*/
$u = [];
for ($o = 65; $o <= 90; $o++) {
$u[] = dechex($o);
}
for ($o = 97; $o <= 122; $o++) {
$u[] = dechex($o);
}
for ($o = 48; $o <= 57; $o++) {
$u[] = dechex($o);
}
$chrs = ['-', '.', '_', '~'];
foreach ($chrs as $chr) {
$u[] = dechex(ord($chr));
}
$url['path'] = preg_replace_callback(
array_map(
create_function('$str', 'return "/%" . strtoupper($str) . "/x";'),
$u
),
create_function('$matches', 'return chr(hexdec($matches[0]));'),
$url['path']
);
// Remove directory index
$defaultIndexes = ["/default\.aspx/" => 'default.aspx', "/default\.asp/" => 'default.asp',
"/index\.html/" => 'index.html', "/index\.htm/" => 'index.htm',
"/default\.html/" => 'default.html', "/default\.htm/" => 'default.htm',
"/index\.php/" => 'index.php', "/index\.jsp/" => 'index.jsp', ];
foreach ($defaultIndexes as $index => $strip) {
if (preg_match($index, $url['path'])) {
$url['path'] = str_replace($strip, '', $url['path']);
}
}
/**
* Path segment normalization, http://www.apps.ietf.org/rfc/rfc3986.html#sec-5.2.4
* Heavily rewritten version of removeDotSegments() in Glen Scott's url-normalizer.
*/
$new_path = '';
while (! empty($url['path'])) {
if (preg_match('!^(\.\./|\./)!x', $url['path'])) {
$url['path'] = preg_replace('!^(\.\./|\./)!x', '', $url['path']);
} elseif (preg_match('!^(/\./)!x', $url['path'], $matches) || preg_match('!^(/\.)$!x', $url['path'], $matches)) {
$url['path'] = preg_replace('!^' . $matches[1] . '!', '/', $url['path']);
} elseif (preg_match('!^(/\.\./|/\.\.)!x', $url['path'], $matches)) {
$url['path'] = preg_replace('!^' . preg_quote($matches[1], '!') . '!x', '/', $url['path']);
$new_path = preg_replace('!/([^/]+)$!x', '', $new_path);
} elseif (preg_match('!^(\.|\.\.)$!x', $url['path'])) {
$url['path'] = preg_replace('!^(\.|\.\.)$!x', '', $url['path']);
} else {
if (preg_match('!(/*[^/]*)!x', $url['path'], $matches)) {
$first_path_segment = $matches[1];
$url['path'] = preg_replace('/^' . preg_quote($first_path_segment, '/') . '/', '', $url['path'], 1);
$new_path .= $first_path_segment;
}
}
}
$newUrl .= $new_path;
}
if (isset($url['fragment'])) {
unset($url['fragment']);
}
// Sort GET params alphabetically, not because the RFC requires it but because it's cool!
if (isset($url['query'])) {
if (preg_match('/&/', $url['query'])) {
$s = explode('&', $url['query']);
$url['query'] = '';
sort($s);
foreach ($s as $z) {
$url['query'] .= "{$z}&";
}
$url['query'] = preg_replace('/&\Z/', '', $url['query']);
}
$newUrl .= "?{$url['query']}";
}
return $newUrl;
}
// sourced from https://stackoverflow.com/a/9776726
function prettyPrintJson(string $json): string
{
$result = '';
$level = 0;
$in_quotes = false;
$in_escape = false;
$ends_line_level = null;
$json_length = strlen($json);
for ($i = 0; $i < $json_length; $i++) {
$char = $json[$i];
$new_line_level = null;
$post = '';
if ($ends_line_level !== null) {
$new_line_level = $ends_line_level;
$ends_line_level = null;
}
if ($in_escape) {
$in_escape = false;
} elseif ($char === '"') {
$in_quotes = ! $in_quotes;
} elseif (! $in_quotes) {
switch ($char) {
case '}': case ']':
$level--;
$ends_line_level = null;
$new_line_level = $level;
break;
case '{': case '[':
$level++;
case ',':
$ends_line_level = $level;
break;
case ':':
$post = ' ';
break;
case ' ': case "\t": case "\n": case "\r":
$char = '';
$ends_line_level = $new_line_level;
$new_line_level = null;
break;
}
} elseif ($char === '\\') {
$in_escape = true;
}
if ($new_line_level !== null) {
$result .= "\n".str_repeat("\t", $new_line_level);
}
$result .= $char.$post;
}
return str_replace("\t", ' ', $result);
}

View file

@ -44,7 +44,7 @@
"App\\": "app/"
},
"files": [
"app/helpers.php"
"helpers.php"
]
},
"autoload-dev": {

247
composer.lock generated
View file

@ -8,16 +8,16 @@
"packages": [
{
"name": "aws/aws-sdk-php",
"version": "3.25.7",
"version": "3.27.2",
"source": {
"type": "git",
"url": "https://github.com/aws/aws-sdk-php.git",
"reference": "d4f1104f5ac9c755875c5e6e9bade2c70708219a"
"reference": "eb10e43cccf8e868f9622ab8ce2beb9fb756b5a8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/d4f1104f5ac9c755875c5e6e9bade2c70708219a",
"reference": "d4f1104f5ac9c755875c5e6e9bade2c70708219a",
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/eb10e43cccf8e868f9622ab8ce2beb9fb756b5a8",
"reference": "eb10e43cccf8e868f9622ab8ce2beb9fb756b5a8",
"shasum": ""
},
"require": {
@ -39,7 +39,7 @@
"ext-simplexml": "*",
"ext-spl": "*",
"nette/neon": "^2.3",
"phpunit/phpunit": "~4.0|~5.0",
"phpunit/phpunit": "^4.8.35|^5.4.0",
"psr/cache": "^1.0"
},
"suggest": {
@ -84,7 +84,7 @@
"s3",
"sdk"
],
"time": "2017-04-11T22:31:27+00:00"
"time": "2017-05-11T21:23:43+00:00"
},
{
"name": "barnabywalters/mf-cleaner",
@ -1104,16 +1104,16 @@
},
{
"name": "indieauth/client",
"version": "0.2.0",
"version": "0.2.1",
"source": {
"type": "git",
"url": "https://github.com/indieweb/indieauth-client-php.git",
"reference": "4b9bd766a92b8abbe420f5889bf7ebac7678151d"
"reference": "f5f6efad79334d1ff9370fe4dce8ccf4814820fa"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/indieweb/indieauth-client-php/zipball/4b9bd766a92b8abbe420f5889bf7ebac7678151d",
"reference": "4b9bd766a92b8abbe420f5889bf7ebac7678151d",
"url": "https://api.github.com/repos/indieweb/indieauth-client-php/zipball/f5f6efad79334d1ff9370fe4dce8ccf4814820fa",
"reference": "f5f6efad79334d1ff9370fe4dce8ccf4814820fa",
"shasum": ""
},
"require": {
@ -1139,7 +1139,7 @@
}
],
"description": "IndieAuth Client Library",
"time": "2017-02-09T23:42:05+00:00"
"time": "2017-04-26T21:44:35+00:00"
},
{
"name": "indieweb/link-rel-parser",
@ -1464,16 +1464,16 @@
},
{
"name": "laravel/framework",
"version": "v5.4.19",
"version": "v5.4.23",
"source": {
"type": "git",
"url": "https://github.com/laravel/framework.git",
"reference": "02444b7450350db17a7607c8a52f7268ebdb0dad"
"reference": "ad82327705658dbf5f0ce72805caa950dfbe150d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/framework/zipball/02444b7450350db17a7607c8a52f7268ebdb0dad",
"reference": "02444b7450350db17a7607c8a52f7268ebdb0dad",
"url": "https://api.github.com/repos/laravel/framework/zipball/ad82327705658dbf5f0ce72805caa950dfbe150d",
"reference": "ad82327705658dbf5f0ce72805caa950dfbe150d",
"shasum": ""
},
"require": {
@ -1589,7 +1589,7 @@
"framework",
"laravel"
],
"time": "2017-04-16T13:33:34+00:00"
"time": "2017-05-11T20:10:35+00:00"
},
{
"name": "laravel/scout",
@ -1769,16 +1769,16 @@
},
{
"name": "league/commonmark",
"version": "0.15.3",
"version": "0.15.4",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/commonmark.git",
"reference": "c8b43ee5821362216f8e9ac684f0f59de164edcc"
"reference": "c4c8e6bf99e62d9568875d9fc3ef473fe3e18e0c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/commonmark/zipball/c8b43ee5821362216f8e9ac684f0f59de164edcc",
"reference": "c8b43ee5821362216f8e9ac684f0f59de164edcc",
"url": "https://api.github.com/repos/thephpleague/commonmark/zipball/c4c8e6bf99e62d9568875d9fc3ef473fe3e18e0c",
"reference": "c4c8e6bf99e62d9568875d9fc3ef473fe3e18e0c",
"shasum": ""
},
"require": {
@ -1834,20 +1834,20 @@
"markdown",
"parser"
],
"time": "2016-12-19T00:11:43+00:00"
"time": "2017-05-09T12:47:53+00:00"
},
{
"name": "league/flysystem",
"version": "1.0.37",
"version": "1.0.40",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/flysystem.git",
"reference": "78b5cc4feb61a882302df4fbaf63b7662e5e4ccd"
"reference": "3828f0b24e2c1918bb362d57a53205d6dc8fde61"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/flysystem/zipball/78b5cc4feb61a882302df4fbaf63b7662e5e4ccd",
"reference": "78b5cc4feb61a882302df4fbaf63b7662e5e4ccd",
"url": "https://api.github.com/repos/thephpleague/flysystem/zipball/3828f0b24e2c1918bb362d57a53205d6dc8fde61",
"reference": "3828f0b24e2c1918bb362d57a53205d6dc8fde61",
"shasum": ""
},
"require": {
@ -1869,12 +1869,12 @@
"league/flysystem-azure": "Allows you to use Windows Azure Blob storage",
"league/flysystem-cached-adapter": "Flysystem adapter decorator for metadata caching",
"league/flysystem-copy": "Allows you to use Copy.com storage",
"league/flysystem-dropbox": "Allows you to use Dropbox storage",
"league/flysystem-eventable-filesystem": "Allows you to use EventableFilesystem",
"league/flysystem-rackspace": "Allows you to use Rackspace Cloud Files",
"league/flysystem-sftp": "Allows you to use SFTP server storage via phpseclib",
"league/flysystem-webdav": "Allows you to use WebDAV storage",
"league/flysystem-ziparchive": "Allows you to use ZipArchive adapter"
"league/flysystem-ziparchive": "Allows you to use ZipArchive adapter",
"spatie/flysystem-dropbox": "Allows you to use Dropbox storage"
},
"type": "library",
"extra": {
@ -1917,25 +1917,25 @@
"sftp",
"storage"
],
"time": "2017-03-22T15:43:14+00:00"
"time": "2017-04-28T10:15:08+00:00"
},
{
"name": "league/flysystem-aws-s3-v3",
"version": "1.0.13",
"version": "1.0.15",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/flysystem-aws-s3-v3.git",
"reference": "dc56a8faf3aff0841f9eae04b6af94a50657896c"
"reference": "c947f36f977b495a57e857ae1630df0da35ec456"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/dc56a8faf3aff0841f9eae04b6af94a50657896c",
"reference": "dc56a8faf3aff0841f9eae04b6af94a50657896c",
"url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/c947f36f977b495a57e857ae1630df0da35ec456",
"reference": "c947f36f977b495a57e857ae1630df0da35ec456",
"shasum": ""
},
"require": {
"aws/aws-sdk-php": "^3.0.0",
"league/flysystem": "~1.0",
"league/flysystem": "^1.0.40",
"php": ">=5.5.0"
},
"require-dev": {
@ -1964,7 +1964,7 @@
}
],
"description": "Flysystem adapter for the AWS S3 SDK v3.x",
"time": "2016-06-21T21:34:35+00:00"
"time": "2017-04-28T10:21:54+00:00"
},
{
"name": "martinbean/laravel-sluggable-trait",
@ -2844,16 +2844,16 @@
},
{
"name": "swiftmailer/swiftmailer",
"version": "v5.4.6",
"version": "v5.4.8",
"source": {
"type": "git",
"url": "https://github.com/swiftmailer/swiftmailer.git",
"reference": "81fdccfaf8bdc5d5d7a1ef6bb3a61bbb1a6c4a3e"
"reference": "9a06dc570a0367850280eefd3f1dc2da45aef517"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/81fdccfaf8bdc5d5d7a1ef6bb3a61bbb1a6c4a3e",
"reference": "81fdccfaf8bdc5d5d7a1ef6bb3a61bbb1a6c4a3e",
"url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/9a06dc570a0367850280eefd3f1dc2da45aef517",
"reference": "9a06dc570a0367850280eefd3f1dc2da45aef517",
"shasum": ""
},
"require": {
@ -2894,20 +2894,20 @@
"mail",
"mailer"
],
"time": "2017-02-13T07:52:53+00:00"
"time": "2017-05-01T15:54:03+00:00"
},
{
"name": "symfony/console",
"version": "v3.2.7",
"version": "v3.2.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "c30243cc51f726812be3551316b109a2f5deaf8d"
"reference": "a7a17e0c6c3c4d70a211f80782e4b90ddadeaa38"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/c30243cc51f726812be3551316b109a2f5deaf8d",
"reference": "c30243cc51f726812be3551316b109a2f5deaf8d",
"url": "https://api.github.com/repos/symfony/console/zipball/a7a17e0c6c3c4d70a211f80782e4b90ddadeaa38",
"reference": "a7a17e0c6c3c4d70a211f80782e4b90ddadeaa38",
"shasum": ""
},
"require": {
@ -2957,20 +2957,20 @@
],
"description": "Symfony Console Component",
"homepage": "https://symfony.com",
"time": "2017-04-04T14:33:42+00:00"
"time": "2017-04-26T01:39:17+00:00"
},
{
"name": "symfony/css-selector",
"version": "v3.2.7",
"version": "v3.2.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/css-selector.git",
"reference": "a48f13dc83c168f1253a5d2a5a4fb46c36244c4c"
"reference": "02983c144038e697c959e6b06ef6666de759ccbc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/css-selector/zipball/a48f13dc83c168f1253a5d2a5a4fb46c36244c4c",
"reference": "a48f13dc83c168f1253a5d2a5a4fb46c36244c4c",
"url": "https://api.github.com/repos/symfony/css-selector/zipball/02983c144038e697c959e6b06ef6666de759ccbc",
"reference": "02983c144038e697c959e6b06ef6666de759ccbc",
"shasum": ""
},
"require": {
@ -3010,20 +3010,20 @@
],
"description": "Symfony CssSelector Component",
"homepage": "https://symfony.com",
"time": "2017-02-21T09:12:04+00:00"
"time": "2017-05-01T14:55:58+00:00"
},
{
"name": "symfony/debug",
"version": "v3.2.7",
"version": "v3.2.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/debug.git",
"reference": "56f613406446a4a0a031475cfd0a01751de22659"
"reference": "fd6eeee656a5a7b384d56f1072243fe1c0e81686"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/debug/zipball/56f613406446a4a0a031475cfd0a01751de22659",
"reference": "56f613406446a4a0a031475cfd0a01751de22659",
"url": "https://api.github.com/repos/symfony/debug/zipball/fd6eeee656a5a7b384d56f1072243fe1c0e81686",
"reference": "fd6eeee656a5a7b384d56f1072243fe1c0e81686",
"shasum": ""
},
"require": {
@ -3067,20 +3067,20 @@
],
"description": "Symfony Debug Component",
"homepage": "https://symfony.com",
"time": "2017-03-28T21:38:24+00:00"
"time": "2017-04-19T20:17:50+00:00"
},
{
"name": "symfony/event-dispatcher",
"version": "v3.2.7",
"version": "v3.2.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
"reference": "154bb1ef7b0e42ccc792bd53edbce18ed73440ca"
"reference": "b8a401f733b43251e1d088c589368b2a94155e40"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/154bb1ef7b0e42ccc792bd53edbce18ed73440ca",
"reference": "154bb1ef7b0e42ccc792bd53edbce18ed73440ca",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/b8a401f733b43251e1d088c589368b2a94155e40",
"reference": "b8a401f733b43251e1d088c589368b2a94155e40",
"shasum": ""
},
"require": {
@ -3127,20 +3127,20 @@
],
"description": "Symfony EventDispatcher Component",
"homepage": "https://symfony.com",
"time": "2017-04-04T07:26:27+00:00"
"time": "2017-05-01T14:58:48+00:00"
},
{
"name": "symfony/finder",
"version": "v3.2.7",
"version": "v3.2.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
"reference": "b20900ce5ea164cd9314af52725b0bb5a758217a"
"reference": "9cf076f8f492f4b1ffac40aae9c2d287b4ca6930"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/finder/zipball/b20900ce5ea164cd9314af52725b0bb5a758217a",
"reference": "b20900ce5ea164cd9314af52725b0bb5a758217a",
"url": "https://api.github.com/repos/symfony/finder/zipball/9cf076f8f492f4b1ffac40aae9c2d287b4ca6930",
"reference": "9cf076f8f492f4b1ffac40aae9c2d287b4ca6930",
"shasum": ""
},
"require": {
@ -3176,20 +3176,20 @@
],
"description": "Symfony Finder Component",
"homepage": "https://symfony.com",
"time": "2017-03-20T09:32:19+00:00"
"time": "2017-04-12T14:13:17+00:00"
},
{
"name": "symfony/http-foundation",
"version": "v3.2.7",
"version": "v3.2.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-foundation.git",
"reference": "cb0b6418f588952c9290b3df4ca650f1b7ab570a"
"reference": "9de6add7f731e5af7f5b2e9c0da365e43383ebef"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/cb0b6418f588952c9290b3df4ca650f1b7ab570a",
"reference": "cb0b6418f588952c9290b3df4ca650f1b7ab570a",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/9de6add7f731e5af7f5b2e9c0da365e43383ebef",
"reference": "9de6add7f731e5af7f5b2e9c0da365e43383ebef",
"shasum": ""
},
"require": {
@ -3229,20 +3229,20 @@
],
"description": "Symfony HttpFoundation Component",
"homepage": "https://symfony.com",
"time": "2017-04-04T15:30:56+00:00"
"time": "2017-05-01T14:55:58+00:00"
},
{
"name": "symfony/http-kernel",
"version": "v3.2.7",
"version": "v3.2.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-kernel.git",
"reference": "8285ab5faf1306b1a5ebcf287fe91c231a6de88e"
"reference": "46e8b209abab55c072c47d72d5cd1d62c0585e05"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/8285ab5faf1306b1a5ebcf287fe91c231a6de88e",
"reference": "8285ab5faf1306b1a5ebcf287fe91c231a6de88e",
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/46e8b209abab55c072c47d72d5cd1d62c0585e05",
"reference": "46e8b209abab55c072c47d72d5cd1d62c0585e05",
"shasum": ""
},
"require": {
@ -3311,7 +3311,7 @@
],
"description": "Symfony HttpKernel Component",
"homepage": "https://symfony.com",
"time": "2017-04-05T12:52:03+00:00"
"time": "2017-05-01T17:46:48+00:00"
},
{
"name": "symfony/polyfill-mbstring",
@ -3374,16 +3374,16 @@
},
{
"name": "symfony/process",
"version": "v3.2.7",
"version": "v3.2.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
"reference": "57fdaa55827ae14d617550ebe71a820f0a5e2282"
"reference": "999c2cf5061e627e6cd551dc9ebf90dd1d11d9f0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/process/zipball/57fdaa55827ae14d617550ebe71a820f0a5e2282",
"reference": "57fdaa55827ae14d617550ebe71a820f0a5e2282",
"url": "https://api.github.com/repos/symfony/process/zipball/999c2cf5061e627e6cd551dc9ebf90dd1d11d9f0",
"reference": "999c2cf5061e627e6cd551dc9ebf90dd1d11d9f0",
"shasum": ""
},
"require": {
@ -3419,20 +3419,20 @@
],
"description": "Symfony Process Component",
"homepage": "https://symfony.com",
"time": "2017-03-27T18:07:02+00:00"
"time": "2017-04-12T14:13:17+00:00"
},
{
"name": "symfony/routing",
"version": "v3.2.7",
"version": "v3.2.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/routing.git",
"reference": "d6605f9a5767bc5bc4895e1c762ba93964608aee"
"reference": "5029745d6d463585e8b487dbc83d6333f408853a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/routing/zipball/d6605f9a5767bc5bc4895e1c762ba93964608aee",
"reference": "d6605f9a5767bc5bc4895e1c762ba93964608aee",
"url": "https://api.github.com/repos/symfony/routing/zipball/5029745d6d463585e8b487dbc83d6333f408853a",
"reference": "5029745d6d463585e8b487dbc83d6333f408853a",
"shasum": ""
},
"require": {
@ -3494,20 +3494,20 @@
"uri",
"url"
],
"time": "2017-03-02T15:58:09+00:00"
"time": "2017-04-12T14:13:17+00:00"
},
{
"name": "symfony/translation",
"version": "v3.2.7",
"version": "v3.2.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/translation.git",
"reference": "c740eee70783d2af4d3d6b70d5146f209e6b4d13"
"reference": "f4a04d2df710f81515df576b2de06bdeee518b83"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/translation/zipball/c740eee70783d2af4d3d6b70d5146f209e6b4d13",
"reference": "c740eee70783d2af4d3d6b70d5146f209e6b4d13",
"url": "https://api.github.com/repos/symfony/translation/zipball/f4a04d2df710f81515df576b2de06bdeee518b83",
"reference": "f4a04d2df710f81515df576b2de06bdeee518b83",
"shasum": ""
},
"require": {
@ -3558,20 +3558,20 @@
],
"description": "Symfony Translation Component",
"homepage": "https://symfony.com",
"time": "2017-03-21T21:44:32+00:00"
"time": "2017-04-12T14:13:17+00:00"
},
{
"name": "symfony/var-dumper",
"version": "v3.2.7",
"version": "v3.2.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-dumper.git",
"reference": "81dce20f69a8b40427e1f4e6462178df87cafc03"
"reference": "fa47963ac7979ddbd42b2d646d1b056bddbf7bb8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/81dce20f69a8b40427e1f4e6462178df87cafc03",
"reference": "81dce20f69a8b40427e1f4e6462178df87cafc03",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/fa47963ac7979ddbd42b2d646d1b056bddbf7bb8",
"reference": "fa47963ac7979ddbd42b2d646d1b056bddbf7bb8",
"shasum": ""
},
"require": {
@ -3582,9 +3582,11 @@
"phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0"
},
"require-dev": {
"ext-iconv": "*",
"twig/twig": "~1.20|~2.0"
},
"suggest": {
"ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).",
"ext-symfony_debug": ""
},
"type": "library",
@ -3624,7 +3626,7 @@
"debug",
"dump"
],
"time": "2017-03-12T16:07:05+00:00"
"time": "2017-05-01T14:55:58+00:00"
},
{
"name": "themattharris/tmhoauth",
@ -3670,16 +3672,16 @@
},
{
"name": "thujohn/twitter",
"version": "2.2.2",
"version": "2.2.5",
"source": {
"type": "git",
"url": "https://github.com/thujohn/twitter.git",
"reference": "203d903856212835206675ae9c0504d74b681886"
"reference": "ff414bdadba3f1570ca211355e5359ec266552d8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thujohn/twitter/zipball/203d903856212835206675ae9c0504d74b681886",
"reference": "203d903856212835206675ae9c0504d74b681886",
"url": "https://api.github.com/repos/thujohn/twitter/zipball/ff414bdadba3f1570ca211355e5359ec266552d8",
"reference": "ff414bdadba3f1570ca211355e5359ec266552d8",
"shasum": ""
},
"require": {
@ -3710,7 +3712,7 @@
"laravel5",
"twitter"
],
"time": "2017-01-31T23:37:52+00:00"
"time": "2017-04-27T09:00:04+00:00"
},
{
"name": "tijsverkoyen/css-to-inline-styles",
@ -3921,16 +3923,16 @@
},
{
"name": "facebook/webdriver",
"version": "1.4.0",
"version": "1.4.1",
"source": {
"type": "git",
"url": "https://github.com/facebook/php-webdriver.git",
"reference": "3ea034c056189e11c0ce7985332a9f4b5b2b5db2"
"reference": "eadb0b7a7c3e6578185197fd40158b08c3164c83"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/facebook/php-webdriver/zipball/3ea034c056189e11c0ce7985332a9f4b5b2b5db2",
"reference": "3ea034c056189e11c0ce7985332a9f4b5b2b5db2",
"url": "https://api.github.com/repos/facebook/php-webdriver/zipball/eadb0b7a7c3e6578185197fd40158b08c3164c83",
"reference": "eadb0b7a7c3e6578185197fd40158b08c3164c83",
"shasum": ""
},
"require": {
@ -3969,7 +3971,7 @@
"selenium",
"webdriver"
],
"time": "2017-03-22T10:56:03+00:00"
"time": "2017-04-28T14:54:49+00:00"
},
{
"name": "fzaninotto/faker",
@ -4113,21 +4115,22 @@
},
{
"name": "laravel/dusk",
"version": "v1.0.12",
"version": "v1.1.0",
"source": {
"type": "git",
"url": "https://github.com/laravel/dusk.git",
"reference": "9a150bedc3ae6566d05f0a8d1657c658ce98dcad"
"reference": "6b81e97ae1ce384e3d8dbd020b2b9751c1449889"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/dusk/zipball/9a150bedc3ae6566d05f0a8d1657c658ce98dcad",
"reference": "9a150bedc3ae6566d05f0a8d1657c658ce98dcad",
"url": "https://api.github.com/repos/laravel/dusk/zipball/6b81e97ae1ce384e3d8dbd020b2b9751c1449889",
"reference": "6b81e97ae1ce384e3d8dbd020b2b9751c1449889",
"shasum": ""
},
"require": {
"facebook/webdriver": "~1.0",
"illuminate/support": "~5.3",
"illuminate/console": "~5.4",
"illuminate/support": "~5.4",
"nesbot/carbon": "~1.20",
"php": ">=5.6.4",
"symfony/console": "~3.2",
@ -4164,7 +4167,7 @@
"testing",
"webdriver"
],
"time": "2017-04-07T21:47:06+00:00"
"time": "2017-04-23T17:13:04+00:00"
},
{
"name": "maximebf/debugbar",
@ -4232,12 +4235,12 @@
"version": "0.9.9",
"source": {
"type": "git",
"url": "https://github.com/padraic/mockery.git",
"url": "https://github.com/mockery/mockery.git",
"reference": "6fdb61243844dc924071d3404bb23994ea0b6856"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/padraic/mockery/zipball/6fdb61243844dc924071d3404bb23994ea0b6856",
"url": "https://api.github.com/repos/mockery/mockery/zipball/6fdb61243844dc924071d3404bb23994ea0b6856",
"reference": "6fdb61243844dc924071d3404bb23994ea0b6856",
"shasum": ""
},
@ -5537,16 +5540,16 @@
},
{
"name": "symfony/yaml",
"version": "v3.2.7",
"version": "v3.2.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
"reference": "62b4cdb99d52cb1ff253c465eb1532a80cebb621"
"reference": "acec26fcf7f3031e094e910b94b002fa53d4e4d6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/yaml/zipball/62b4cdb99d52cb1ff253c465eb1532a80cebb621",
"reference": "62b4cdb99d52cb1ff253c465eb1532a80cebb621",
"url": "https://api.github.com/repos/symfony/yaml/zipball/acec26fcf7f3031e094e910b94b002fa53d4e4d6",
"reference": "acec26fcf7f3031e094e910b94b002fa53d4e4d6",
"shasum": ""
},
"require": {
@ -5588,20 +5591,20 @@
],
"description": "Symfony Yaml Component",
"homepage": "https://symfony.com",
"time": "2017-03-20T09:45:15+00:00"
"time": "2017-05-01T14:55:58+00:00"
},
{
"name": "theseer/fdomdocument",
"version": "1.6.4",
"version": "1.6.5",
"source": {
"type": "git",
"url": "https://github.com/theseer/fDOMDocument.git",
"reference": "cf219ede922fb47956726f35e2127277ebd302ca"
"reference": "8dcfd392135a5bd938c3c83ea71419501ad9855d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/theseer/fDOMDocument/zipball/cf219ede922fb47956726f35e2127277ebd302ca",
"reference": "cf219ede922fb47956726f35e2127277ebd302ca",
"url": "https://api.github.com/repos/theseer/fDOMDocument/zipball/8dcfd392135a5bd938c3c83ea71419501ad9855d",
"reference": "8dcfd392135a5bd938c3c83ea71419501ad9855d",
"shasum": ""
},
"require": {
@ -5628,7 +5631,7 @@
],
"description": "The classes contained within this repository extend the standard DOM to use exceptions at all occasions of errors instead of PHP warnings or notices. They also add various custom methods and shortcuts for convenience and to simplify the usage of DOM.",
"homepage": "https://github.com/theseer/fDOMDocument",
"time": "2017-04-17T09:08:13+00:00"
"time": "2017-04-21T14:50:31+00:00"
},
{
"name": "webmozart/assert",

View file

@ -0,0 +1,32 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class UpdateNotesTableAddSwarmUrl extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('notes', function (Blueprint $table) {
$table->string('swarm_url')->nullable();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('notes', function (Blueprint $table) {
$table->dropColumn('swarm_url');
});
}
}

View file

@ -0,0 +1,32 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class UpdatePlacesTableAddFoursquareColumn extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('places', function (Blueprint $table) {
$table->string('foursquare')->nullable();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('places', function (Blueprint $table) {
$table->dropColumn('foursquare');
});
}
}

199
helpers.php Normal file
View file

@ -0,0 +1,199 @@
<?php
declare(strict_types=1);
/*
helpers.php
*/
// sourced from https://github.com/flattr/normalize-url/blob/master/normalize_url.php
if (! function_exists('normalize_url')) {
function normalize_url(?string $url): ?string
{
if ($url === null) {
return null;
}
$newUrl = '';
$url = parse_url($url);
$defaultSchemes = ['http' => 80, 'https' => 443];
if (isset($url['scheme'])) {
$url['scheme'] = strtolower($url['scheme']);
// Strip scheme default ports
if (isset($defaultSchemes[$url['scheme']]) &&
isset($url['port']) &&
$defaultSchemes[$url['scheme']] == $url['port']
) {
unset($url['port']);
}
$newUrl .= "{$url['scheme']}://";
}
if (isset($url['host'])) {
$url['host'] = mb_strtolower($url['host']);
$newUrl .= $url['host'];
}
if (isset($url['port'])) {
$newUrl .= ":{$url['port']}";
}
if (isset($url['path'])) {
// Case normalization
$url['path'] = normalizer_normalize($url['path'], Normalizer::FORM_C);
// Strip duplicate slashes
while (preg_match("/\/\//", $url['path'])) {
$url['path'] = preg_replace('/\/\//', '/', $url['path']);
}
/*
* Decode unreserved characters, http://www.apps.ietf.org/rfc/rfc3986.html#sec-2.3
* Heavily rewritten version of urlDecodeUnreservedChars() in Glen Scott's url-normalizer.
*/
$u = [];
for ($o = 65; $o <= 90; $o++) {
$u[] = dechex($o);
}
for ($o = 97; $o <= 122; $o++) {
$u[] = dechex($o);
}
for ($o = 48; $o <= 57; $o++) {
$u[] = dechex($o);
}
$chrs = ['-', '.', '_', '~'];
foreach ($chrs as $chr) {
$u[] = dechex(ord($chr));
}
$url['path'] = preg_replace_callback(
array_map(
create_function('$str', 'return "/%" . strtoupper($str) . "/x";'),
$u
),
create_function('$matches', 'return chr(hexdec($matches[0]));'),
$url['path']
);
// Remove directory index
$defaultIndexes = ["/default\.aspx/" => 'default.aspx/', "/default\.asp/" => 'default.asp/',
"/index\.html/" => 'index.html/', "/index\.htm/" => 'index.htm/',
"/default\.html/" => 'default.html/', "/default\.htm/" => 'default.htm/',
"/index\.php/" => 'index.php/', "/index\.jsp/" => 'index.jsp/', ];
foreach ($defaultIndexes as $index => $strip) {
if (preg_match($index, $url['path'])) {
$url['path'] = str_replace($strip, '', $url['path']);
}
}
// here we only want to drop a slash for the root domain
// e.g. http://example.com/ -> http://example.com
// but http://example.com/path/ -/-> http://example.com/path
if ($url['path'] == '/') {
unset($url['path']);
}
/**
* Path segment normalization, http://www.apps.ietf.org/rfc/rfc3986.html#sec-5.2.4
* Heavily rewritten version of removeDotSegments() in Glen Scott's url-normalizer.
*/
$new_path = '';
while (! empty($url['path'])) {
if (preg_match('!^(\.\./|\./)!x', $url['path'])) {
$url['path'] = preg_replace('!^(\.\./|\./)!x', '', $url['path']);
} elseif (preg_match('!^(/\./)!x', $url['path'], $matches)
|| preg_match('!^(/\.)$!x', $url['path'], $matches)) {
$url['path'] = preg_replace('!^' . $matches[1] . '!', '/', $url['path']);
} elseif (preg_match('!^(/\.\./|/\.\.)!x', $url['path'], $matches)) {
$url['path'] = preg_replace('!^' . preg_quote($matches[1], '!') . '!x', '/', $url['path']);
$new_path = preg_replace('!/([^/]+)$!x', '', $new_path);
} elseif (preg_match('!^(\.|\.\.)$!x', $url['path'])) {
$url['path'] = preg_replace('!^(\.|\.\.)$!x', '', $url['path']);
} else {
if (preg_match('!(/*[^/]*)!x', $url['path'], $matches)) {
$first_path_segment = $matches[1];
$url['path'] = preg_replace('/^' . preg_quote($first_path_segment, '/') . '/', '', $url['path'], 1);
$new_path .= $first_path_segment;
}
}
}
$newUrl .= $new_path;
}
if (isset($url['fragment'])) {
unset($url['fragment']);
}
// Sort GET params alphabetically, not because the RFC requires it but because it's cool!
if (isset($url['query'])) {
if (preg_match('/&/', $url['query'])) {
$s = explode('&', $url['query']);
$url['query'] = '';
sort($s);
foreach ($s as $z) {
$url['query'] .= "{$z}&";
}
$url['query'] = preg_replace('/&\Z/', '', $url['query']);
}
$newUrl .= "?{$url['query']}";
}
return $newUrl;
}
}
// sourced from https://stackoverflow.com/a/9776726
if (! function_exists('prettyPrintJson')) {
function prettyPrintJson(string $json): string
{
$result = '';
$level = 0;
$in_quotes = false;
$in_escape = false;
$ends_line_level = null;
$json_length = strlen($json);
for ($i = 0; $i < $json_length; $i++) {
$char = $json[$i];
$new_line_level = null;
$post = '';
if ($ends_line_level !== null) {
$new_line_level = $ends_line_level;
$ends_line_level = null;
}
if ($in_escape) {
$in_escape = false;
} elseif ($char === '"') {
$in_quotes = ! $in_quotes;
} elseif (! $in_quotes) {
switch ($char) {
case '}':
case ']':
$level--;
$ends_line_level = null;
$new_line_level = $level;
break;
case '{':
case '[':
$level++;
//no break
case ',':
$ends_line_level = $level;
break;
case ':':
$post = ' ';
break;
case ' ':
case "\t":
case "\n":
case "\r":
$char = '';
$ends_line_level = $new_line_level;
$new_line_level = null;
break;
}
} elseif ($char === '\\') {
$in_escape = true;
}
if ($new_line_level !== null) {
$result .= "\n".str_repeat("\t", $new_line_level);
}
$result .= $char.$post;
}
return str_replace("\t", ' ', $result);
}
}

View file

@ -6,15 +6,15 @@
"license": "CC0-1.0",
"dependencies": {
"alertify.js": "^1.0.12",
"mapbox-gl": "^0.34.0",
"mapbox-gl": "0.37.0",
"marked": "^0.3.6",
"normalize.css": "^5.0.0",
"normalize.css": "7.0.0",
"webStorage": "^1.2.2"
},
"devDependencies": {
"babel-cli": "^6.18.0",
"babel-core": "^6.21.0",
"babel-loader": "^6.2.10",
"babel-loader": "7.0.0",
"babel-preset-env": "^1.2.2",
"babel-preset-es2015": "^6.18.0",
"babel-preset-latest": "^6.16.0",

View file

@ -89,21 +89,19 @@ Route::group(['domain' => config('url.longurl')], function () {
Route::get('blog/{year?}/{month?}', 'ArticlesController@index');
Route::get('blog/{year}/{month}/{slug}', 'ArticlesController@show');
//micropub new notes page
//this needs to be first so `notes/new` doesn't match `notes/{id}`
//Notes pages using NotesController
Route::get('notes', 'NotesController@index');
Route::get('notes/{id}', 'NotesController@show');
Route::get('note/{id}', 'NotesController@redirect');
Route::get('notes/tagged/{tag}', 'NotesController@tagged');
//indieauth
// IndieAuth
Route::post('indieauth/start', 'IndieAuthController@start')->name('indieauth-start');
Route::get('indieauth/callback', 'IndieAuthController@callback')->name('indieauth-callback');
Route::get('logout', 'IndieAuthController@logout')->name('indieauth-logout');
Route::post('api/token', 'IndieAuthController@tokenEndpoint'); //hmmm?
// Token Endpoint
Route::post('api/token', 'TokenEndpointController@create');
// Micropub Client
Route::get('micropub/create', 'MicropubClientController@create')->name('micropub-client');
@ -118,7 +116,7 @@ Route::group(['domain' => config('url.longurl')], function () {
Route::post('micropub/media', 'MicropubClientController@processMedia')->name('process-media');
Route::get('micropub/media/clearlinks', 'MicropubClientController@clearLinks');
// Micropub Endpoint
// Micropub Endpoints
Route::get('api/post', 'MicropubController@get')->middleware('micropub.token');
Route::post('api/post', 'MicropubController@post')->middleware('micropub.token');
Route::post('api/media', 'MicropubController@media')->middleware('micropub.token')->name('media-endpoint');

View file

@ -231,9 +231,9 @@ class MicropubControllerTest extends TestCase
$response
->assertJson([
'response' => 'error',
'error' => 'invalid_token'
'error' => 'insufficient_scope'
])
->assertStatus(400);
->assertStatus(401);
}
public function test_micropub_request_with_json_syntax_creates_new_place()
@ -276,6 +276,47 @@ class MicropubControllerTest extends TestCase
->assertStatus(201);
}
public function test_micropub_request_with_json_syntax_update_replace_post()
{
$response = $this->json(
'POST',
'/api/post',
[
'action' => 'update',
'url' => config('app.url') . '/notes/A',
'replace' => [
'content' => ['replaced content'],
],
],
['HTTP_Authorization' => 'Bearer ' . $this->getToken()]
);
$response
->assertJson(['response' => 'updated'])
->assertStatus(200);
}
public function test_micropub_request_with_json_syntax_update_add_post()
{
$response = $this->json(
'POST',
'/api/post',
[
'action' => 'update',
'url' => config('app.url') . '/notes/A',
'add' => [
'syndication' => ['https://www.swarmapp.com/checkin/123'],
],
],
['HTTP_Authorization' => 'Bearer ' . $this->getToken()]
);
$response
->assertJson(['response' => 'updated'])
->assertStatus(200);
$this->assertDatabaseHas('notes', [
'swarm_url' => 'https://www.swarmapp.com/checkin/123'
]);
}
/**
* Generate a valid token to be used in the tests.
*

View file

@ -0,0 +1,69 @@
<?php
namespace Tests\Feature;
use Tests\TestCase;
use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
class SwarmTest extends TestCase
{
use DatabaseTransactions;
public function test_faked_ownyourswarm_request()
{
$response = $this->json(
'POST',
'api/post',
[
'type' => ['h-entry'],
'properties' => [
'published' => [\Carbon\Carbon::now()->toDateTimeString()],
'syndication' => ['https://www.swarmapp.com/checkin/abc'],
'content' => [[
'value' => 'My first #checkin using Example Product',
'html' => 'My first #checkin using <a href="http://example.org">Example Product</a>',
]],
'checkin' => [[
'type' => ['h-card'],
'properties' => [
'name' => ['Awesome Venue'],
'url' => ['https://foursquare.com/v/123456'],
'latitude' => ['1.23'],
'longitude' => ['4.56'],
],
]],
],
],
['HTTP_Authorization' => 'Bearer ' . $this->getToken()]
);
$response
->assertStatus(201)
->assertJson(['response' => 'created']);
$this->assertDatabaseHas('places', [
'foursquare' => 'https://foursquare.com/v/123456'
]);
}
/**
* 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;
}
}

View file

@ -0,0 +1,38 @@
<?php
namespace Tests\Feature;
use Mockery;
use Tests\TestCase;
use IndieAuth\Client;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
class TokenEndpointTest extends TestCase
{
public function test_token_endpoint_issues_token()
{
$mockClient = Mockery::mock(Client::class);
$mockClient->shouldReceive('discoverAuthorizationEndpoint')
->with(normalize_url(config('app.url')))
->once()
->andReturn('https://indieauth.com/auth');
$mockClient->shouldReceive('verifyIndieAuthCode')
->andReturn([
'me' => config('app.url'),
'scope' => 'create update',
]);
$this->app->instance(Client::class, $mockClient);
$response = $this->post('/api/token', [
'me' => config('app.url'),
'code' => 'abc123',
'redirect_uri' => route('indieauth-callback'),
'client_id' => route('micropub-client'),
'state' => mt_rand(1000, 10000),
]);
parse_str($response->content(), $output);
$this->assertEquals(config('app.url'), $output['me']);
$this->assertTrue(array_key_exists('access_token', $output));
}
}

View file

@ -0,0 +1,69 @@
<?php
namespace Tests\Unit;
use Tests\TestCase;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
class HelpersTest extends TestCase
{
public function test_normalize_url_is_idempotent()
{
$input = 'http://example.org:80/index.php?foo=bar&baz=1';
$this->assertEquals(normalize_url(normalize_url($input)), normalize_url($input));
}
/**
* @dataProvider urlProvider
*/
public function test_normalize_url($input, $output)
{
$this->assertEquals($output, normalize_url($input));
}
public function urlProvider()
{
return [
['https://example.org/', 'https://example.org'],
['https://example.org:443/', 'https://example.org'],
['http://www.foo.bar/index.php/', 'http://www.foo.bar'],
['https://example.org/?foo=bar&baz=true', 'https://example.org?baz=true&foo=bar'],
];
}
public function test_pretty_print_json()
{
$json = <<<JSON
{"glossary": {"title": "example glossary", "GlossDiv": {"title": "S", "GlossList": {"GlossEntry": {"ID": "SGML", "SortAs": "SGML", "GlossTerm": "Standard Generalized Markup Language", "Acronym": "SGML", "Abbrev": "ISO 8879:1986", "GlossDef": {"para": "A meta-markup language, used to create markup languages such as DocBook.", "GlossSeeAlso": ["GML", "XML"]}, "GlossSee": "markup"}}}}}
JSON;
$expected = <<<EXPECTED
{
"glossary": {
"title": "example glossary",
"GlossDiv": {
"title": "S",
"GlossList": {
"GlossEntry": {
"ID": "SGML",
"SortAs": "SGML",
"GlossTerm": "Standard Generalized Markup Language",
"Acronym": "SGML",
"Abbrev": "ISO 8879:1986",
"GlossDef": {
"para": "A meta-markup language, used to create markup languages such as DocBook.",
"GlossSeeAlso": [
"GML",
"XML"
]
},
"GlossSee": "markup"
}
}
}
}
}
EXPECTED;
$this->assertEquals($expected, prettyPrintJson($json));
}
}

38
tinker.config.php Normal file
View file

@ -0,0 +1,38 @@
<?php
/**
* Automatically alias Laravel Model's to their base classname.
* Ex: "App\Models\User" now can just be accessed by "User"
*/
if (! function_exists('aliasModels')) {
function aliasModels() {
$finder = new \Symfony\Component\Finder\Finder();
$finder->files()->name('*.php')->in(base_path().'/app');
foreach ($finder as $file) {
$namespace = 'App\\';
if ($relativePath = $file->getRelativePath()) {
$namespace .= strtr($relativePath, '/', '\\') . '\\';
}
$class = $namespace . $file->getBasename('.php');
try {
$r = new \ReflectionClass($class);
if ($r->isSubclassOf('Illuminate\\Database\\Eloquent\\Model')) {
class_alias($class, $file->getBasename('.php'));
}
} catch (Exception $e) {
//
}
}
}
}
aliasModels();
return [
'startupMessage' => '<info>Using local config file (tinker.config.php)</info>',
'commands' => [
// new \App\Tinker\TestCommand,
],
];

349
yarn.lock
View file

@ -48,17 +48,21 @@ acorn@^3.0.4, acorn@^3.1.0, acorn@^3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a"
acorn@^4.0.0, acorn@^4.0.3, acorn@^4.0.4:
acorn@^4.0.0, acorn@^4.0.3:
version "4.0.11"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.11.tgz#edcda3bd937e7556410d42ed5860f67399c794c0"
acorn@^5.0.0:
version "5.0.3"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.0.3.tgz#c460df08491463f028ccb82eab3730bf01087b3d"
ajv-keywords@^1.1.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c"
ajv@^4.7.0, ajv@^4.9.1:
version "4.11.6"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.6.tgz#947e93049790942b2a2d60a8289b28924d39f987"
version "4.11.8"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536"
dependencies:
co "^4.6.0"
json-stable-stringify "^1.0.1"
@ -117,11 +121,11 @@ archy@^1.0.0:
resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40"
are-we-there-yet@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.2.tgz#80e470e95a084794fe1899262c5667c6e88de1b3"
version "1.1.4"
resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz#bb5dca382bb94f05e15194373d16fd3ba1ca110d"
dependencies:
delegates "^1.0.0"
readable-stream "^2.0.0 || ^1.1.13"
readable-stream "^2.0.6"
argparse@^1.0.7:
version "1.0.9"
@ -136,8 +140,8 @@ arr-diff@^2.0.0:
arr-flatten "^1.0.1"
arr-flatten@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.0.1.tgz#e5ffe54d45e19f32f216e91eb99c8ce892bb604b"
version "1.0.3"
resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.0.3.tgz#a274ed85ac08849b6bd7847c4580745dc51adfb1"
array-unique@^0.2.1:
version "0.2.1"
@ -182,8 +186,8 @@ async-each@^1.0.0:
resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d"
async@^2.1.2:
version "2.3.0"
resolved "https://registry.yarnpkg.com/async/-/async-2.3.0.tgz#1013d1051047dd320fe24e494d5c66ecaf6147d9"
version "2.4.0"
resolved "https://registry.yarnpkg.com/async/-/async-2.4.0.tgz#4990200f18ea5b837c2cc4f8c031a6985c385611"
dependencies:
lodash "^4.14.0"
@ -374,14 +378,13 @@ babel-helpers@^6.24.1:
babel-runtime "^6.22.0"
babel-template "^6.24.1"
babel-loader@^6.2.10:
version "6.4.1"
resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-6.4.1.tgz#0b34112d5b0748a8dcdbf51acf6f9bd42d50b8ca"
babel-loader@7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-7.0.0.tgz#2e43a66bee1fff4470533d0402c8a4532fafbaf7"
dependencies:
find-cache-dir "^0.1.1"
loader-utils "^0.2.16"
loader-utils "^1.0.2"
mkdirp "^0.5.1"
object-assign "^4.0.1"
babel-messages@^6.23.0:
version "6.23.0"
@ -613,8 +616,8 @@ babel-polyfill@^6.23.0:
regenerator-runtime "^0.10.0"
babel-preset-env@^1.2.2:
version "1.3.3"
resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.3.3.tgz#5913407784e3d98de2aa814a3ef9059722b34e0b"
version "1.4.0"
resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.4.0.tgz#c8e02a3bcc7792f23cded68e0355b9d4c28f0f7a"
dependencies:
babel-plugin-check-es2015-constants "^6.22.0"
babel-plugin-syntax-trailing-function-commas "^6.22.0"
@ -749,8 +752,8 @@ babel-types@^6.19.0, babel-types@^6.24.1:
to-fast-properties "^1.0.1"
babylon@^6.11.0, babylon@^6.15.0:
version "6.16.1"
resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.16.1.tgz#30c5a22f481978a9e7f8cdfdf496b11d94b404d3"
version "6.17.1"
resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.17.1.tgz#17f14fddf361b695981fe679385e4f1c01ebd86f"
balanced-match@^0.4.1:
version "0.4.2"
@ -778,6 +781,10 @@ binary-extensions@^1.0.0:
version "1.8.0"
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.8.0.tgz#48ec8d16df4377eae5fa5884682480af4d95c774"
bindings@1.2.x:
version "1.2.1"
resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.2.1.tgz#14ad6113812d2d37d72e67b4cacb4bb726505f11"
block-stream@*:
version "0.0.9"
resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a"
@ -812,7 +819,7 @@ boxen@^0.3.1:
string-width "^1.0.1"
widest-line "^1.0.0"
brace-expansion@^1.0.0:
brace-expansion@^1.0.0, brace-expansion@^1.1.7:
version "1.1.7"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.7.tgz#3effc3c50e000531fb720eaff80f0ae8ef23cf59"
dependencies:
@ -967,8 +974,8 @@ camelcase@^3.0.0:
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a"
caniuse-db@^1.0.30000639:
version "1.0.30000650"
resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000650.tgz#615f564d367533d32b82d72ada09661e75386bab"
version "1.0.30000666"
resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000666.tgz#951ed9f3d3bfaa08a06dafbb5089ab07cce6ab90"
capture-stack-trace@^1.0.0:
version "1.0.0"
@ -996,8 +1003,8 @@ chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3:
supports-color "^2.0.0"
chokidar@^1.4.3, chokidar@^1.6.1:
version "1.6.1"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.6.1.tgz#2f4447ab5e96e50fb3d789fd90d4c72e0e4c70c2"
version "1.7.0"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468"
dependencies:
anymatch "^1.3.0"
async-each "^1.0.0"
@ -1010,7 +1017,7 @@ chokidar@^1.4.3, chokidar@^1.6.1:
optionalDependencies:
fsevents "^1.0.0"
cipher-base@^1.0.0, cipher-base@^1.0.1:
cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.3.tgz#eeabf194419ce900da3018c207d212f2a6df0a07"
dependencies:
@ -1095,7 +1102,7 @@ concat-map@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
concat-stream@^1.4.7:
concat-stream@^1.4.7, concat-stream@~1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7"
dependencies:
@ -1109,14 +1116,6 @@ concat-stream@~1.2.1:
dependencies:
bops "0.0.6"
concat-stream@~1.4.5:
version "1.4.10"
resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.4.10.tgz#acc3bbf5602cb8cc980c6ac840fa7d8603e3ef36"
dependencies:
inherits "~2.0.1"
readable-stream "~1.1.9"
typedarray "~0.0.5"
configstore@^1.0.0, configstore@^1.2.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/configstore/-/configstore-1.4.0.tgz#c35781d0501d268c25c54b8b17f6240e8a4fb021"
@ -1196,21 +1195,25 @@ create-error-class@^3.0.1:
dependencies:
capture-stack-trace "^1.0.0"
create-hash@^1.1.0, create-hash@^1.1.1:
version "1.1.2"
resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.1.2.tgz#51210062d7bb7479f6c65bb41a92208b1d61abad"
create-hash@^1.1.0, create-hash@^1.1.1, create-hash@^1.1.2:
version "1.1.3"
resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.1.3.tgz#606042ac8b9262750f483caddab0f5819172d8fd"
dependencies:
cipher-base "^1.0.1"
inherits "^2.0.1"
ripemd160 "^1.0.0"
sha.js "^2.3.6"
ripemd160 "^2.0.0"
sha.js "^2.4.0"
create-hmac@^1.1.0, create-hmac@^1.1.2:
version "1.1.4"
resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.4.tgz#d3fb4ba253eb8b3f56e39ea2fbcb8af747bd3170"
create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4:
version "1.1.6"
resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.6.tgz#acb9e221a4e17bdb076e90657c42b93e3726cf06"
dependencies:
cipher-base "^1.0.3"
create-hash "^1.1.0"
inherits "^2.0.1"
ripemd160 "^2.0.0"
safe-buffer "^5.0.1"
sha.js "^2.4.8"
cross-spawn@^5.0.1:
version "5.1.0"
@ -1248,18 +1251,18 @@ dashdash@^1.12.0:
assert-plus "^1.0.0"
date-fns@^1.27.2:
version "1.28.2"
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.28.2.tgz#19e4192d68875c0bf7c9537e3f296a8ec64853ef"
version "1.28.4"
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.28.4.tgz#7938aec34ba31fc8bd134d2344bc2e0bbfd95165"
date-now@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b"
debug@^2.1.1, debug@^2.2.0:
version "2.6.3"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.3.tgz#0f7eb8c30965ec08c72accfa0130c8b79984141d"
version "2.6.6"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.6.tgz#a9fa6fbe9ca43cf1e79f73b75c0189cbb7d6db5a"
dependencies:
ms "0.7.2"
ms "0.7.3"
decamelize@^1.0.0, decamelize@^1.1.1:
version "1.2.0"
@ -1270,8 +1273,8 @@ deep-equal@^1.0.0:
resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5"
deep-extend@~0.4.0:
version "0.4.1"
resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.1.tgz#efe4113d08085f4e6f9687759810f807469e2253"
version "0.4.2"
resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f"
deep-is@~0.1.3:
version "0.1.3"
@ -1348,8 +1351,8 @@ ecc-jsbn@~0.1.1:
jsbn "~0.1.0"
electron-to-chromium@^1.2.7:
version "1.3.3"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.3.tgz#651eb63fe89f39db70ffc8dbd5d9b66958bc6a0e"
version "1.3.10"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.10.tgz#63d62b785471f0d8dda85199d64579de8a449f08"
elegant-spinner@^1.0.1:
version "1.0.1"
@ -1521,8 +1524,8 @@ expand-range@^1.8.1:
fill-range "^2.1.0"
extend@~3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.0.tgz#5a474353b9f3353ddd8176dfd37b91c83a46f1d4"
version "3.0.1"
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444"
extglob@^0.3.1:
version "0.3.2"
@ -1555,8 +1558,8 @@ figures@^1.3.5, figures@^1.7.0:
object-assign "^4.1.0"
filename-regex@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.0.tgz#996e3e80479b98b9897f15a8a58b3d084e926775"
version "2.0.1"
resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26"
fill-range@^2.1.0:
version "2.2.3"
@ -1588,8 +1591,8 @@ find-up@^1.0.0:
pinkie-promise "^2.0.0"
flow-remove-types@^1.1.2:
version "1.2.0"
resolved "https://registry.yarnpkg.com/flow-remove-types/-/flow-remove-types-1.2.0.tgz#c285516eabba72177a1b10bfb58f6ffb675a8877"
version "1.2.1"
resolved "https://registry.yarnpkg.com/flow-remove-types/-/flow-remove-types-1.2.1.tgz#58e261bf8b842bd234c86cafb982a1213aff0edb"
dependencies:
babylon "^6.15.0"
vlq "^0.2.1"
@ -1656,9 +1659,9 @@ function-bind@^1.0.2:
version "1.1.0"
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.0.tgz#16176714c801798e4e8f2cf7f7529467bb4a5771"
gauge@~2.7.1:
version "2.7.3"
resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.3.tgz#1c23855f962f17b3ad3d0dc7443f304542edfe09"
gauge@~2.7.3:
version "2.7.4"
resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
dependencies:
aproba "^1.0.3"
console-control-strings "^1.0.0"
@ -1696,8 +1699,8 @@ get-stream@^3.0.0:
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
getpass@^0.1.1:
version "0.1.6"
resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.6.tgz#283ffd9fc1256840875311c1b60e8c40187110e6"
version "0.1.7"
resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
dependencies:
assert-plus "^1.0.0"
@ -1817,6 +1820,12 @@ hasbin@^1.2.3:
dependencies:
async "~1.5"
hash-base@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-2.0.2.tgz#66ea1d856db4e8a5470cadf6fce23ae5244ef2e1"
dependencies:
inherits "^2.0.1"
hash.js@^1.0.0, hash.js@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.0.3.tgz#1332ff00156c0a0ffdd8236013d07b77a0451573"
@ -1852,8 +1861,8 @@ home-or-tmp@^2.0.0:
os-tmpdir "^1.0.1"
hosted-git-info@^2.1.4:
version "2.4.1"
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.4.1.tgz#4b0445e41c004a8bd1337773a4ff790ca40318c8"
version "2.4.2"
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.4.2.tgz#0076b9f46a270506ddbaaea56496897460612a67"
http-signature@~1.1.0:
version "1.1.1"
@ -1931,8 +1940,8 @@ inquirer@1.0.3:
through "^2.3.6"
interpret@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.2.tgz#f4f623f0bb7122f15f5717c8e254b8161b5c5b2d"
version "1.0.3"
resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.3.tgz#cbc35c62eeee73f19ab7b10a801511401afc0f90"
invariant@^2.2.0, invariant@^2.2.2:
version "2.2.2"
@ -1954,7 +1963,7 @@ is-binary-path@^1.0.0:
dependencies:
binary-extensions "^1.0.0"
is-buffer@^1.0.2:
is-buffer@^1.1.5:
version "1.1.5"
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.5.tgz#1f3b26ef613b214b88cbca23cc6c01d87961eecc"
@ -1994,6 +2003,10 @@ is-fullwidth-code-point@^1.0.0:
dependencies:
number-is-nan "^1.0.0"
is-fullwidth-code-point@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
is-glob@^2.0.0, is-glob@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863"
@ -2079,8 +2092,8 @@ js-tokens@^3.0.0:
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7"
js-yaml@^3.4.3, js-yaml@^3.5.3:
version "3.8.3"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.3.tgz#33a05ec481c850c8875929166fe1beb61c728766"
version "3.8.4"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.4.tgz#520b4564f86573ba96662af85a8cafa7b4b5a6f6"
dependencies:
argparse "^1.0.7"
esprima "^3.1.1"
@ -2115,7 +2128,7 @@ json-stringify-safe@~5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
json5@^0.5.0:
json5@^0.5.0, json5@^0.5.1:
version "0.5.1"
resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821"
@ -2137,10 +2150,10 @@ kdbush@^1.0.1:
resolved "https://registry.yarnpkg.com/kdbush/-/kdbush-1.0.1.tgz#3cbd03e9dead9c0f6f66ccdb96450e5cecc640e0"
kind-of@^3.0.2:
version "3.1.0"
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.1.0.tgz#475d698a5e49ff5e53d14e3e732429dc8bf4cf47"
version "3.2.0"
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.0.tgz#b58abe4d5c044ad33726a8c1525b48cf891bff07"
dependencies:
is-buffer "^1.0.2"
is-buffer "^1.1.5"
latest-version@^1.0.0:
version "1.0.1"
@ -2172,13 +2185,13 @@ levn@~0.3.0:
type-check "~0.3.2"
lint-staged@^3.2.1:
version "3.4.0"
resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-3.4.0.tgz#52fa85dfc92bb1c6fe8ad0d0d98ca13924e03e4b"
version "3.4.1"
resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-3.4.1.tgz#96cd1cf7a1ac92d81662643c37d1cca28b91b046"
dependencies:
app-root-path "^2.0.0"
cosmiconfig "^1.1.0"
execa "^0.6.0"
listr "^0.11.0"
listr "^0.12.0"
minimatch "^3.0.0"
npm-which "^3.0.1"
staged-git-files "0.0.4"
@ -2209,9 +2222,9 @@ listr-verbose-renderer@^0.4.0:
date-fns "^1.27.2"
figures "^1.7.0"
listr@^0.11.0:
version "0.11.0"
resolved "https://registry.yarnpkg.com/listr/-/listr-0.11.0.tgz#5e778bc23806ac3ab984ed75564458151f39b03e"
listr@^0.12.0:
version "0.12.0"
resolved "https://registry.yarnpkg.com/listr/-/listr-0.12.0.tgz#6bce2c0f5603fa49580ea17cd6a00cc0e5fa451a"
dependencies:
chalk "^1.1.3"
cli-truncate "^0.2.1"
@ -2225,6 +2238,7 @@ listr@^0.11.0:
log-symbols "^1.0.2"
log-update "^1.0.2"
ora "^0.2.3"
p-map "^1.1.1"
rxjs "^5.0.0-beta.11"
stream-to-observable "^0.1.0"
strip-ansi "^3.0.1"
@ -2252,6 +2266,14 @@ loader-utils@^0.2.16:
json5 "^0.5.0"
object-assign "^4.0.1"
loader-utils@^1.0.2:
version "1.1.0"
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.1.0.tgz#c98aef488bcceda2ffb5e2de646d6a754429f5cd"
dependencies:
big.js "^3.1.3"
emojis-list "^2.0.0"
json5 "^0.5.0"
lodash.assign@^4.0.3, lodash.assign@^4.0.6:
version "4.2.0"
resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7"
@ -2320,9 +2342,9 @@ mapbox-gl-supported@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/mapbox-gl-supported/-/mapbox-gl-supported-1.2.0.tgz#cbd34df894206cadda9a33c8d9a4609f26bb1989"
mapbox-gl@^0.34.0:
version "0.34.0"
resolved "https://registry.yarnpkg.com/mapbox-gl/-/mapbox-gl-0.34.0.tgz#f35effae360b8174b7466476a400cc1306a19713"
mapbox-gl@0.37.0:
version "0.37.0"
resolved "https://registry.yarnpkg.com/mapbox-gl/-/mapbox-gl-0.37.0.tgz#20103b0ae73a0e77fe9405439749318b87c04f10"
dependencies:
"@mapbox/gl-matrix" "^0.0.1"
"@mapbox/shelf-pack" "^3.0.0"
@ -2377,6 +2399,13 @@ micromatch@^2.1.5:
parse-glob "^3.0.4"
regex-cache "^0.4.2"
microtime@^2.1.3:
version "2.1.3"
resolved "https://registry.yarnpkg.com/microtime/-/microtime-2.1.3.tgz#0d1307f25da0ca7fde4ab791edc8c91dd7b4e3be"
dependencies:
bindings "1.2.x"
nan "2.6.x"
miller-rabin@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.0.tgz#4a62fb1d42933c05583982f4c716f6fb9e6c6d3d"
@ -2409,10 +2438,10 @@ minimatch@3.0.2:
brace-expansion "^1.0.0"
minimatch@^3.0.0, minimatch@^3.0.2:
version "3.0.3"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774"
version "3.0.4"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
dependencies:
brace-expansion "^1.0.0"
brace-expansion "^1.1.7"
minimist@0.0.5:
version "0.0.5"
@ -2432,9 +2461,9 @@ minimist@^1.1.0, minimist@^1.1.3, minimist@^1.2.0:
dependencies:
minimist "0.0.8"
ms@0.7.2:
version "0.7.2"
resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765"
ms@0.7.3:
version "0.7.3"
resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.3.tgz#708155a5e44e33f5fd0fc53e81d0d40a91be1fff"
multi-stage-sourcemap@^0.2.1:
version "0.2.1"
@ -2446,9 +2475,9 @@ mute-stream@0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.6.tgz#48962b19e169fd1dfc240b3f1e7317627bbc47db"
nan@^2.3.0:
version "2.6.1"
resolved "https://registry.yarnpkg.com/nan/-/nan-2.6.1.tgz#8c84f7b14c96b89f57fbc838012180ec8ca39a01"
nan@2.6.x, nan@^2.3.0:
version "2.6.2"
resolved "https://registry.yarnpkg.com/nan/-/nan-2.6.2.tgz#e4ff34e6c95fdfb5aecc08de6596f43605a7db45"
nconf@^0.7.2:
version "0.7.2"
@ -2518,8 +2547,8 @@ nopt@^4.0.1:
osenv "^0.1.4"
normalize-package-data@^2.3.2:
version "2.3.6"
resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.3.6.tgz#498fa420c96401f787402ba21e600def9f981fff"
version "2.3.8"
resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.3.8.tgz#d819eda2a9dedbd1ffa563ea4071d936782295bb"
dependencies:
hosted-git-info "^2.1.4"
is-builtin-module "^1.0.0"
@ -2532,9 +2561,9 @@ normalize-path@^2.0.1:
dependencies:
remove-trailing-separator "^1.0.1"
normalize.css@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/normalize.css/-/normalize.css-5.0.0.tgz#7cec875ce8178a5333c4de80b68ea9c18b9d7c37"
normalize.css@7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/normalize.css/-/normalize.css-7.0.0.tgz#abfb1dd82470674e0322b53ceb1aaf412938e4bf"
npm-path@^2.0.2:
version "2.0.3"
@ -2557,12 +2586,12 @@ npm-which@^3.0.1:
which "^1.2.10"
npmlog@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.0.2.tgz#d03950e0e78ce1527ba26d2a7592e9348ac3e75f"
version "4.1.0"
resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.0.tgz#dc59bee85f64f00ed424efb2af0783df25d1c0b5"
dependencies:
are-we-there-yet "~1.1.2"
console-control-strings "~1.1.0"
gauge "~2.7.1"
gauge "~2.7.3"
set-blocking "~2.0.0"
number-is-nan@^1.0.0:
@ -2694,6 +2723,10 @@ p-finally@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
p-map@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.1.1.tgz#05f5e4ae97a068371bc2a5cc86bfbdbc19c4ae7a"
package-json-versionify@^1.0.2:
version "1.0.4"
resolved "https://registry.yarnpkg.com/package-json-versionify/-/package-json-versionify-1.0.4.tgz#5860587a944873a6b7e6d26e8e51ffb22315bf17"
@ -2783,10 +2816,16 @@ pbf@^1.3.2:
resolve-protobuf-schema "^2.0.0"
pbkdf2@^3.0.3:
version "3.0.9"
resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.9.tgz#f2c4b25a600058b3c3773c086c37dbbee1ffe693"
version "3.0.11"
resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.11.tgz#791b7414e50c848438976e12ea2651003037ca6b"
dependencies:
create-hmac "^1.1.2"
create-hash "^1.1.2"
create-hmac "^1.1.4"
ripemd160 "^2.0.1"
safe-buffer "^5.0.1"
sha.js "^2.4.8"
optionalDependencies:
microtime "^2.1.3"
performance-now@^0.2.0:
version "0.2.0"
@ -2845,8 +2884,8 @@ process-nextick-args@~1.0.6:
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3"
process@^0.11.0:
version "0.11.9"
resolved "https://registry.yarnpkg.com/process/-/process-0.11.9.tgz#7bd5ad21aa6253e7da8682264f1e11d11c0318c1"
version "0.11.10"
resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
"promise@>=3.2 <8":
version "7.1.1"
@ -2876,11 +2915,11 @@ public-encrypt@^4.0.0:
parse-asn1 "^5.0.0"
randombytes "^2.0.1"
punycode@1.3.2:
punycode@1.3.2, punycode@^1.2.4:
version "1.3.2"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
punycode@^1.2.4, punycode@^1.4.1:
punycode@^1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
@ -2957,7 +2996,7 @@ read-pkg@^1.0.0:
normalize-package-data "^2.3.2"
path-type "^1.0.0"
readable-stream@^2.0.0, "readable-stream@^2.0.0 || ^1.1.13", readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.2.6:
readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.2.6:
version "2.2.9"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.9.tgz#cf78ec6f4a6d1eb43d26488cac97f042e74b7fc8"
dependencies:
@ -3001,8 +3040,8 @@ regenerate@^1.2.1:
resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.2.tgz#d1941c67bad437e1be76433add5b385f95b19260"
regenerator-runtime@^0.10.0:
version "0.10.3"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz#8c4367a904b51ea62a908ac310bf99ff90a82a3e"
version "0.10.5"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658"
regenerator-transform@0.9.11:
version "0.9.11"
@ -3028,10 +3067,11 @@ regexpu-core@^2.0.0:
regjsparser "^0.1.4"
registry-auth-token@^3.0.1:
version "3.1.2"
resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.1.2.tgz#1b9e51a185c930da34a9894b12a52ea998f1adaf"
version "3.3.1"
resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.3.1.tgz#fb0d3289ee0d9ada2cbb52af5dfe66cb070d3006"
dependencies:
rc "^1.1.6"
safe-buffer "^5.0.1"
registry-url@^3.0.0, registry-url@^3.0.3:
version "3.1.0"
@ -3119,8 +3159,8 @@ resolve-protobuf-schema@^2.0.0:
protocol-buffers-schema "^2.0.2"
resolve@^1.1.5:
version "1.3.2"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.3.2.tgz#1f0442c9e0cbb8136e87b9305f932f46c7f28235"
version "1.3.3"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.3.3.tgz#655907c3469a8680dc2de3a275a8fdd69691f0e5"
dependencies:
path-parse "^1.0.5"
@ -3143,9 +3183,12 @@ rimraf@2, rimraf@^2.5.1, rimraf@^2.6.1:
dependencies:
glob "^7.0.5"
ripemd160@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-1.0.1.tgz#93a4bbd4942bc574b69a8fa57c71de10ecca7d6e"
ripemd160@^2.0.0, ripemd160@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.1.tgz#0f4584295c53a3628af7e6d79aca21ce57d1c6e7"
dependencies:
hash-base "^2.0.0"
inherits "^2.0.1"
run-async@^2.2.0:
version "2.3.0"
@ -3158,8 +3201,8 @@ rx@^4.1.0:
resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782"
rxjs@^5.0.0-beta.11:
version "5.3.0"
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.3.0.tgz#d88ccbdd46af290cbdb97d5d8055e52453fabe2d"
version "5.4.0"
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.4.0.tgz#a7db14ab157f9d7aac6a56e655e7a3860d39bf26"
dependencies:
symbol-observable "^1.0.1"
@ -3189,7 +3232,7 @@ setimmediate@^1.0.4:
version "1.0.5"
resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
sha.js@^2.3.6:
sha.js@^2.4.0, sha.js@^2.4.8:
version "2.4.8"
resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.8.tgz#37068c2c476b6baf402d14a49c67f597921f634f"
dependencies:
@ -3309,8 +3352,8 @@ snyk-try-require@^1.1.1, snyk-try-require@^1.2.0:
then-fs "^2.0.0"
snyk@^1.14.3:
version "1.28.0"
resolved "https://registry.yarnpkg.com/snyk/-/snyk-1.28.0.tgz#f805cc5917d57203aa7fe055650e70d1b31daba2"
version "1.30.0"
resolved "https://registry.yarnpkg.com/snyk/-/snyk-1.30.0.tgz#a323809ea477d6aff0e325f5995cb491c0d7ca3d"
dependencies:
abbrev "^1.0.7"
ansi-escapes "^1.3.0"
@ -3340,12 +3383,12 @@ snyk@^1.14.3:
uuid "^3.0.1"
source-list-map@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-1.1.1.tgz#1a33ac210ca144d1e561f906ebccab5669ff4cb4"
version "1.1.2"
resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-1.1.2.tgz#9889019d1024cce55cdc069498337ef6186a11a1"
source-map-support@^0.4.2:
version "0.4.14"
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.14.tgz#9d4463772598b86271b4f523f6c1f4e02a7d6aef"
version "0.4.15"
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.15.tgz#03202df65c06d2bd8c7ec2362a193056fef8d3b1"
dependencies:
source-map "^0.5.6"
@ -3391,8 +3434,8 @@ sprintf-js@~1.0.2:
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
sshpk@^1.7.0:
version "1.11.0"
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.11.0.tgz#2d8d5ebb4a6fab28ffba37fa62a90f4a3ea59d77"
version "1.13.0"
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.0.tgz#ff2a3e4fd04497555fed97b39a0fd82fafb3a33c"
dependencies:
asn1 "~0.2.3"
assert-plus "^1.0.0"
@ -3416,10 +3459,10 @@ static-eval@~0.2.0:
escodegen "~0.0.24"
static-module@^1.1.0:
version "1.3.1"
resolved "https://registry.yarnpkg.com/static-module/-/static-module-1.3.1.tgz#79071d340e4419e4ab5ce87976a9eb67250c8493"
version "1.3.2"
resolved "https://registry.yarnpkg.com/static-module/-/static-module-1.3.2.tgz#329fb9f223a566266bda71843b7d932c767174f3"
dependencies:
concat-stream "~1.4.5"
concat-stream "~1.6.0"
duplexer2 "~0.0.2"
escodegen "~1.3.2"
falafel "^1.0.0"
@ -3439,8 +3482,8 @@ stream-browserify@^2.0.1:
readable-stream "^2.0.2"
stream-http@^2.3.1:
version "2.7.0"
resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.7.0.tgz#cec1f4e3b494bc4a81b451808970f8b20b4ed5f6"
version "2.7.1"
resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.7.1.tgz#546a51741ad5a6b07e9e31b0b10441a917df528a"
dependencies:
builtin-status-codes "^3.0.0"
inherits "^2.0.1"
@ -3470,6 +3513,13 @@ string-width@^1.0.1, string-width@^1.0.2:
is-fullwidth-code-point "^1.0.0"
strip-ansi "^3.0.0"
string-width@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.0.0.tgz#635c5436cc72a6e0c387ceca278d4e2eec52687e"
dependencies:
is-fullwidth-code-point "^2.0.0"
strip-ansi "^3.0.0"
string_decoder@^0.10.25, string_decoder@~0.10.x:
version "0.10.31"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
@ -3607,8 +3657,8 @@ to-arraybuffer@^1.0.0:
resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43"
to-fast-properties@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.2.tgz#f3f5c0c3ba7299a7ef99427e44633257ade43320"
version "1.0.3"
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47"
to-utf8@0.0.1:
version "0.0.1"
@ -3644,13 +3694,13 @@ type-check@~0.3.2:
dependencies:
prelude-ls "~1.1.2"
typedarray@^0.0.6, typedarray@~0.0.5:
typedarray@^0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
uglify-js@^2.8.5:
version "2.8.22"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.22.tgz#d54934778a8da14903fa29a326fb24c0ab51a1a0"
version "2.8.23"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.23.tgz#8230dd9783371232d62a7821e2cf9a817270a8a0"
dependencies:
source-map "~0.5.1"
yargs "~3.10.0"
@ -3762,8 +3812,8 @@ uuid@^3.0.0, uuid@^3.0.1:
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.0.1.tgz#6544bba2dfda8c1cf17e629a3a305e2bb1fee6c1"
v8flags@^2.0.10:
version "2.0.12"
resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-2.0.12.tgz#73235d9f7176f8e8833fb286795445f7938d84e5"
version "2.1.1"
resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-2.1.1.tgz#aab1a1fa30d45f88dd321148875ac02c0b55e5b4"
dependencies:
user-home "^1.1.1"
@ -3787,8 +3837,8 @@ verror@1.3.6:
extsprintf "1.0.2"
vlq@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.1.tgz#14439d711891e682535467f8587c5630e4222a6c"
version "0.2.2"
resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.2.tgz#e316d5257b40b86bb43cb8d5fea5d7f54d6b0ca1"
vm-browserify@0.0.4:
version "0.0.4"
@ -3826,10 +3876,10 @@ webpack-sources@^0.2.3:
source-map "~0.5.3"
webpack@^2.2.0:
version "2.3.3"
resolved "https://registry.yarnpkg.com/webpack/-/webpack-2.3.3.tgz#eecc083c18fb7bf958ea4f40b57a6640c5a0cc78"
version "2.5.1"
resolved "https://registry.yarnpkg.com/webpack/-/webpack-2.5.1.tgz#61742f0cf8af555b87460a9cd8bba2f1e3ee2fce"
dependencies:
acorn "^4.0.4"
acorn "^5.0.0"
acorn-dynamic-import "^2.0.0"
ajv "^4.7.0"
ajv-keywords "^1.1.1"
@ -3837,6 +3887,7 @@ webpack@^2.2.0:
enhanced-resolve "^3.0.0"
interpret "^1.0.0"
json-loader "^0.5.4"
json5 "^0.5.1"
loader-runner "^2.3.0"
loader-utils "^0.2.16"
memory-fs "~0.4.1"
@ -3869,10 +3920,10 @@ which@1.2.x, which@^1.2.10, which@^1.2.9:
isexe "^2.0.0"
wide-align@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.0.tgz#40edde802a71fea1f070da3e62dcda2e7add96ad"
version "1.1.1"
resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.1.tgz#d2ea8aa2db2e66467e8b60cc3e897de3bc4429e6"
dependencies:
string-width "^1.0.1"
string-width "^2.0.0"
widest-line@^1.0.0:
version "1.0.0"
@ -3918,8 +3969,8 @@ wrappy@1:
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
write-file-atomic@^1.1.2:
version "1.3.1"
resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-1.3.1.tgz#7d45ba32316328dd1ec7d90f60ebc0d845bb759a"
version "1.3.4"
resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-1.3.4.tgz#f807a4f0b1d9e913ae7a48112e6cc3af1991b45f"
dependencies:
graceful-fs "^4.1.11"
imurmurhash "^0.1.4"