From a54aa8e0c725e2bcfd776a10f8aa4d01a143e1d1 Mon Sep 17 00:00:00 2001 From: Aaron Parecki Date: Thu, 4 Feb 2016 18:54:43 -0800 Subject: [PATCH] adds API route to handle Superfeedr payload * new API route to handle Superfeedr notification of a mention * sends webmentions to all URLs on the target domain of the notification * adds "url" column to sites to specify the domain to use for superfeedr pings * includes database migration --- controllers/API.php | 44 ++++++++++++++++++++++++++++++- controllers/Auth.php | 1 + migrations/20160204131300.sql | 7 +++++ schema.sql => migrations/init.sql | 0 public/index.php | 1 + tests/APITest.php | 22 ++++++++++++++++ 6 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 migrations/20160204131300.sql rename schema.sql => migrations/init.sql (100%) diff --git a/controllers/API.php b/controllers/API.php index 8e955bd..d3cbbf0 100644 --- a/controllers/API.php +++ b/controllers/API.php @@ -35,7 +35,6 @@ class API { } public function webmention(Request $request, Response $response) { - # Require the token parameter if(!$token=$request->get('token')) { return $this->respond($response, 401, [ @@ -160,6 +159,49 @@ class API { return $this->respond($response, 201, $body, $headers); } + public function superfeedr_tracker(Request $request, Response $response, $args) { + # Require the code parameter + if(!$token=$args['token']) { + return $this->respond($response, 401, [ + 'error' => 'authentication_required', + 'error_description' => 'A token is required to use the API' + ]); + } + + # Verify the token is valid + $role = ORM::for_table('roles')->where('token', $token)->find_one(); + + if(!$role) { + return $this->respond($response, 401, [ + 'error' => 'invalid_token', + 'error_description' => 'The token provided is not valid' + ]); + } + + $site = ORM::for_table('sites')->where('id', $role->site_id)->find_one(); + + if(($items = $request->get('items')) + && is_array($items) + && array_key_exists(0, $items) + && ($item = $items[0]) + && array_key_exists('permalinkUrl', $item)) { + $url = $item['permalinkUrl']; + + $domain = parse_url($site->url, PHP_URL_HOST); + + # Create a new request that looks like a request to the API with a target_domain parameter + $new_request = new Request(['token' => $token, 'source' => $url, 'target_domain' => $domain]); + + return $this->webmention($new_request, $response); + + } else { + return $this->respond($response, 400, [ + 'error' => 'invalid_request', + 'error_description' => 'Could not find source URL from the superfeedr payload' + ]); + } + } + public function webmention_status(Request $request, Response $response, $args) { $webmention = ORM::for_table('webmentions')->where('token', $args['code'])->find_one(); diff --git a/controllers/Auth.php b/controllers/Auth.php index d06f457..0af1852 100644 --- a/controllers/Auth.php +++ b/controllers/Auth.php @@ -130,6 +130,7 @@ class Auth { // Create a site for them with the default role $site = ORM::for_table('sites')->create(); $site->name = 'My Website'; + $site->url = $token['auth']['me']; $site->created_by = $user->id; $site->created_at = date('Y-m-d H:i:s'); $site->save(); diff --git a/migrations/20160204131300.sql b/migrations/20160204131300.sql new file mode 100644 index 0000000..4389a17 --- /dev/null +++ b/migrations/20160204131300.sql @@ -0,0 +1,7 @@ +ALTER TABLE sites +ADD COLUMN url VARCHAR(255) DEFAULT NULL AFTER name; + +UPDATE sites +JOIN roles ON sites.id = roles.site_id +JOIN users ON users.id = roles.user_id +SET sites.url = users.url; diff --git a/schema.sql b/migrations/init.sql similarity index 100% rename from schema.sql rename to migrations/init.sql diff --git a/public/index.php b/public/index.php index ebd56c7..ede0878 100644 --- a/public/index.php +++ b/public/index.php @@ -16,6 +16,7 @@ $router->addRoute('POST', '/dashboard/get_outgoing_links.json', 'Controller::get $router->addRoute('POST', '/dashboard/discover_endpoint.json', 'Controller::discover_endpoint'); $router->addRoute('POST', '/webmention', 'API::webmention'); +$router->addRoute('POST', '/superfeedr/{token}', 'API::superfeedr_tracker'); $router->addRoute('GET', '/webmention/{code}', 'API::webmention_status'); $router->addRoute('GET', '/login', 'Auth::login'); diff --git a/tests/APITest.php b/tests/APITest.php index 103f097..8e903b5 100644 --- a/tests/APITest.php +++ b/tests/APITest.php @@ -22,6 +22,12 @@ class APITest extends PHPUnit_Framework_TestCase { return $this->client->webmention($request, $response); } + private function superfeedr_tracker($params, $args) { + $request = new Request($params); + $response = new Response(); + return $this->client->superfeedr_tracker($request, $response, $args); + } + private function status($code) { $request = new Request(); $response = new Response(); @@ -35,6 +41,7 @@ class APITest extends PHPUnit_Framework_TestCase { $site = ORM::for_table('sites')->create(); $site->name = 'Example'; + $site->url = 'http://example.com'; $site->created_by = $user->id(); $site->save(); @@ -245,4 +252,19 @@ class APITest extends PHPUnit_Framework_TestCase { $this->assertEquals('not_found', $data->status); } + public function testSuperfeedrTracker() { + $this->_createExampleAccount(); + + $payload = [ + 'items' => [[ + 'permalinkUrl' => 'http://source.example.com/basictest' + ]] + ]; + $response = $this->superfeedr_tracker($payload, ['token'=>'a']); + + $this->assertEquals(201, $response->getStatusCode()); + $data = json_decode($response->getContent()); + $this->assertEquals('queued', $data->status); + } + }