diff --git a/database.sql b/database.sql index b986cc409f..1f35cd0573 100644 --- a/database.sql +++ b/database.sql @@ -1,6 +1,6 @@ -- ------------------------------------------ -- Friendica 2022.05-dev (Siberian Iris) --- DB_UPDATE_VERSION 1454 +-- DB_UPDATE_VERSION 1455 -- ------------------------------------------ @@ -1526,6 +1526,7 @@ CREATE TABLE IF NOT EXISTS `user-contact` ( `ignored` boolean COMMENT 'Posts from this contact are ignored', `collapsed` boolean COMMENT 'Posts from this contact are collapsed', `hidden` boolean COMMENT 'This contact is hidden from the others', + `is-blocked` boolean COMMENT 'User is blocked by this contact', `pending` boolean COMMENT '', `rel` tinyint unsigned COMMENT 'The kind of the relation between the user and the contact', `info` mediumtext COMMENT '', diff --git a/doc/database/db_user-contact.md b/doc/database/db_user-contact.md index 2cd910bb05..30c80c5261 100644 --- a/doc/database/db_user-contact.md +++ b/doc/database/db_user-contact.md @@ -15,6 +15,7 @@ Fields | ignored | Posts from this contact are ignored | boolean | YES | | NULL | | | collapsed | Posts from this contact are collapsed | boolean | YES | | NULL | | | hidden | This contact is hidden from the others | boolean | YES | | NULL | | +| is-blocked | User is blocked by this contact | boolean | YES | | NULL | | | pending | | boolean | YES | | NULL | | | rel | The kind of the relation between the user and the contact | tinyint unsigned | YES | | NULL | | | info | | mediumtext | YES | | NULL | | diff --git a/src/Model/Contact/User.php b/src/Model/Contact/User.php index c39b1302a4..665b95624d 100644 --- a/src/Model/Contact/User.php +++ b/src/Model/Contact/User.php @@ -311,4 +311,48 @@ class User return $collapsed; } + + /** + * Set/Release that the user is blocked by the contact + * + * @param int $cid Either public contact id or user's contact id + * @param int $uid User ID + * @param boolean $blocked Is the user blocked or unblocked by the contact? + * @throws \Exception + */ + public static function setIsBlocked($cid, $uid, $blocked) + { + $cdata = Contact::getPublicAndUserContactID($cid, $uid); + if (empty($cdata)) { + return; + } + + DBA::update('user-contact', ['is-blocked' => $blocked], ['cid' => $cdata['public'], 'uid' => $uid], true); + } + + /** + * Returns if the user is blocked by the contact + * + * @param int $cid Either public contact id or user's contact id + * @param int $uid User ID + * + * @return boolean Is the user blocked or unblocked by the contact? + * @throws \Exception + */ + public static function isIsBlocked($cid, $uid) + { + $cdata = Contact::getPublicAndUserContactID($cid, $uid); + if (empty($cdata)) { + return false; + } + + if (!empty($cdata['public'])) { + $public_contact = DBA::selectFirst('user-contact', ['is-blocked'], ['cid' => $cdata['public'], 'uid' => $uid]); + if (DBA::isResult($public_contact)) { + return $public_contact['is-blocked']; + } + } + + return false; + } } diff --git a/src/Protocol/ActivityPub/Processor.php b/src/Protocol/ActivityPub/Processor.php index 5caef7745e..5604043fa4 100644 --- a/src/Protocol/ActivityPub/Processor.php +++ b/src/Protocol/ActivityPub/Processor.php @@ -1206,6 +1206,52 @@ class Processor Logger::info('Deleted contact', ['object' => $activity['object_id']]); } + /** + * Blocks the user by the contact + * + * @param array $activity + * @throws \Exception + */ + public static function blockAccount($activity) + { + $cid = Contact::getIdForURL($activity['actor']); + if (empty($cid)) { + return; + } + + $uid = User::getIdForURL($activity['object_id']); + if (empty($uid)) { + return; + } + + Contact\User::setIsBlocked($cid, $uid, true); + + Logger::info('Contact blocked user', ['contact' => $cid, 'user' => $uid]); + } + + /** + * Unblocks the user by the contact + * + * @param array $activity + * @throws \Exception + */ + public static function unblockAccount($activity) + { + $cid = Contact::getIdForURL($activity['actor']); + if (empty($cid)) { + return; + } + + $uid = User::getIdForURL($activity['object_object']); + if (empty($uid)) { + return; + } + + Contact\User::setIsBlocked($cid, $uid, false); + + Logger::info('Contact unblocked user', ['contact' => $cid, 'user' => $uid]); + } + /** * Accept a follow request * diff --git a/src/Protocol/ActivityPub/Receiver.php b/src/Protocol/ActivityPub/Receiver.php index 80bba0b0b9..caf97231fe 100644 --- a/src/Protocol/ActivityPub/Receiver.php +++ b/src/Protocol/ActivityPub/Receiver.php @@ -670,8 +670,7 @@ class Receiver case 'as:Block': if (in_array($object_data['object_type'], self::ACCOUNT_TYPES)) { - // Used by Mastodon to announce that the sender has blocked the account - self::storeUnhandledActivity(false, $type, $object_data, $activity, $body, $uid, $trust_source, $push, $signer); + ActivityPub\Processor::blockAccount($object_data); } else { self::storeUnhandledActivity(true, $type, $object_data, $activity, $body, $uid, $trust_source, $push, $signer); } @@ -728,6 +727,9 @@ class Receiver } elseif (($object_data['object_type'] == 'as:Accept') && in_array($object_data['object_object_type'], self::ACCOUNT_TYPES)) { ActivityPub\Processor::rejectFollowUser($object_data); + } elseif (($object_data['object_type'] == 'as:Block') && + in_array($object_data['object_object_type'], self::ACCOUNT_TYPES)) { + ActivityPub\Processor::unblockAccount($object_data); } elseif (in_array($object_data['object_type'], array_merge(self::ACTIVITY_TYPES, ['as:Announce'])) && in_array($object_data['object_object_type'], array_merge(['as:Tombstone'], self::CONTENT_TYPES))) { ActivityPub\Processor::undoActivity($object_data); diff --git a/static/dbstructure.config.php b/static/dbstructure.config.php index 36c9ca3e0a..95daab4649 100644 --- a/static/dbstructure.config.php +++ b/static/dbstructure.config.php @@ -55,7 +55,7 @@ use Friendica\Database\DBA; if (!defined('DB_UPDATE_VERSION')) { - define('DB_UPDATE_VERSION', 1454); + define('DB_UPDATE_VERSION', 1455); } return [ @@ -1544,6 +1544,7 @@ return [ "ignored" => ["type" => "boolean", "comment" => "Posts from this contact are ignored"], "collapsed" => ["type" => "boolean", "comment" => "Posts from this contact are collapsed"], "hidden" => ["type" => "boolean", "comment" => "This contact is hidden from the others"], + "is-blocked" => ["type" => "boolean", "comment" => "User is blocked by this contact"], "pending" => ["type" => "boolean", "comment" => ""], "rel" => ["type" => "tinyint unsigned", "comment" => "The kind of the relation between the user and the contact"], "info" => ["type" => "mediumtext", "comment" => ""],