]> git.mxchange.org Git - friendica.git/commitdiff
API: First steps to support subscriptions
authorMichael <heluecht@pirati.ca>
Sun, 15 Aug 2021 00:30:41 +0000 (00:30 +0000)
committerMichael <heluecht@pirati.ca>
Sun, 15 Aug 2021 00:30:41 +0000 (00:30 +0000)
18 files changed:
database.sql
doc/API-Mastodon.md
doc/database.md
doc/database/db_subscription.md [new file with mode: 0644]
src/DI.php
src/Factory/Api/Mastodon/Subscription.php [new file with mode: 0644]
src/Model/Subscription.php [new file with mode: 0644]
src/Module/Api/Mastodon/Accounts/Followers.php
src/Module/Api/Mastodon/Accounts/Following.php
src/Module/Api/Mastodon/Blocks.php
src/Module/Api/Mastodon/Favourited.php
src/Module/Api/Mastodon/Lists/Accounts.php
src/Module/Api/Mastodon/Mutes.php
src/Module/Api/Mastodon/PushSubscription.php [new file with mode: 0644]
src/Object/Api/Mastodon/Subscription.php [new file with mode: 0644]
src/Util/Crypto.php
static/dbstructure.config.php
static/routes.config.php

index 4d444cbe50ddcd97d7c6d03eb0316f1a792baca9..eff8f83faf819ba88b0e92fae6eccdb5329a745c 100644 (file)
@@ -1,6 +1,6 @@
 -- ------------------------------------------
 -- Friendica 2021.09-dev (Siberian Iris)
--- DB_UPDATE_VERSION 1433
+-- DB_UPDATE_VERSION 1434
 -- ------------------------------------------
 
 
@@ -1472,6 +1472,30 @@ CREATE TABLE IF NOT EXISTS `storage` (
         PRIMARY KEY(`id`)
 ) DEFAULT COLLATE utf8mb4_general_ci COMMENT='Data stored by Database storage backend';
 
+--
+-- TABLE subscription
+--
+CREATE TABLE IF NOT EXISTS `subscription` (
+       `id` int unsigned NOT NULL auto_increment COMMENT 'Auto incremented image data id',
+       `application-id` int unsigned NOT NULL COMMENT '',
+       `uid` mediumint unsigned NOT NULL COMMENT 'Owner User id',
+       `endpoint` varchar(511) COMMENT 'Endpoint URL',
+       `pubkey` varchar(127) COMMENT 'User agent public key',
+       `secret` varchar(32) COMMENT 'Auth secret',
+       `follow` boolean COMMENT '',
+       `favourite` boolean COMMENT '',
+       `reblog` boolean COMMENT '',
+       `mention` boolean COMMENT '',
+       `poll` boolean COMMENT '',
+       `follow_request` boolean COMMENT '',
+       `status` boolean COMMENT '',
+        PRIMARY KEY(`id`),
+        UNIQUE INDEX `application-id_uid` (`application-id`,`uid`),
+        INDEX `uid_application-id` (`uid`,`application-id`),
+       FOREIGN KEY (`application-id`) REFERENCES `application` (`id`) ON UPDATE RESTRICT ON DELETE CASCADE,
+       FOREIGN KEY (`uid`) REFERENCES `user` (`uid`) ON UPDATE RESTRICT ON DELETE CASCADE
+) DEFAULT COLLATE utf8mb4_general_ci COMMENT='Push Subscription for the API';
+
 --
 -- TABLE userd
 --
index 006b8da4736d164ae9305885211dc4330a92d00f..dd82a5144d97d41b55445e34b7b2c0bcd9e6977f 100644 (file)
@@ -93,7 +93,12 @@ These endpoints use the [Mastodon API entities](https://docs.joinmastodon.org/en
 - [`POST /api/v1/notifications/clear`](https://docs.joinmastodon.org/methods/notifications/)
 - [`POST /api/v1/notifications/:id/dismiss`](https://docs.joinmastodon.org/methods/notifications/)
 - [`GET /api/v1/preferences`](https://docs.joinmastodon.org/methods/accounts/preferences/)
+- [`DELETE /api/v1/push/subscription`](https://docs.joinmastodon.org/methods/notifications/push/)
+- [`GET /api/v1/push/subscription`](https://docs.joinmastodon.org/methods/notifications/push/)
+- [`PUSH /api/v1/push/subscription`](https://docs.joinmastodon.org/methods/notifications/push/)
 - [`GET /api/v1/scheduled_statuses`](https://docs.joinmastodon.org/methods/statuses/scheduled_statuses/)
+- [`DELETE /api/v1/scheduled_statuses/:id`](https://docs.joinmastodon.org/methods/statuses/scheduled_statuses/)
+- [`GET /api/v1/scheduled_statuses/:id`](https://docs.joinmastodon.org/methods/statuses/scheduled_statuses/)
 - [`GET /api/v1/search`](https://docs.joinmastodon.org/methods/search/)
 - [`POST /api/v1/statuses`](https://docs.joinmastodon.org/methods/statuses/)
 - [`GET /api/v1/statuses/:id`](https://docs.joinmastodon.org/methods/statuses/)
@@ -173,13 +178,8 @@ They refer to features or data that don't exist in Friendica yet.
 - [`POST /api/v1/markers`](https://docs.joinmastodon.org/methods/timelines/markers/)
 - [`GET /api/v1/polls/:id`](https://docs.joinmastodon.org/methods/statuses/polls/)
 - [`POST /api/v1/polls/:id/votes`](https://docs.joinmastodon.org/methods/statuses/polls/)
-- [`DELETE /api/v1/push/subscription`](https://docs.joinmastodon.org/methods/notifications/push/)
-- [`GET /api/v1/push/subscription`](https://docs.joinmastodon.org/methods/notifications/push/)
-- [`PUSH /api/v1/push/subscription`](https://docs.joinmastodon.org/methods/notifications/push/)
 - [`PUT /api/v1/push/subscription`](https://docs.joinmastodon.org/methods/notifications/push/)
 - [`POST /api/v1/reports`](https://docs.joinmastodon.org/methods/accounts/reports/)
-- [`GET /api/v1/scheduled_statuses/:id`](https://docs.joinmastodon.org/methods/statuses/scheduled_statuses/)
 - [`PUT /api/v1/scheduled_statuses/:id`](https://docs.joinmastodon.org/methods/statuses/scheduled_statuses/)
-- [`DELETE /api/v1/scheduled_statuses/:id`](https://docs.joinmastodon.org/methods/statuses/scheduled_statuses/)
 - [`GET /api/v1/streaming`](https://docs.joinmastodon.org/methods/timelines/streaming/)
 - [`DELETE /api/v1/suggestions/:id`](https://docs.joinmastodon.org/methods/accounts/suggestions/)
index 194f30eb6eac0dc57512c79368bbab17a92f0654..bc690c6cd28855c8a09d9c6d67d5afc5de3950e1 100644 (file)
@@ -65,6 +65,7 @@ Database Tables
 | [search](help/database/db_search) |  |
 | [session](help/database/db_session) | web session storage |
 | [storage](help/database/db_storage) | Data stored by Database storage backend |
+| [subscription](help/database/db_subscription) | Push Subscription for the API |
 | [tag](help/database/db_tag) | tags and mentions |
 | [user](help/database/db_user) | The local users |
 | [user-contact](help/database/db_user-contact) | User specific public contact data |
diff --git a/doc/database/db_subscription.md b/doc/database/db_subscription.md
new file mode 100644 (file)
index 0000000..8bcf4f2
--- /dev/null
@@ -0,0 +1,42 @@
+Table subscription
+===========
+
+Push Subscription for the API
+
+Fields
+------
+
+| Field          | Description                    | Type               | Null | Key | Default | Extra          |
+| -------------- | ------------------------------ | ------------------ | ---- | --- | ------- | -------------- |
+| id             | Auto incremented image data id | int unsigned       | NO   | PRI | NULL    | auto_increment |
+| application-id |                                | int unsigned       | NO   |     | NULL    |                |
+| uid            | Owner User id                  | mediumint unsigned | NO   |     | NULL    |                |
+| endpoint       | Endpoint URL                   | varchar(511)       | YES  |     | NULL    |                |
+| pubkey         | User agent public key          | varchar(127)       | YES  |     | NULL    |                |
+| secret         | Auth secret                    | varchar(32)        | YES  |     | NULL    |                |
+| follow         |                                | boolean            | YES  |     | NULL    |                |
+| favourite      |                                | boolean            | YES  |     | NULL    |                |
+| reblog         |                                | boolean            | YES  |     | NULL    |                |
+| mention        |                                | boolean            | YES  |     | NULL    |                |
+| poll           |                                | boolean            | YES  |     | NULL    |                |
+| follow_request |                                | boolean            | YES  |     | NULL    |                |
+| status         |                                | boolean            | YES  |     | NULL    |                |
+
+Indexes
+------------
+
+| Name               | Fields                      |
+| ------------------ | --------------------------- |
+| PRIMARY            | id                          |
+| application-id_uid | UNIQUE, application-id, uid |
+| uid_application-id | uid, application-id         |
+
+Foreign Keys
+------------
+
+| Field | Target Table | Target Field |
+|-------|--------------|--------------|
+| application-id | [application](help/database/db_application) | id |
+| uid | [user](help/database/db_user) | uid |
+
+Return to [database documentation](help/database)
index 0bfaacf89a064c348c0987401842bc24e99757f8..02620ea11eac21ce38e78c87dccf06ee02675694 100644 (file)
@@ -319,6 +319,14 @@ abstract class DI
                return self::$dice->create(Factory\Api\Mastodon\ScheduledStatus::class);
        }
 
+       /**
+        * @return Factory\Api\Mastodon\Subscription
+        */
+       public static function mstdnSubscription()
+       {
+               return self::$dice->create(Factory\Api\Mastodon\Subscription::class);
+       }
+
        /**
         * @return Factory\Api\Mastodon\ListEntity
         */
diff --git a/src/Factory/Api/Mastodon/Subscription.php b/src/Factory/Api/Mastodon/Subscription.php
new file mode 100644 (file)
index 0000000..3b8f343
--- /dev/null
@@ -0,0 +1,41 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2021, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Factory\Api\Mastodon;
+
+use Friendica\BaseFactory;
+use Friendica\Database\DBA;
+use Friendica\Model\Subscription as ModelSubscription;
+
+class Subscription extends BaseFactory
+{
+       /**
+        * @param int $applicationid Application Id
+        * @param int $uid           Item user
+        *
+        * @return \Friendica\Object\Api\Mastodon\Status
+        */
+       public function createForApplicationIdAndUserId(int $applicationid, int $uid): \Friendica\Object\Api\Mastodon\Subscription
+       {
+               $subscription = DBA::selectFirst('subscription', ['application-id' => $applicationid, 'uid' => $uid]);
+               return new \Friendica\Object\Api\Mastodon\Subscription($subscription, ModelSubscription::getVapidKey());
+       }
+}
diff --git a/src/Model/Subscription.php b/src/Model/Subscription.php
new file mode 100644 (file)
index 0000000..173d5a9
--- /dev/null
@@ -0,0 +1,66 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2021, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Model;
+
+use Friendica\Database\DBA;
+use Friendica\DI;
+use Friendica\Util\Crypto;
+
+class Subscription
+{
+       /**
+        * Insert an Subscription record
+        *
+        * @param array $fields subscription fields
+        *
+        * @return bool result of replace
+        */
+       public static function replace(array $fields)
+       {
+               return DBA::replace('subscription', $fields);
+       }
+
+       /**
+        * Delete a subscription record
+        * @param int $applicationid 
+        * @param int $uid 
+        * @return bool 
+        */
+       public static function delete(int $applicationid, int $uid)
+       {
+               return DBA::delete('subscription', ['application-id' => $applicationid, 'uid' => $uid]);
+       }
+
+       /**
+        * Fetch a VAPID key
+        * @return string
+        */
+       public static function getVapidKey():string
+       {
+               $keypair = DI::config()->get('system', 'ec_keypair');
+               if (empty($keypair)) {
+                       $keypair = Crypto::newECKeypair();
+                       DI::config()->set('system', 'ec_keypair', $keypair);
+               }
+               return $keypair['vapid'];
+       }
+}
index c495d6ca1ec8b70b3ca6841061ab620880064cfa..e1f864acbe930193141ed192aff80c1efc9c5973 100644 (file)
@@ -49,8 +49,6 @@ class Followers extends BaseApi
                        DI::mstdnError()->RecordNotFound();
                }
 
-               // @todo provide HTTP link header
-
                $request = self::getRequest([
                        'max_id'   => 0,  // Return results older than this id
                        'since_id' => 0,  // Return results newer than this id
index b6a8f7f75c2096726eb8b6a242657957e6817539..e2b963e0c3e1fbe456a2584a88f7e308c2225d63 100644 (file)
@@ -49,8 +49,6 @@ class Following extends BaseApi
                        DI::mstdnError()->RecordNotFound();
                }
 
-               // @todo provide HTTP link header
-
                $request = self::getRequest([
                        'max_id'   => 0,  // Return results older than this id
                        'since_id' => 0,  // Return results newer than this id
index 37ab61af5251c0ebb349301208c396db91594f12..305914c1aadca10a1846bd99e54fddc50b1d8af2 100644 (file)
@@ -49,8 +49,6 @@ class Blocks extends BaseApi
                        DI::mstdnError()->RecordNotFound();
                }
 
-               // @todo provide HTTP link header
-
                $request = self::getRequest([
                        'max_id'   => 0,  // Return results older than this id
                        'since_id' => 0,  // Return results newer than this id
index 239257e8331c066b106ec0e9a07985d257cfcc03..31e760d3b8e0110a9b3bd3cf053ffd514b05b129 100644 (file)
@@ -43,8 +43,6 @@ class Favourited extends BaseApi
                self::checkAllowedScope(self::SCOPE_READ);
                $uid = self::getCurrentUserID();
 
-               // @todo provide HTTP link header
-
                $request = self::getRequest([
                        'limit'      => 20,    // Maximum number of results to return. Defaults to 20.
                        'min_id'     => 0,     // Return results immediately newer than id
index 013a9f4aa9d47073d441a19bd940f3bf353ab8af..6e112356303fa2ee7b473cac83fa1f364e423f1f 100644 (file)
@@ -62,8 +62,6 @@ class Accounts extends BaseApi
                        DI::mstdnError()->RecordNotFound();
                }
 
-               // @todo provide HTTP link header
-
                $request = self::getRequest([
                        'max_id'   => 0,  // Return results older than this id
                        'since_id' => 0,  // Return results newer than this id
index ea890d9fdb345d3549fbc1d024cd1afec5a980e4..7939da114b0619061c997825d1951102dcb3f5b6 100644 (file)
@@ -49,8 +49,6 @@ class Mutes extends BaseApi
                        DI::mstdnError()->RecordNotFound();
                }
 
-               // @todo provide HTTP link header
-
                $request = self::getRequest([
                        'max_id'   => 0,  // Return results older than this id
                        'since_id' => 0,  // Return results newer than this id
diff --git a/src/Module/Api/Mastodon/PushSubscription.php b/src/Module/Api/Mastodon/PushSubscription.php
new file mode 100644 (file)
index 0000000..68b1b46
--- /dev/null
@@ -0,0 +1,97 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2021, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Module\Api\Mastodon;
+
+use Friendica\App\Router;
+use Friendica\Core\Logger;
+use Friendica\Core\System;
+use Friendica\DI;
+use Friendica\Model\Subscription;
+use Friendica\Module\BaseApi;
+
+/**
+ * @see https://docs.joinmastodon.org/methods/notifications/push/
+ */
+class PushSubscription extends BaseApi
+{
+       public static function post(array $parameters = [])
+       {
+               self::checkAllowedScope(self::SCOPE_PUSH);
+               $uid         = self::getCurrentUserID();
+               $application = self::getCurrentApplication();
+
+               $request = self::getRequest([
+                       'subscription' => [],
+                       'data'         => [],
+               ]);
+
+               $subscription = [
+                       'application-id' => $application['id'],
+                       'uid'            => $uid,
+                       'endpoint'       => $request['subscription']['endpoint'] ?? '',
+                       'pubkey'         => $request['subscription']['keys']['p256dh'] ?? '',
+                       'secret'         => $request['subscription']['keys']['auth'] ?? '',
+                       'follow'         => $request['data']['alerts']['follow'] ?? false,
+                       'favourite'      => $request['data']['alerts']['favourite'] ?? false,
+                       'reblog'         => $request['data']['alerts']['reblog'] ?? false,
+                       'mention'        => $request['data']['alerts']['mention'] ?? false,
+                       'poll'           => $request['data']['alerts']['poll'] ?? false,
+                       'follow_request' => $request['data']['alerts']['follow_request'] ?? false,
+                       'status'         => $request['data']['alerts']['status'] ?? false,
+               ];
+
+               $ret = Subscription::replace($subscription);
+
+               Logger::info('Subscription stored', ['ret' => $ret, 'subscription' => $subscription]);
+
+               return DI::mstdnSubscription()->createForApplicationIdAndUserId($application['id'], $uid)->toArray();
+       }
+
+       public static function put(array $parameters = [])
+       {
+               self::checkAllowedScope(self::SCOPE_PUSH);
+               $uid         = self::getCurrentUserID();
+               $application = self::getCurrentApplication();
+
+               self::unsupported(Router::PUT);
+       }
+
+       public static function delete(array $parameters = [])
+       {
+               self::checkAllowedScope(self::SCOPE_PUSH);
+               $uid         = self::getCurrentUserID();
+               $application = self::getCurrentApplication();
+
+               Subscription::delete($application['id'], $uid);
+
+               System::jsonExit([]);
+       }
+
+       public static function rawContent(array $parameters = [])
+       {
+               self::checkAllowedScope(self::SCOPE_PUSH);
+               $uid         = self::getCurrentUserID();
+               $application = self::getCurrentApplication();
+
+               return DI::mstdnSubscription()->createForApplicationIdAndUserId($application['id'], $uid)->toArray();
+       }
+}
diff --git a/src/Object/Api/Mastodon/Subscription.php b/src/Object/Api/Mastodon/Subscription.php
new file mode 100644 (file)
index 0000000..dcd0a69
--- /dev/null
@@ -0,0 +1,63 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2021, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Object\Api\Mastodon;
+
+use Friendica\BaseDataTransferObject;
+
+/**
+ * Class Subscription
+ *
+ * @see https://docs.joinmastodon.org/entities/pushsubscription
+ */
+class Subscription extends BaseDataTransferObject
+{
+       /** @var string */
+       protected $id;
+       /** @var string|null (URL)*/
+       protected $endpoint;
+       /** @var array */
+       protected $alerts;
+       /** @var string */
+       protected $server_key;
+
+       /**
+        * Creates a subscription record from an item record.
+        *
+        * @param array   $subscription
+        * @throws \Friendica\Network\HTTPException\InternalServerErrorException
+        */
+       public function __construct(array $subscription, string $vapid)
+       {
+               $this->id       = (string)$subscription['id'];
+               $this->endpoint = $subscription['endpoint'];
+               $this->alerts   = [
+                       'follow'    => $subscription['follow'],
+                       'favourite' => $subscription['favourite'],
+                       'reblog'    => $subscription['reblog'],
+                       'mention'   => $subscription['mention'],
+                       'mention'   => $subscription['mention'],
+                       'poll'      => $subscription['poll'],
+               ];
+
+               $this->server_key = $vapid;
+       }
+}
index 0187079e39d8087579c8c4478ba4ed4aab2c6b12..1ff0e19c3c8f1b081f8714501f189109948a7e6e 100644 (file)
@@ -25,6 +25,7 @@ use Friendica\Core\Hook;
 use Friendica\Core\Logger;
 use Friendica\Core\System;
 use Friendica\DI;
+use ParagonIE\ConstantTime\Base64UrlSafe;
 use phpseclib\Crypt\RSA;
 use phpseclib\Math\BigInteger;
 
@@ -150,6 +151,48 @@ class Crypto
                return $response;
        }
 
+       /**
+        * Create a new elliptic curve key pair
+        *
+        * @return array with the elements "prvkey", "vapid" and "pubkey"
+        */
+       public static function newECKeypair()
+       {
+               $openssl_options = [
+                       'curve_name'       => 'prime256v1',
+                       'private_key_type' => OPENSSL_KEYTYPE_EC
+               ];
+
+               $conf = DI::config()->get('system', 'openssl_conf_file');
+               if ($conf) {
+                       $openssl_options['config'] = $conf;
+               }
+               $result = openssl_pkey_new($openssl_options);
+
+               if (empty($result)) {
+                       Logger::notice('new_keypair: failed');
+                       return [];
+               }
+
+               $response = ['prvkey' => '', 'pubkey' => '', 'vapid' => ''];
+
+               // Get private key
+               openssl_pkey_export($result, $response['prvkey']);
+
+               // Get public key
+               $pkey = openssl_pkey_get_details($result);
+               $response['pubkey'] = $pkey['key'];
+
+               // Create VAPID key
+               // @see https://github.com/web-push-libs/web-push-php/blob/256a18b2a2411469c94943725fb6eccb9681bd75/src/Utils.php#L60-L62
+               $hexString = '04';
+               $hexString .= str_pad(bin2hex($pkey['ec']['x']), 64, '0', STR_PAD_LEFT);
+               $hexString .= str_pad(bin2hex($pkey['ec']['y']), 64, '0', STR_PAD_LEFT);
+               $response['vapid'] = Base64UrlSafe::encode(hex2bin($hexString));
+
+               return $response;
+       }
+
        /**
         * Encrypt a string with 'aes-256-cbc' cipher method.
         *
index f820401a192939350fd3144f34e5567be0f48ff0..6f455d14e94fb4e7a46b3bd36114a6fa087967c5 100644 (file)
@@ -55,7 +55,7 @@
 use Friendica\Database\DBA;
 
 if (!defined('DB_UPDATE_VERSION')) {
-       define('DB_UPDATE_VERSION', 1433);
+       define('DB_UPDATE_VERSION', 1434);
 }
 
 return [
@@ -1492,6 +1492,29 @@ return [
                        "PRIMARY" => ["id"]
                ]
        ],
+       "subscription" => [
+               "comment" => "Push Subscription for the API",
+               "fields" => [
+                       "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "Auto incremented image data id"],
+                       "application-id" => ["type" => "int unsigned", "not null" => "1", "foreign" => ["application" => "id"], "comment" => ""],
+                       "uid" => ["type" => "mediumint unsigned", "not null" => "1", "foreign" => ["user" => "uid"], "comment" => "Owner User id"],
+                       "endpoint" => ["type" => "varchar(511)", "comment" => "Endpoint URL"],
+                       "pubkey" => ["type" => "varchar(127)", "comment" => "User agent public key"],
+                       "secret" => ["type" => "varchar(32)", "comment" => "Auth secret"],
+                       "follow" => ["type" => "boolean", "comment" => ""],
+                       "favourite" => ["type" => "boolean", "comment" => ""],
+                       "reblog" => ["type" => "boolean", "comment" => ""],
+                       "mention" => ["type" => "boolean", "comment" => ""],
+                       "poll" => ["type" => "boolean", "comment" => ""],
+                       "follow_request" => ["type" => "boolean", "comment" => ""],
+                       "status" => ["type" => "boolean", "comment" => ""],
+               ],
+               "indexes" => [
+                       "PRIMARY" => ["id"],
+                       "application-id_uid" => ["UNIQUE", "application-id", "uid"],
+                       "uid_application-id" => ["uid", "application-id"],
+               ]
+       ],
        "userd" => [
                "comment" => "Deleted usernames",
                "fields" => [
index ac4ec53917c161647206763d6156a7db16ae329e..f47051e321e3ffa12e135b9998cb5aa646a8f928 100644 (file)
@@ -126,7 +126,7 @@ return [
                        '/polls/{id:\d+}'                    => [Module\Api\Mastodon\Unimplemented::class,            [R::GET         ]], // not supported
                        '/polls/{id:\d+}/votes'              => [Module\Api\Mastodon\Unimplemented::class,            [        R::POST]], // not supported
                        '/preferences'                       => [Module\Api\Mastodon\Preferences::class,              [R::GET         ]],
-                       '/push/subscription'                 => [Module\Api\Mastodon\Unimplemented::class,            [R::GET, R::POST, R::PUT, R::DELETE]], // not supported
+                       '/push/subscription'                 => [Module\Api\Mastodon\PushSubscription::class,         [R::GET, R::POST, R::PUT, R::DELETE]],
                        '/reports'                           => [Module\Api\Mastodon\Unimplemented::class,            [        R::POST]], // not supported
                        '/scheduled_statuses'                => [Module\Api\Mastodon\ScheduledStatuses::class,        [R::GET         ]],
                        '/scheduled_statuses/{id:\d+}'       => [Module\Api\Mastodon\ScheduledStatuses::class,        [R::GET, R::PUT, R::DELETE]],