From 73f37e4dc7247d993c4aebb385815ba8eb23605c Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Sun, 23 Jun 2019 14:11:13 -0600 Subject: [PATCH 01/49] Update .env.example --- .env.example | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.env.example b/.env.example index 2a8604cc..d87451b7 100644 --- a/.env.example +++ b/.env.example @@ -57,8 +57,8 @@ ACTIVITYPUB_SHAREDINBOX=false # php artisan optimize PF_COSTAR_ENABLED=false -CS_BLOCKED_DOMAINS='example.org,example.net,example.com' -CS_CW_DOMAINS='example.org,example.net,example.com' +CS_BLOCKED_DOMAINS='gab.com,gab.ai,develop.gab.com' +CS_CW_DOMAINS='switter.at' CS_UNLISTED_DOMAINS='example.org,example.net,example.com' ## Optional From 53b0a0601a1deda45e8f7aab1cf5b211d7ca6e56 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Sun, 23 Jun 2019 14:24:30 -0600 Subject: [PATCH 02/49] Update .env.example --- .env.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env.example b/.env.example index d87451b7..f5ed15a9 100644 --- a/.env.example +++ b/.env.example @@ -56,7 +56,7 @@ ACTIVITYPUB_SHAREDINBOX=false # php artisan optimize:clear # php artisan optimize -PF_COSTAR_ENABLED=false +PF_COSTAR_ENABLED=true CS_BLOCKED_DOMAINS='gab.com,gab.ai,develop.gab.com' CS_CW_DOMAINS='switter.at' CS_UNLISTED_DOMAINS='example.org,example.net,example.com' From 83e56333883da5442076bfe236e6fc55740c0018 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Sun, 23 Jun 2019 20:35:37 -0600 Subject: [PATCH 03/49] Update User RateLimit --- app/Util/RateLimit/User.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/Util/RateLimit/User.php b/app/Util/RateLimit/User.php index 75e4b1c6..c93aa6c4 100644 --- a/app/Util/RateLimit/User.php +++ b/app/Util/RateLimit/User.php @@ -48,4 +48,9 @@ trait User { { return 500; } + + public function getMaxInstanceBansPerDayAttribute() + { + return 100; + } } \ No newline at end of file From d2039ac3fdb9f160419c05fbdd7096976f6ad97f Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Sun, 23 Jun 2019 20:35:56 -0600 Subject: [PATCH 04/49] Update web routes --- routes/web.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routes/web.php b/routes/web.php index ee4da973..4efa8226 100644 --- a/routes/web.php +++ b/routes/web.php @@ -192,7 +192,7 @@ Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofact Route::get('privacy/blocked-users', 'SettingsController@blockedUsers')->name('settings.privacy.blocked-users'); Route::post('privacy/blocked-users', 'SettingsController@blockedUsersUpdate'); Route::get('privacy/blocked-instances', 'SettingsController@blockedInstances')->name('settings.privacy.blocked-instances'); - Route::post('privacy/blocked-instances', 'SettingsController@blockedInstanceStore'); + Route::post('privacy/blocked-instances', 'SettingsController@blockedInstanceStore')->middleware('throttle:maxInstanceBansPerDay,1440'); Route::post('privacy/blocked-instances/unblock', 'SettingsController@blockedInstanceUnblock')->name('settings.privacy.blocked-instances.unblock'); Route::get('privacy/blocked-keywords', 'SettingsController@blockedKeywords')->name('settings.privacy.blocked-keywords'); From 13f18d09c8ab8facad4adbeed25ae13223cbb2c7 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Sun, 23 Jun 2019 21:09:13 -0600 Subject: [PATCH 05/49] Update blocked instances view --- .../privacy/blocked-instances.blade.php | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/resources/views/settings/privacy/blocked-instances.blade.php b/resources/views/settings/privacy/blocked-instances.blade.php index 34fb7d8f..ff2b1812 100644 --- a/resources/views/settings/privacy/blocked-instances.blade.php +++ b/resources/views/settings/privacy/blocked-instances.blade.php @@ -64,23 +64,31 @@ }, }) .then(val => { - if (!val) throw null; + if (!val) { + swal.stopLoading(); + swal.close(); + return; + }; try { let validator = new URL(val); - if(!validator.hostname) throw null; + if(!validator.hostname || validator.protocol != 'https:') { + swal.stopLoading(); + swal.close(); + swal('Invalid URL', 'The URL you have entered is not valid, it must start with https://', 'error'); + return; + }; axios.post(window.location.href, { - domain: validator.hostname + domain: validator.href }).then(res => { window.location.href = window.location.href; }).catch(err => { swal.stopLoading(); swal.close(); - swal('An Error Occured', 'An error occured, please try again later.', 'error'); }); } catch(e) { swal.stopLoading(); swal.close(); - swal('An Error Occured', 'An error occured, please try again later.', 'error'); + swal('Invalid URL', 'The URL you have entered is not valid, it must start with https://', 'error'); } }) }); From 95807c93e5446f02787051597f19ce2480dd39bd Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Sun, 23 Jun 2019 22:22:23 -0600 Subject: [PATCH 06/49] Update AP Helpers --- app/Util/ActivityPub/Helpers.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/Util/ActivityPub/Helpers.php b/app/Util/ActivityPub/Helpers.php index f2c1169d..14e40cc4 100644 --- a/app/Util/ActivityPub/Helpers.php +++ b/app/Util/ActivityPub/Helpers.php @@ -146,9 +146,13 @@ class Helpers { $host = parse_url($valid, PHP_URL_HOST); + if(count(dns_get_record($host, DNS_A | DNS_AAAA)) == 0) { + return false; + } + if(config('costar.enabled') == true) { if( - (config('costar.domain.block') != null && in_array($host, config('costar.domain.block')) == true) || + (config('costar.domain.block') != null && Str::contains($host, config('costar.domain.block')) == true) || (config('costar.actor.block') != null && in_array($url, config('costar.actor.block')) == true) ) { return false; From 74b76ac1758a066892c6fc530acfcde29319ee9a Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Sun, 23 Jun 2019 23:31:07 -0600 Subject: [PATCH 07/49] Update PrivacySettings --- app/Http/Controllers/Settings/PrivacySettings.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/Settings/PrivacySettings.php b/app/Http/Controllers/Settings/PrivacySettings.php index d3283c92..8e987ab6 100644 --- a/app/Http/Controllers/Settings/PrivacySettings.php +++ b/app/Http/Controllers/Settings/PrivacySettings.php @@ -10,6 +10,7 @@ use App\Profile; use App\User; use App\UserFilter; use App\Util\Lexer\PrettyNumber; +use App\Util\ActivityPub\Helpers; use Auth, Cache, DB; use Illuminate\Http\Request; @@ -134,9 +135,13 @@ trait PrivacySettings public function blockedInstanceStore(Request $request) { $this->validate($request, [ - 'domain' => 'required|active_url' + 'domain' => 'required|url|min:1|max:120' ]); $domain = $request->input('domain'); + if(Helpers::validateUrl($domain) == false) { + return abort(400, 'Invalid domain'); + } + $domain = parse_url($domain, PHP_URL_HOST); $instance = Instance::firstOrCreate(['domain' => $domain]); $filter = new UserFilter; $filter->user_id = Auth::user()->profile->id; From 1c0b6134e3914556c8b0a9e726e2570deba52274 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Sun, 23 Jun 2019 23:31:45 -0600 Subject: [PATCH 08/49] Update privacy settings view --- .../views/settings/privacy/blocked-instances.blade.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/resources/views/settings/privacy/blocked-instances.blade.php b/resources/views/settings/privacy/blocked-instances.blade.php index ff2b1812..d7e6679f 100644 --- a/resources/views/settings/privacy/blocked-instances.blade.php +++ b/resources/views/settings/privacy/blocked-instances.blade.php @@ -69,12 +69,13 @@ swal.close(); return; }; + let msg = 'The URL you have entered is not valid, please try again.' try { let validator = new URL(val); if(!validator.hostname || validator.protocol != 'https:') { swal.stopLoading(); swal.close(); - swal('Invalid URL', 'The URL you have entered is not valid, it must start with https://', 'error'); + swal('Invalid URL', msg, 'error'); return; }; axios.post(window.location.href, { @@ -84,11 +85,13 @@ }).catch(err => { swal.stopLoading(); swal.close(); + swal('Invalid URL', msg, 'error'); + return; }); } catch(e) { swal.stopLoading(); swal.close(); - swal('Invalid URL', 'The URL you have entered is not valid, it must start with https://', 'error'); + swal('Invalid URL', msg, 'error'); } }) }); From 73bacf5b8d35d25c5335fae3f930b3d051af4814 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Sun, 23 Jun 2019 23:49:49 -0600 Subject: [PATCH 09/49] Update AccountController --- app/Http/Controllers/AccountController.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php index 13d5dc03..8ddc8875 100644 --- a/app/Http/Controllers/AccountController.php +++ b/app/Http/Controllers/AccountController.php @@ -191,7 +191,6 @@ class AccountController extends Controller $pid = $user->id; Cache::forget("user:filter:list:$pid"); - Cache::forget("feature:discover:people:$pid"); Cache::forget("feature:discover:posts:$pid"); Cache::forget("api:local:exp:rec:$pid"); @@ -242,7 +241,6 @@ class AccountController extends Controller $pid = $user->id; Cache::forget("user:filter:list:$pid"); - Cache::forget("feature:discover:people:$pid"); Cache::forget("feature:discover:posts:$pid"); Cache::forget("api:local:exp:rec:$pid"); @@ -296,7 +294,6 @@ class AccountController extends Controller $pid = $user->id; Cache::forget("user:filter:list:$pid"); - Cache::forget("feature:discover:people:$pid"); Cache::forget("feature:discover:posts:$pid"); Cache::forget("api:local:exp:rec:$pid"); @@ -348,7 +345,6 @@ class AccountController extends Controller $pid = $user->id; Cache::forget("user:filter:list:$pid"); - Cache::forget("feature:discover:people:$pid"); Cache::forget("feature:discover:posts:$pid"); Cache::forget("api:local:exp:rec:$pid"); From 9d2b5c43bae14d66d1750339968e147222d07e87 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Sun, 23 Jun 2019 23:50:20 -0600 Subject: [PATCH 10/49] Update FollowPipeline --- app/Jobs/FollowPipeline/FollowPipeline.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/Jobs/FollowPipeline/FollowPipeline.php b/app/Jobs/FollowPipeline/FollowPipeline.php index 17ad4788..57ed1d2e 100644 --- a/app/Jobs/FollowPipeline/FollowPipeline.php +++ b/app/Jobs/FollowPipeline/FollowPipeline.php @@ -61,8 +61,6 @@ class FollowPipeline implements ShouldQueue $notification->item_type = "App\Profile"; $notification->save(); - Cache::forever('notification.'.$notification->id, $notification); - Cache::forget('feature:discover:people:'.$actor->id); $redis = Redis::connection(); $nkey = config('cache.prefix').':user.'.$target->id.'.notifications'; From 8c860dc2edba8d75106a8259fb1b2a55ee629c9c Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Sun, 23 Jun 2019 23:50:42 -0600 Subject: [PATCH 11/49] Update SharePipeline --- app/Jobs/SharePipeline/SharePipeline.php | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/app/Jobs/SharePipeline/SharePipeline.php b/app/Jobs/SharePipeline/SharePipeline.php index 6d581eb7..186188ea 100644 --- a/app/Jobs/SharePipeline/SharePipeline.php +++ b/app/Jobs/SharePipeline/SharePipeline.php @@ -2,16 +2,13 @@ namespace App\Jobs\SharePipeline; -use App\Status; -use App\Notification; -use Cache; +use Cache, Log, Redis; +use App\{Status, Notification}; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; -use Log; -use Redis; class SharePipeline implements ShouldQueue { @@ -74,8 +71,6 @@ class SharePipeline implements ShouldQueue $notification->item_type = "App\Status"; $notification->save(); - Cache::forever('notification.'.$notification->id, $notification); - $redis = Redis::connection(); $key = config('cache.prefix').':user.'.$status->profile_id.'.notifications'; $redis->lpush($key, $notification->id); From 84fba79f0e1b8353acc59cc1b0d213235f58f525 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Sun, 23 Jun 2019 23:54:45 -0600 Subject: [PATCH 12/49] Add new tests --- tests/Unit/APAnnounceStrategyTest.php | 86 +++++++++++++++++++++ tests/Unit/ActivityPub/RemoteFollowTest.php | 27 +++++++ 2 files changed, 113 insertions(+) create mode 100644 tests/Unit/APAnnounceStrategyTest.php create mode 100644 tests/Unit/ActivityPub/RemoteFollowTest.php diff --git a/tests/Unit/APAnnounceStrategyTest.php b/tests/Unit/APAnnounceStrategyTest.php new file mode 100644 index 00000000..30b2bf1e --- /dev/null +++ b/tests/Unit/APAnnounceStrategyTest.php @@ -0,0 +1,86 @@ +invalid = [ + 'id' => 'test', + 'type' => 'Announce', + 'actor' => null, + 'published' => '', + 'to' => ['test'], + 'cc' => 'test', + 'object' => 'test' + ]; + + $this->mastodon = json_decode('{"@context":["https://www.w3.org/ns/activitystreams","https://w3id.org/security/v1",{"manuallyApprovesFollowers":"as:manuallyApprovesFollowers","sensitive":"as:sensitive","movedTo":{"@id":"as:movedTo","@type":"@id"},"Hashtag":"as:Hashtag","ostatus":"http://ostatus.org#","atomUri":"ostatus:atomUri","inReplyToAtomUri":"ostatus:inReplyToAtomUri","conversation":"ostatus:conversation","toot":"http://joinmastodon.org/ns#","Emoji":"toot:Emoji","focalPoint":{"@container":"@list","@id":"toot:focalPoint"},"featured":{"@id":"toot:featured","@type":"@id"},"schema":"http://schema.org#","PropertyValue":"schema:PropertyValue","value":"schema:value"}],"id":"https://mastodon.social/users/dansup/statuses/100784657480587830/activity","type":"Announce","actor":"https://mastodon.social/users/dansup","published":"2018-09-25T05:03:49Z","to":["https://www.w3.org/ns/activitystreams#Public"],"cc":["https://pleroma.site/users/pixeldev","https://mastodon.social/users/dansup/followers"],"object":"https://pleroma.site/objects/68b5c876-f52b-4819-8d81-de6839d73fbc","atomUri":"https://mastodon.social/users/dansup/statuses/100784657480587830/activity"}', true); + + $this->pleroma = json_decode('{"@context":"https://www.w3.org/ns/activitystreams","actor":"https://pleroma.site/users/pixeldev","cc":["https://www.w3.org/ns/activitystreams#Public"],"context":"tag:mastodon.social,2018-10-14:objectId=59146153:objectType=Conversation","context_id":12325955,"id":"https://pleroma.site/activities/db2273eb-d504-4e3a-8f74-c343d069755a","object":"https://mastodon.social/users/dansup/statuses/100891324792793720","published":"2018-10-14T01:22:18.554227Z","to":["https://pleroma.site/users/pixeldev/followers","https://mastodon.social/users/dansup"],"type":"Announce"}', true); + } + + public function testBasicValidation() + { + $this->assertFalse(Helpers::validateObject($this->invalid)); + } + + public function testMastodonValidation() + { + $this->assertTrue(Helpers::validateObject($this->mastodon)); + } + + public function testPleromaValidation() + { + $this->assertTrue(Helpers::validateObject($this->pleroma)); + } + + public function testMastodonAudienceScope() + { + $scope = Helpers::normalizeAudience($this->mastodon, false); + $actual = [ + "to" => [], + "cc" => [ + "https://pleroma.site/users/pixeldev", + "https://mastodon.social/users/dansup/followers", + ], + "scope" => "public", + ]; + + $this->assertEquals($scope, $actual); + } + + public function testPleromaAudienceScope() + { + $scope = Helpers::normalizeAudience($this->pleroma, false); + $actual = [ + "to" => [ + "https://pleroma.site/users/pixeldev/followers", + "https://mastodon.social/users/dansup", + ], + "cc" => [], + "scope" => "unlisted", + ]; + + $this->assertEquals($scope, $actual); + } + + public function testInvalidAudienceScope() + { + $scope = Helpers::normalizeAudience($this->invalid, false); + $actual = [ + 'to' => [], + 'cc' => [], + 'scope' => 'private' + ]; + $this->assertEquals($scope, $actual); + } +} diff --git a/tests/Unit/ActivityPub/RemoteFollowTest.php b/tests/Unit/ActivityPub/RemoteFollowTest.php new file mode 100644 index 00000000..5d97bd55 --- /dev/null +++ b/tests/Unit/ActivityPub/RemoteFollowTest.php @@ -0,0 +1,27 @@ +mastodon = '{"type":"Follow","signature":{"type":"RsaSignature2017","signatureValue":"Kn1/UkAQGJVaXBfWLAHcnwHg8YMAUqlEaBuYLazAG+pz5hqivsyrBmPV186Xzr+B4ZLExA9+SnOoNx/GOz4hBm0kAmukNSILAsUd84tcJ2yT9zc1RKtembK4WiwOw7li0+maeDN0HaB6t+6eTqsCWmtiZpprhXD8V1GGT8yG7X24fQ9oFGn+ng7lasbcCC0988Y1eGqNe7KryxcPuQz57YkDapvtONzk8gyLTkZMV4De93MyRHq6GVjQVIgtiYabQAxrX6Q8C+4P/jQoqdWJHEe+MY5JKyNaT/hMPt2Md1ok9fZQBGHlErk22/zy8bSN19GdG09HmIysBUHRYpBLig==","creator":"http://mastodon.example.org/users/admin#main-key","created":"2018-02-17T13:29:31Z"},"object":"http://localtesting.pleroma.lol/users/lain","nickname":"lain","id":"http://mastodon.example.org/users/admin#follows/2","actor":"http://mastodon.example.org/users/admin","@context":["https://www.w3.org/ns/activitystreams","https://w3id.org/security/v1",{"toot":"http://joinmastodon.org/ns#","sensitive":"as:sensitive","ostatus":"http://ostatus.org#","movedTo":"as:movedTo","manuallyApprovesFollowers":"as:manuallyApprovesFollowers","inReplyToAtomUri":"ostatus:inReplyToAtomUri","conversation":"ostatus:conversation","atomUri":"ostatus:atomUri","Hashtag":"as:Hashtag","Emoji":"toot:Emoji"}]}'; + + } + + /** @test */ + public function validateMastodonFollowObject() + { + $mastodon = json_decode($this->mastodon, true); + $mastodon = Helpers::validateObject($mastodon); + $this->assertTrue($mastodon); + } +} \ No newline at end of file From 962e6190610d629ce7c5406940339b30b4f48d9f Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Mon, 24 Jun 2019 00:01:49 -0600 Subject: [PATCH 13/49] Update AP Helpers --- app/Util/ActivityPub/Helpers.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/Util/ActivityPub/Helpers.php b/app/Util/ActivityPub/Helpers.php index 14e40cc4..a6e18262 100644 --- a/app/Util/ActivityPub/Helpers.php +++ b/app/Util/ActivityPub/Helpers.php @@ -403,7 +403,10 @@ class Helpers { return; } $domain = parse_url($res['id'], PHP_URL_HOST); - $username = Purify::clean($res['preferredUsername']); + $username = (string) Purify::clean($res['preferredUsername']); + if(empty($username)) { + return; + } $remoteUsername = "@{$username}@{$domain}"; abort_if(!self::validateUrl($res['inbox']), 400); @@ -414,7 +417,7 @@ class Helpers { if(!$profile) { $profile = new Profile; $profile->domain = $domain; - $profile->username = Purify::clean($remoteUsername); + $profile->username = (string) Purify::clean($remoteUsername); $profile->name = Purify::clean($res['name']) ?? 'user'; $profile->bio = Purify::clean($res['summary']); $profile->sharedInbox = isset($res['endpoints']) && isset($res['endpoints']['sharedInbox']) ? $res['endpoints']['sharedInbox'] : null; From a5e8b2eec97d8d0f8180a16772ec9e683b477bac Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Mon, 24 Jun 2019 14:26:16 -0600 Subject: [PATCH 14/49] Update Like AP transformer --- app/Transformer/ActivityPub/Verb/Like.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/Transformer/ActivityPub/Verb/Like.php b/app/Transformer/ActivityPub/Verb/Like.php index 5662ab75..b6f69915 100644 --- a/app/Transformer/ActivityPub/Verb/Like.php +++ b/app/Transformer/ActivityPub/Verb/Like.php @@ -11,6 +11,7 @@ class Like extends Fractal\TransformerAbstract { return [ '@context' => 'https://www.w3.org/ns/activitystreams', + 'id' => $like->actor->permalink('#likes/'.$like->id), 'type' => 'Like', 'actor' => $like->actor->permalink(), 'object' => $like->status->url() From 023d279b604544bb71bf95fb4de139aed9a1fbdc Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Mon, 24 Jun 2019 14:36:41 -0600 Subject: [PATCH 15/49] Update Announce AP Transformer --- app/Transformer/ActivityPub/Verb/Announce.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/app/Transformer/ActivityPub/Verb/Announce.php b/app/Transformer/ActivityPub/Verb/Announce.php index b6acb31d..bac66943 100644 --- a/app/Transformer/ActivityPub/Verb/Announce.php +++ b/app/Transformer/ActivityPub/Verb/Announce.php @@ -11,9 +11,16 @@ class Announce extends Fractal\TransformerAbstract { return [ '@context' => 'https://www.w3.org/ns/activitystreams', + 'id' => $status->permalink(), 'type' => 'Announce', 'actor' => $status->profile->permalink(), - 'object' => $status->parent()->url() + 'to' => ['https://www.w3.org/ns/activitystreams#Public'], + 'cc' => [ + $status->parent()->profile->permalink(), + $status->parent()->profile->follower_url + ], + 'published' => $status->created_at->format(DATE_ISO8601), + 'object' => $status->parent()->url(), ]; } } \ No newline at end of file From e5683f94d4c3988ddcc36353c2e0827bfceb65f1 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Mon, 24 Jun 2019 20:22:05 -0600 Subject: [PATCH 16/49] Update LikePipeline --- app/Jobs/LikePipeline/LikePipeline.php | 35 ++++++++++++++++++++------ 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/app/Jobs/LikePipeline/LikePipeline.php b/app/Jobs/LikePipeline/LikePipeline.php index f8aeb5c0..89682791 100644 --- a/app/Jobs/LikePipeline/LikePipeline.php +++ b/app/Jobs/LikePipeline/LikePipeline.php @@ -2,16 +2,17 @@ namespace App\Jobs\LikePipeline; -use App\Like; -use App\Notification; -use Cache; +use Cache, Log, Redis; +use App\{Like, Notification}; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; -use Log; -use Redis; +use App\Util\ActivityPub\Helpers; +use League\Fractal; +use League\Fractal\Serializer\ArraySerializer; +use App\Transformer\ActivityPub\Verb\Like as LikeTransformer; class LikePipeline implements ShouldQueue { @@ -48,11 +49,15 @@ class LikePipeline implements ShouldQueue $status = $this->like->status; $actor = $this->like->actor; - if (!$status || $status->url !== null) { - // Ignore notifications to remote statuses, or deleted statuses + if (!$status) { + // Ignore notifications to deleted statuses return; } + if($status->url && $actor->domain == null) { + return $this->remoteLikeDeliver(); + } + $exists = Notification::whereProfileId($status->profile_id) ->whereActorId($actor->id) ->whereAction('like') @@ -78,4 +83,20 @@ class LikePipeline implements ShouldQueue } catch (Exception $e) { } } + + public function remoteLikeDeliver() + { + $like = $this->like; + $status = $this->like->status; + $actor = $this->like->actor; + + $fractal = new Fractal\Manager(); + $fractal->setSerializer(new ArraySerializer()); + $resource = new Fractal\Resource\Item($like, new LikeTransformer()); + $activity = $fractal->createData($resource)->toArray(); + + $url = $status->profile->sharedInbox ?? $status->profile->inbox_url; + + Helpers::sendSignedObject($actor, $url, $activity); + } } From 4eda870a97ba8dd76b2153f87afb7736b2225048 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Mon, 24 Jun 2019 20:55:38 -0600 Subject: [PATCH 17/49] Update StatusController --- app/Http/Controllers/StatusController.php | 107 +--------------------- 1 file changed, 3 insertions(+), 104 deletions(-) diff --git a/app/Http/Controllers/StatusController.php b/app/Http/Controllers/StatusController.php index 65d6a2da..c6985858 100644 --- a/app/Http/Controllers/StatusController.php +++ b/app/Http/Controllers/StatusController.php @@ -102,109 +102,6 @@ class StatusController extends Controller public function store(Request $request) { return; - - $this->authCheck(); - $user = Auth::user(); - - $size = Media::whereUserId($user->id)->sum('size') / 1000; - $limit = (int) config('pixelfed.max_account_size'); - if ($size >= $limit) { - return redirect()->back()->with('error', 'You have exceeded your storage limit. Please click here for more info.'); - } - - $this->validate($request, [ - 'photo.*' => 'required|mimetypes:' . config('pixelfed.media_types').'|max:' . config('pixelfed.max_photo_size'), - 'caption' => 'nullable|string|max:'.config('pixelfed.max_caption_length'), - 'cw' => 'nullable|string', - 'filter_class' => 'nullable|alpha_dash|max:30', - 'filter_name' => 'nullable|string', - 'visibility' => 'required|string|min:5|max:10', - ]); - - if (count($request->file('photo')) > config('pixelfed.max_album_length')) { - return redirect()->back()->with('error', 'Too many files, max limit per post: '.config('pixelfed.max_album_length')); - } - $cw = $request->filled('cw') && $request->cw == 'on' ? true : false; - $monthHash = hash('sha1', date('Y').date('m')); - $userHash = hash('sha1', $user->id.(string) $user->created_at); - $profile = $user->profile; - $visibility = $this->validateVisibility($request->visibility); - - $cw = $profile->cw == true ? true : $cw; - $visibility = $profile->unlisted == true && $visibility == 'public' ? 'unlisted' : $visibility; - - if(config('costar.enabled') == true) { - $blockedKeywords = config('costar.keyword.block'); - if($blockedKeywords !== null) { - $keywords = config('costar.keyword.block'); - foreach($keywords as $kw) { - if(Str::contains($request->caption, $kw) == true) { - abort(400, 'Invalid object'); - } - } - } - } - - $status = new Status(); - $status->profile_id = $profile->id; - $status->caption = strip_tags($request->caption); - $status->is_nsfw = $cw; - - // TODO: remove deprecated visibility in favor of scope - $status->visibility = $visibility; - $status->scope = $visibility; - - $status->save(); - - $photos = $request->file('photo'); - $order = 1; - $mimes = []; - $medias = 0; - - foreach ($photos as $k => $v) { - - $allowedMimes = explode(',', config('pixelfed.media_types')); - if(in_array($v->getMimeType(), $allowedMimes) == false) { - continue; - } - $filter_class = $request->input('filter_class'); - $filter_name = $request->input('filter_name'); - - $storagePath = "public/m/{$monthHash}/{$userHash}"; - $path = $v->store($storagePath); - $hash = \hash_file('sha256', $v); - $media = new Media(); - $media->status_id = $status->id; - $media->profile_id = $profile->id; - $media->user_id = $user->id; - $media->media_path = $path; - $media->original_sha256 = $hash; - $media->size = $v->getSize(); - $media->mime = $v->getMimeType(); - - $media->filter_class = in_array($filter_class, Filter::classes()) ? $filter_class : null; - $media->filter_name = in_array($filter_name, Filter::names()) ? $filter_name : null; - $media->order = $order; - $media->save(); - array_push($mimes, $media->mime); - ImageOptimize::dispatch($media); - $order++; - $medias++; - } - - if($medias == 0) { - $status->delete(); - return; - } - $status->type = (new self)::mimeTypeCheck($mimes); - $status->save(); - - Cache::forget('profile:status_count:'.$profile->id); - NewStatusPipeline::dispatch($status); - - // TODO: Send to subscribers - - return redirect($status->url()); } public function delete(Request $request) @@ -238,7 +135,9 @@ class StatusController extends Controller $user = Auth::user(); $profile = $user->profile; - $status = Status::withCount('shares')->findOrFail($request->input('item')); + $status = Status::withCount('shares') + ->whereIn('scope', ['public', 'unlisted']) + ->findOrFail($request->input('item')); $count = $status->shares_count; From 912e96692645af62f92ec1d0ede74579bf0b22c7 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Mon, 24 Jun 2019 21:14:22 -0600 Subject: [PATCH 18/49] Update StatusTransformer --- app/Transformer/Api/StatusTransformer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Transformer/Api/StatusTransformer.php b/app/Transformer/Api/StatusTransformer.php index 1c033c1f..8a16e4df 100644 --- a/app/Transformer/Api/StatusTransformer.php +++ b/app/Transformer/Api/StatusTransformer.php @@ -34,7 +34,7 @@ class StatusTransformer extends Fractal\TransformerAbstract 'muted' => null, 'sensitive' => (bool) $status->is_nsfw, 'spoiler_text' => $status->cw_summary, - 'visibility' => $status->visibility, + 'visibility' => $status->visibility ?? $status->scope, 'application' => [ 'name' => 'web', 'website' => null From 66481b77250e9dafd35140445bc71fac6b82aa84 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Mon, 24 Jun 2019 21:14:58 -0600 Subject: [PATCH 19/49] Update Timeline.vue, hide share button for non-public posts --- resources/assets/js/components/Timeline.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/assets/js/components/Timeline.vue b/resources/assets/js/components/Timeline.vue index c4c83463..cf8c5fac 100644 --- a/resources/assets/js/components/Timeline.vue +++ b/resources/assets/js/components/Timeline.vue @@ -117,7 +117,7 @@

-

+


-
-
-
-
-
- -
-
-
-
-

This page isn't available

-

We haven't finished it yet, it will be updated soon!

-
-
-
-
+ @if($page) +
+ {!!$page->content!!} +
+

This document was last updated {{$page->created_at->format('M d, Y')}}.

+

Originally adapted from the Mastodon Code of Conduct.

+ @else +
+

The following guidelines are not a legal document, and final interpretation is up to the administration of {{config('pixelfed.domain.app')}}; they are here to provide you with an insight into our content moderation policies:

+
+
The following types of content will be removed from the public timeline:
+
    +
  • Excessive advertising
  • +
  • Uncurated news bots posting from third-party news sources
  • +
  • Untagged nudity, pornography and sexually explicit content, including artistic depictions
  • +
  • Untagged gore and extremely graphic violence, including artistic depictions
  • +
+
+
+
+
The following types of content will be removed from the public timeline, and may result in account suspension and revocation of access to the service:
+
    +
  • Racism or advocation of racism
  • +
  • Sexism or advocation of sexism
  • +
  • Discrimination against gender and sexual minorities, or advocation thereof
  • +
  • Xenophobic and/or violent nationalism
  • +
+
+
+
+
The following types of content are explicitly disallowed and will result in revocation of access to the service:
+
    +
  • Sexual depictions of children
  • +
  • Content illegal in Canada, Germany and/or France, such as holocaust denial or Nazi symbolism
  • +
  • Conduct promoting the ideology of National Socialism
  • +
+
+
+
+
Any conduct intended to stalk or harass other users, or to impede other users from utilizing the service, or to degrade the performance of the service, or to harass other users, or to incite other users to perform any of the aforementioned actions, is also disallowed, and subject to punishment up to and including revocation of access to the service. This includes, but is not limited to, the following behaviors:
+
    +
  • Continuing to engage in conversation with a user that has specifically has requested for said engagement with that user to cease and desist may be considered harassment, regardless of platform-specific privacy tools employed.
  • +
  • Aggregating, posting, and/or disseminating a person's demographic, personal, or private data without express permission (informally called doxing or dropping dox) may be considered harassment.
  • +
  • Inciting users to engage another user in continued interaction or discussion after a user has requested for said engagement with that user to cease and desist (informally called brigading or dogpiling) may be considered harassment.
  • +
+
+
+

These provisions notwithstanding, the administration of the service reserves the right to revoke any user's access permissions, at any time, for any reason, except as limited by law.

+
+

This document was last updated Jun 26, 2019.

+

Originally adapted from the Mastodon Code of Conduct.

+
+ @endif @endsection From 9327d50c28adf128b7522387a490fab9d9b0a56c Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Thu, 27 Jun 2019 00:58:45 -0600 Subject: [PATCH 45/49] Update terms view --- resources/views/site/terms.blade.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/resources/views/site/terms.blade.php b/resources/views/site/terms.blade.php index 6ede0830..5a2e51fb 100644 --- a/resources/views/site/terms.blade.php +++ b/resources/views/site/terms.blade.php @@ -43,7 +43,9 @@

Pixelfed may revise these terms of service for its website at any time without notice. By using this website you are agreeing to be bound by the then current version of these terms of service.

8. Governing Law

These terms and conditions are governed by and construed in accordance with the laws of Canada and you irrevocably submit to the exclusive jurisdiction of the courts in that State or location.

-
9. Additional Rules
+
9. Community Guidelines
+

You can view our Community Guidelines here.

+
10. Additional Rules

This website does not have any additional rules.

@endif @endsection From 91062b1f55718e2eda222107e18b29a004e2a166 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Thu, 27 Jun 2019 01:01:20 -0600 Subject: [PATCH 46/49] Update Webfinger class --- app/Util/Webfinger/Webfinger.php | 105 +++++++++++-------------------- 1 file changed, 37 insertions(+), 68 deletions(-) diff --git a/app/Util/Webfinger/Webfinger.php b/app/Util/Webfinger/Webfinger.php index e8f10c31..87910333 100644 --- a/app/Util/Webfinger/Webfinger.php +++ b/app/Util/Webfinger/Webfinger.php @@ -4,74 +4,43 @@ namespace App\Util\Webfinger; class Webfinger { - public $user; - public $subject; - public $aliases; - public $links; + protected $user; + protected $subject; + protected $aliases; + protected $links; - public function __construct($user) - { - $this->user = $user; - $this->subject = ''; - $this->aliases = []; - $this->links = []; - } + public function __construct($user) + { + $this->subject = 'acct:'.$user->username.'@'.parse_url(config('app.url'), PHP_URL_HOST); + $this->aliases = [ + $user->url(), + $user->permalink(), + ]; + $this->links = [ + [ + 'rel' => 'http://webfinger.net/rel/profile-page', + 'type' => 'text/html', + 'href' => $user->url(), + ], + [ + 'rel' => 'http://schemas.google.com/g/2010#updates-from', + 'type' => 'application/atom+xml', + 'href' => $user->permalink('.atom'), + ], + [ + 'rel' => 'self', + 'type' => 'application/activity+json', + 'href' => $user->permalink(), + ], + ]; + } - public function setSubject() - { - $host = parse_url(config('app.url'), PHP_URL_HOST); - $username = $this->user->username; - - $this->subject = 'acct:'.$username.'@'.$host; - - return $this; - } - - public function generateAliases() - { - $this->aliases = [ - $this->user->url(), - $this->user->permalink(), - ]; - - return $this; - } - - public function generateLinks() - { - $user = $this->user; - - $this->links = [ - [ - 'rel' => 'http://webfinger.net/rel/profile-page', - 'type' => 'text/html', - 'href' => $user->url(), - ], - [ - 'rel' => 'http://schemas.google.com/g/2010#updates-from', - 'type' => 'application/atom+xml', - 'href' => $user->permalink('.atom'), - ], - [ - 'rel' => 'self', - 'type' => 'application/activity+json', - 'href' => $user->permalink(), - ], - ]; - - return $this; - } - - public function generate() - { - $this->setSubject(); - $this->generateAliases(); - $this->generateLinks(); - - return [ - 'subject' => $this->subject, - 'aliases' => $this->aliases, - 'links' => $this->links, - ]; - } + public function generate() + { + return [ + 'subject' => $this->subject, + 'aliases' => $this->aliases, + 'links' => $this->links, + ]; + } } From 103c0e7420d7c0f2782befa2977ba0cdbd2dded1 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Thu, 27 Jun 2019 01:05:39 -0600 Subject: [PATCH 47/49] Update Help Center view --- resources/views/site/help.blade.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/resources/views/site/help.blade.php b/resources/views/site/help.blade.php index 9fd432e5..13b5edff 100644 --- a/resources/views/site/help.blade.php +++ b/resources/views/site/help.blade.php @@ -149,7 +149,7 @@
- {{-- {{--
From 45d248c93438b2dbb0075ce91007e02aa6431f93 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Thu, 27 Jun 2019 01:08:04 -0600 Subject: [PATCH 48/49] Update Help Center sidebar --- resources/views/site/help/partial/sidebar.blade.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/views/site/help/partial/sidebar.blade.php b/resources/views/site/help/partial/sidebar.blade.php index 05f6ec99..2278eb7a 100644 --- a/resources/views/site/help/partial/sidebar.blade.php +++ b/resources/views/site/help/partial/sidebar.blade.php @@ -30,11 +30,11 @@ - {{-- --}} + {{-- --}} From ab0e5a36dec681c140db9907776e12f4779ae2f8 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Thu, 27 Jun 2019 01:31:30 -0600 Subject: [PATCH 49/49] Update SiteController, increase cache ttl --- app/Http/Controllers/SiteController.php | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/app/Http/Controllers/SiteController.php b/app/Http/Controllers/SiteController.php index c14dc1dd..58b092b8 100644 --- a/app/Http/Controllers/SiteController.php +++ b/app/Http/Controllers/SiteController.php @@ -42,7 +42,7 @@ class SiteController extends Controller public function about() { - return Cache::remember('site:about', now()->addMinutes(120), function() { + return Cache::remember('site:about', now()->addHours(12), function() { $page = Page::whereSlug('/site/about')->whereActive(true)->first(); $stats = [ 'posts' => Status::whereLocal(true)->count(), @@ -64,24 +64,25 @@ class SiteController extends Controller public function communityGuidelines(Request $request) { - $slug = '/site/kb/community-guidelines'; - $page = Page::whereSlug($slug)->whereActive(true)->first(); - return view('site.help.community-guidelines', compact('page')); + return Cache::remember('site:help:community-guidelines', now()->addDays(120), function() { + $slug = '/site/kb/community-guidelines'; + $page = Page::whereSlug($slug)->whereActive(true)->first(); + return View::make('site.help.community-guidelines')->with(compact('page'))->render(); + }); } public function privacy(Request $request) { - return Cache::remember('site:privacy', now()->addMinutes(120), function() { + return Cache::remember('site:privacy', now()->addDays(120), function() { $slug = '/site/privacy'; $page = Page::whereSlug($slug)->whereActive(true)->first(); return View::make('site.privacy')->with(compact('page'))->render(); }); } - public function terms(Request $request) { - return Cache::remember('site:terms', now()->addMinutes(120), function() { + return Cache::remember('site:terms', now()->addDays(120), function() { $slug = '/site/terms'; $page = Page::whereSlug($slug)->whereActive(true)->first(); return View::make('site.terms')->with(compact('page'))->render();