2016-05-19 15:01:28 +01:00
|
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
|
|
2017-07-03 17:04:45 +01:00
|
|
|
|
use Monolog\Logger;
|
2017-03-09 22:00:29 +00:00
|
|
|
|
use Ramsey\Uuid\Uuid;
|
2017-05-18 15:15:53 +01:00
|
|
|
|
use App\{Media, Note, Place};
|
2017-07-03 17:04:45 +01:00
|
|
|
|
use Monolog\Handler\StreamHandler;
|
2017-03-18 20:09:11 +00:00
|
|
|
|
use Illuminate\Http\{Request, Response};
|
2017-05-18 15:15:53 +01:00
|
|
|
|
use App\Exceptions\InvalidTokenException;
|
2017-05-30 20:07:40 +01:00
|
|
|
|
use Phaza\LaravelPostgis\Geometries\Point;
|
2017-08-09 22:15:45 +01:00
|
|
|
|
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
2017-03-09 22:00:29 +00:00
|
|
|
|
use Ramsey\Uuid\Exception\UnsatisfiedDependencyException;
|
2017-03-18 20:09:11 +00:00
|
|
|
|
use App\Services\{NoteService, PlaceService, TokenService};
|
2016-05-19 15:01:28 +01:00
|
|
|
|
|
|
|
|
|
class MicropubController extends Controller
|
|
|
|
|
{
|
|
|
|
|
/**
|
|
|
|
|
* The Token service container.
|
|
|
|
|
*/
|
|
|
|
|
protected $tokenService;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The Note service container.
|
|
|
|
|
*/
|
|
|
|
|
protected $noteService;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The Place service container.
|
|
|
|
|
*/
|
|
|
|
|
protected $placeService;
|
|
|
|
|
|
|
|
|
|
/**
|
2016-07-04 13:53:33 +01:00
|
|
|
|
* Inject the dependencies.
|
2016-05-19 15:01:28 +01:00
|
|
|
|
*/
|
|
|
|
|
public function __construct(
|
|
|
|
|
TokenService $tokenService = null,
|
|
|
|
|
NoteService $noteService = null,
|
|
|
|
|
PlaceService $placeService = null
|
|
|
|
|
) {
|
|
|
|
|
$this->tokenService = $tokenService ?? new TokenService();
|
|
|
|
|
$this->noteService = $noteService ?? new NoteService();
|
|
|
|
|
$this->placeService = $placeService ?? new PlaceService();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* This function receives an API request, verifies the authenticity
|
|
|
|
|
* then passes over the info to the relavent Service class.
|
|
|
|
|
*
|
|
|
|
|
* @param \Illuminate\Http\Request request
|
|
|
|
|
* @return \Illuminate\Http\Response
|
|
|
|
|
*/
|
|
|
|
|
public function post(Request $request)
|
|
|
|
|
{
|
2017-04-21 16:38:39 +01:00
|
|
|
|
try {
|
|
|
|
|
$tokenData = $this->tokenService->validateToken($request->bearerToken());
|
2017-05-18 15:15:53 +01:00
|
|
|
|
} catch (InvalidTokenException $e) {
|
2017-04-21 16:38:39 +01:00
|
|
|
|
return response()->json([
|
|
|
|
|
'response' => 'error',
|
|
|
|
|
'error' => 'invalid_token',
|
|
|
|
|
'error_description' => 'The provided token did not pass validation',
|
|
|
|
|
], 400);
|
|
|
|
|
}
|
2017-06-11 16:48:18 +01:00
|
|
|
|
// Log the request
|
2017-07-03 17:04:45 +01:00
|
|
|
|
$logger = new Logger('micropub');
|
|
|
|
|
$logger->pushHandler(new StreamHandler(storage_path('logs/micropub.log')), Logger::DEBUG);
|
|
|
|
|
$logger->debug('MicropubLog', $request->all());
|
2017-03-24 15:40:36 +00:00
|
|
|
|
if ($tokenData->hasClaim('scope')) {
|
2017-06-17 22:29:30 +01:00
|
|
|
|
if (($request->input('h') == 'entry') || ($request->input('type.0') == 'h-entry')) {
|
2017-05-18 15:15:53 +01:00
|
|
|
|
if (stristr($tokenData->getClaim('scope'), 'create') === false) {
|
|
|
|
|
return $this->returnInsufficientScopeResponse();
|
|
|
|
|
}
|
|
|
|
|
$data = [];
|
|
|
|
|
$data['client-id'] = $tokenData->getClaim('client_id');
|
|
|
|
|
if ($request->header('Content-Type') == 'application/json') {
|
2017-06-17 22:29:30 +01:00
|
|
|
|
if (is_string($request->input('properties.content.0'))) {
|
|
|
|
|
$data['content'] = $request->input('properties.content.0'); //plaintext content
|
2017-03-24 15:40:36 +00:00
|
|
|
|
}
|
2017-06-17 22:29:30 +01:00
|
|
|
|
if (is_array($request->input('properties.content.0'))
|
|
|
|
|
&& array_key_exists('html', $request->input('properties.content.0'))
|
2017-05-18 15:15:53 +01:00
|
|
|
|
) {
|
2017-06-17 22:29:30 +01:00
|
|
|
|
$data['content'] = $request->input('properties.content.0.html');
|
2017-03-24 15:40:36 +00:00
|
|
|
|
}
|
2017-06-17 22:29:30 +01:00
|
|
|
|
$data['in-reply-to'] = $request->input('properties.in-reply-to.0');
|
2017-06-13 18:10:51 +01:00
|
|
|
|
// check location is geo: string
|
|
|
|
|
if (is_string($request->input('properties.location.0'))) {
|
|
|
|
|
$data['location'] = $request->input('properties.location.0');
|
|
|
|
|
}
|
|
|
|
|
// check location is h-card
|
|
|
|
|
if (is_array($request->input('properties.location.0'))) {
|
2017-06-17 22:29:30 +01:00
|
|
|
|
if ($request->input('properties.location.0.type.0' === 'h-card')) {
|
2017-06-13 18:10:51 +01:00
|
|
|
|
try {
|
|
|
|
|
$place = $this->placeService->createPlaceFromCheckin($request->input('properties.location.0'));
|
|
|
|
|
$data['checkin'] = $place->longurl;
|
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
|
//
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-05-18 15:15:53 +01:00
|
|
|
|
}
|
2017-06-17 22:29:30 +01:00
|
|
|
|
$data['published'] = $request->input('properties.published.0');
|
2017-05-18 15:15:53 +01:00
|
|
|
|
//create checkin place
|
|
|
|
|
if (array_key_exists('checkin', $request->input('properties'))) {
|
2017-06-11 20:54:10 +01:00
|
|
|
|
$data['swarm-url'] = $request->input('properties.syndication.0');
|
2017-05-18 15:15:53 +01:00
|
|
|
|
try {
|
2017-06-13 18:10:51 +01:00
|
|
|
|
$place = $this->placeService->createPlaceFromCheckin($request->input('properties.checkin.0'));
|
|
|
|
|
$data['checkin'] = $place->longurl;
|
2017-05-18 15:15:53 +01:00
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
|
$data['checkin'] = null;
|
2017-06-13 18:17:27 +01:00
|
|
|
|
$data['swarm-url'] = null;
|
2017-03-18 20:09:11 +00:00
|
|
|
|
}
|
2016-05-19 15:01:28 +01:00
|
|
|
|
}
|
2017-05-18 15:15:53 +01:00
|
|
|
|
} 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');
|
2017-05-19 15:43:43 +01:00
|
|
|
|
$mpSyndicateTo = null;
|
2017-05-19 15:32:43 +01:00
|
|
|
|
if ($request->has('mp-syndicate-to')) {
|
|
|
|
|
$mpSyndicateTo = $request->input('mp-syndicate-to');
|
|
|
|
|
}
|
|
|
|
|
if ($request->has('properties.mp-syndicate-to')) {
|
|
|
|
|
$mpSyndicateTo = $request->input('properties.mp-syndicate-to');
|
|
|
|
|
}
|
|
|
|
|
if (is_string($mpSyndicateTo)) {
|
|
|
|
|
$service = array_search($mpSyndicateTo, $targets);
|
2017-05-18 15:15:53 +01:00
|
|
|
|
if ($service == 'Twitter') {
|
|
|
|
|
$data['syndicate'][] = 'twitter';
|
|
|
|
|
}
|
|
|
|
|
if ($service == 'Facebook') {
|
|
|
|
|
$data['syndicate'][] = 'facebook';
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-05-19 15:32:43 +01:00
|
|
|
|
if (is_array($mpSyndicateTo)) {
|
|
|
|
|
foreach ($mpSyndicateTo as $uid) {
|
|
|
|
|
$service = array_search($uid, $targets);
|
|
|
|
|
if ($service == 'Twitter') {
|
|
|
|
|
$data['syndicate'][] = 'twitter';
|
|
|
|
|
}
|
|
|
|
|
if ($service == 'Facebook') {
|
|
|
|
|
$data['syndicate'][] = 'facebook';
|
2017-03-01 20:15:35 +00:00
|
|
|
|
}
|
2017-03-24 15:40:36 +00:00
|
|
|
|
}
|
2017-05-18 15:15:53 +01:00
|
|
|
|
}
|
|
|
|
|
$data['photo'] = [];
|
2017-05-19 15:32:43 +01:00
|
|
|
|
$photos = null;
|
|
|
|
|
if ($request->has('photo')) {
|
|
|
|
|
$photos = $request->input('photo');
|
|
|
|
|
}
|
|
|
|
|
if ($request->has('properties.photo')) {
|
|
|
|
|
$photos = $request->input('properties.photo');
|
|
|
|
|
}
|
|
|
|
|
if ($photos !== null) {
|
|
|
|
|
foreach ($photos as $photo) {
|
2017-05-18 15:15:53 +01:00
|
|
|
|
if (is_string($photo)) {
|
|
|
|
|
//only supporting media URLs for now
|
|
|
|
|
$data['photo'][] = $photo;
|
|
|
|
|
}
|
2017-03-24 15:40:36 +00:00
|
|
|
|
}
|
2017-06-11 20:54:10 +01:00
|
|
|
|
if (starts_with($request->input('properties.syndication.0'), 'https://www.instagram.com')) {
|
|
|
|
|
$data['instagram-url'] = $request->input('properties.syndication.0');
|
|
|
|
|
}
|
2017-05-18 15:15:53 +01:00
|
|
|
|
}
|
|
|
|
|
try {
|
|
|
|
|
$note = $this->noteService->createNote($data);
|
|
|
|
|
} catch (\Exception $exception) {
|
|
|
|
|
return response()->json(['error' => true], 400);
|
|
|
|
|
}
|
2016-05-19 15:01:28 +01:00
|
|
|
|
|
2017-05-18 15:15:53 +01:00
|
|
|
|
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();
|
2017-03-24 15:40:36 +00:00
|
|
|
|
}
|
2017-05-18 15:15:53 +01:00
|
|
|
|
$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');
|
2016-05-19 15:01:28 +01:00
|
|
|
|
}
|
2017-05-18 15:15:53 +01:00
|
|
|
|
} 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') {
|
2017-03-24 15:40:36 +00:00
|
|
|
|
try {
|
2017-08-09 22:15:45 +01:00
|
|
|
|
$note = Note::nb60(basename($urlPath))->firstOrFail();
|
|
|
|
|
} catch (ModelNotFoundException $exception) {
|
2017-05-18 15:15:53 +01:00
|
|
|
|
return response()->json([
|
|
|
|
|
'error' => 'invalid_request',
|
|
|
|
|
'error_description' => 'No known note with given ID',
|
|
|
|
|
]);
|
2017-03-24 15:40:36 +00:00
|
|
|
|
}
|
2017-05-18 15:15:53 +01:00
|
|
|
|
//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();
|
2017-03-24 15:40:36 +00:00
|
|
|
|
|
2017-05-18 15:15:53 +01:00
|
|
|
|
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',
|
|
|
|
|
]);
|
|
|
|
|
}
|
2016-05-19 15:01:28 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-23 16:55:02 +01:00
|
|
|
|
return response()->json([
|
|
|
|
|
'response' => 'error',
|
2017-05-18 15:15:53 +01:00
|
|
|
|
'error' => 'forbidden',
|
|
|
|
|
'error_description' => 'The token has no scopes',
|
|
|
|
|
], 403);
|
2016-05-19 15:01:28 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* A GET request has been made to `api/post` with an accompanying
|
|
|
|
|
* token, here we check wether the token is valid and respond
|
|
|
|
|
* appropriately. Further if the request has the query parameter
|
|
|
|
|
* synidicate-to we respond with the known syndication endpoints.
|
|
|
|
|
*
|
|
|
|
|
* @param \Illuminate\Http\Request $request
|
|
|
|
|
* @return \Illuminate\Http\Response
|
|
|
|
|
*/
|
2017-02-16 15:35:25 +00:00
|
|
|
|
public function get(Request $request)
|
2016-05-19 15:01:28 +01:00
|
|
|
|
{
|
2017-04-21 16:38:39 +01:00
|
|
|
|
try {
|
|
|
|
|
$tokenData = $this->tokenService->validateToken($request->bearerToken());
|
2017-05-18 15:15:53 +01:00
|
|
|
|
} catch (InvalidTokenException $e) {
|
2017-03-24 15:40:36 +00:00
|
|
|
|
return response()->json([
|
|
|
|
|
'response' => 'error',
|
|
|
|
|
'error' => 'invalid_token',
|
|
|
|
|
'error_description' => 'The provided token did not pass validation',
|
|
|
|
|
], 400);
|
|
|
|
|
}
|
|
|
|
|
//we have a valid token, is `syndicate-to` set?
|
|
|
|
|
if ($request->input('q') === 'syndicate-to') {
|
|
|
|
|
return response()->json([
|
|
|
|
|
'syndicate-to' => config('syndication.targets'),
|
|
|
|
|
]);
|
|
|
|
|
}
|
2017-03-18 20:09:11 +00:00
|
|
|
|
|
2017-03-24 15:40:36 +00:00
|
|
|
|
//nope, how about a config query?
|
|
|
|
|
if ($request->input('q') == 'config') {
|
|
|
|
|
return response()->json([
|
|
|
|
|
'syndicate-to' => config('syndication.targets'),
|
|
|
|
|
'media-endpoint' => route('media-endpoint'),
|
|
|
|
|
]);
|
|
|
|
|
}
|
2016-05-19 15:01:28 +01:00
|
|
|
|
|
2017-03-24 15:40:36 +00:00
|
|
|
|
//nope, how about a geo URL?
|
|
|
|
|
if (substr($request->input('q'), 0, 4) === 'geo:') {
|
|
|
|
|
preg_match_all(
|
|
|
|
|
'/([0-9\.\-]+)/',
|
|
|
|
|
$request->input('q'),
|
|
|
|
|
$matches
|
|
|
|
|
);
|
|
|
|
|
$distance = (count($matches[0]) == 3) ? 100 * $matches[0][2] : 1000;
|
2017-05-30 20:07:40 +01:00
|
|
|
|
$places = Place::near(new Point($matches[0][0], $matches[0][1]))->get();
|
2017-03-24 15:40:36 +00:00
|
|
|
|
foreach ($places as $place) {
|
|
|
|
|
$place->uri = config('app.url') . '/places/' . $place->slug;
|
2016-05-19 15:01:28 +01:00
|
|
|
|
}
|
2016-07-04 13:53:33 +01:00
|
|
|
|
|
|
|
|
|
return response()->json([
|
2017-03-24 15:40:36 +00:00
|
|
|
|
'response' => 'places',
|
|
|
|
|
'places' => $places,
|
2016-05-19 15:01:28 +01:00
|
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-24 15:40:36 +00:00
|
|
|
|
//nope, just return the token
|
2017-02-16 15:35:25 +00:00
|
|
|
|
return response()->json([
|
2017-03-24 15:40:36 +00:00
|
|
|
|
'response' => 'token',
|
|
|
|
|
'token' => [
|
2017-03-28 01:15:46 +01:00
|
|
|
|
'me' => $tokenData->getClaim('me'),
|
|
|
|
|
'scope' => $tokenData->getClaim('scope'),
|
|
|
|
|
'client_id' => $tokenData->getClaim('client_id'),
|
2017-03-24 15:40:36 +00:00
|
|
|
|
],
|
|
|
|
|
]);
|
2016-05-19 15:01:28 +01:00
|
|
|
|
}
|
2017-03-07 18:47:29 +00:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Process a media item posted to the media endpoint.
|
|
|
|
|
*
|
|
|
|
|
* @param Illuminate\Http\Request $request
|
|
|
|
|
* @return Illuminate\Http\Response
|
|
|
|
|
*/
|
|
|
|
|
public function media(Request $request)
|
|
|
|
|
{
|
2017-05-18 15:15:53 +01:00
|
|
|
|
try {
|
|
|
|
|
$tokenData = $this->tokenService->validateToken($request->bearerToken());
|
|
|
|
|
} catch (InvalidTokenException $e) {
|
2017-03-24 15:40:36 +00:00
|
|
|
|
return response()->json([
|
|
|
|
|
'response' => 'error',
|
|
|
|
|
'error' => 'invalid_token',
|
|
|
|
|
'error_description' => 'The provided token did not pass validation',
|
|
|
|
|
], 400);
|
|
|
|
|
}
|
2017-03-07 18:47:29 +00:00
|
|
|
|
|
2017-07-12 19:00:48 +01:00
|
|
|
|
$logger = new Logger('micropub');
|
|
|
|
|
$logger->pushHandler(new StreamHandler(storage_path('logs/micropub.log')), Logger::DEBUG);
|
|
|
|
|
$logger->debug('MicropubMediaLog', $request->all());
|
2017-03-24 15:40:36 +00:00
|
|
|
|
//check post scope
|
|
|
|
|
if ($tokenData->hasClaim('scope')) {
|
2017-06-22 17:42:21 +01:00
|
|
|
|
if (stristr($tokenData->getClaim('scope'), 'create') === false) {
|
2017-05-18 15:15:53 +01:00
|
|
|
|
return $this->returnInsufficientScopeResponse();
|
|
|
|
|
}
|
|
|
|
|
//check media valid
|
|
|
|
|
if ($request->hasFile('file') && $request->file('file')->isValid()) {
|
|
|
|
|
try {
|
|
|
|
|
$filename = Uuid::uuid4() . '.' . $request->file('file')->extension();
|
|
|
|
|
} catch (UnsatisfiedDependencyException $e) {
|
2017-03-10 11:27:28 +00:00
|
|
|
|
return response()->json([
|
2017-05-18 15:15:53 +01:00
|
|
|
|
'response' => 'error',
|
|
|
|
|
'error' => 'internal_server_error',
|
|
|
|
|
'error_description' => 'A problem occured handling your request',
|
|
|
|
|
], 500);
|
2017-03-10 11:27:28 +00:00
|
|
|
|
}
|
2017-05-18 15:15:53 +01:00
|
|
|
|
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;
|
2017-07-13 17:33:00 +01:00
|
|
|
|
$media->type = $this->getFileTypeFromMimeType($request->file('file')->getMimeType());
|
2017-05-18 15:15:53 +01:00
|
|
|
|
$media->save();
|
2017-03-10 11:27:28 +00:00
|
|
|
|
|
|
|
|
|
return response()->json([
|
2017-05-18 15:15:53 +01:00
|
|
|
|
'response' => 'created',
|
|
|
|
|
'location' => $media->url,
|
|
|
|
|
], 201)->header('Location', $media->url);
|
2017-03-10 11:27:28 +00:00
|
|
|
|
}
|
2017-05-18 15:15:53 +01:00
|
|
|
|
|
|
|
|
|
return response()->json([
|
|
|
|
|
'response' => 'error',
|
|
|
|
|
'error' => 'invalid_request',
|
|
|
|
|
'error_description' => 'The uploaded file failed validation',
|
|
|
|
|
], 400);
|
2017-03-24 15:47:10 +00:00
|
|
|
|
}
|
2017-03-10 11:27:28 +00:00
|
|
|
|
|
2017-03-07 18:47:29 +00:00
|
|
|
|
return response()->json([
|
|
|
|
|
'response' => 'error',
|
2017-05-18 15:15:53 +01:00
|
|
|
|
'error' => 'invalid_request',
|
|
|
|
|
'error_description' => 'The provided token has no scopes',
|
|
|
|
|
], 400);
|
2017-03-07 18:47:29 +00:00
|
|
|
|
}
|
2017-03-19 10:04:48 +00:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the file type from the mimetype of the uploaded file.
|
|
|
|
|
*
|
|
|
|
|
* @param string The mimetype
|
|
|
|
|
* @return string The type
|
|
|
|
|
*/
|
|
|
|
|
private function getFileTypeFromMimeType($mimetype)
|
|
|
|
|
{
|
|
|
|
|
//try known images
|
|
|
|
|
$imageMimeTypes = [
|
|
|
|
|
'image/gif',
|
|
|
|
|
'image/jpeg',
|
|
|
|
|
'image/png',
|
|
|
|
|
'image/svg+xml',
|
|
|
|
|
'image/tiff',
|
|
|
|
|
'image/webp',
|
|
|
|
|
];
|
|
|
|
|
if (in_array($mimetype, $imageMimeTypes)) {
|
|
|
|
|
return 'image';
|
|
|
|
|
}
|
|
|
|
|
//try known video
|
|
|
|
|
$videoMimeTypes = [
|
|
|
|
|
'video/mp4',
|
|
|
|
|
'video/mpeg',
|
|
|
|
|
'video/quicktime',
|
|
|
|
|
'video/webm',
|
|
|
|
|
];
|
|
|
|
|
if (in_array($mimetype, $videoMimeTypes)) {
|
|
|
|
|
return 'video';
|
|
|
|
|
}
|
|
|
|
|
//try known audio types
|
|
|
|
|
$audioMimeTypes = [
|
|
|
|
|
'audio/midi',
|
|
|
|
|
'audio/mpeg',
|
|
|
|
|
'audio/ogg',
|
|
|
|
|
'audio/x-m4a',
|
|
|
|
|
];
|
|
|
|
|
if (in_array($mimetype, $audioMimeTypes)) {
|
|
|
|
|
return 'audio';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 'download';
|
|
|
|
|
}
|
2017-05-18 15:15:53 +01:00
|
|
|
|
|
|
|
|
|
private function returnInsufficientScopeResponse()
|
|
|
|
|
{
|
|
|
|
|
return response()->json([
|
|
|
|
|
'response' => 'error',
|
|
|
|
|
'error' => 'insufficient_scope',
|
|
|
|
|
'error_description' => 'The token’s scope does not have the necessary requirements.',
|
|
|
|
|
], 401);
|
|
|
|
|
}
|
2016-05-19 15:01:28 +01:00
|
|
|
|
}
|