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 2a8604cc7..d87451b75 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 d87451b75..f5ed15a93 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 75e4b1c6e..c93aa6c4f 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 ee4da9733..4efa82265 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 34fb7d8fb..ff2b1812d 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 f2c1169db..14e40cc40 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 d3283c921..8e987ab68 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 ff2b1812d..d7e6679f0 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 13d5dc030..8ddc88751 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 17ad47889..57ed1d2e4 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 6d581eb73..186188ea0 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 000000000..30b2bf1e3 --- /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 000000000..5d97bd55e --- /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 14e40cc40..a6e182624 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 5662ab758..b6f699158 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 b6acb31d1..bac669435 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 f8aeb5c0a..896827917 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 65d6a2da5..c6985858a 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 1c033c1f1..8a16e4dfd 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 c4c834638..cf8c5fac1 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 6ede08305..5a2e51fb2 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 e8f10c31c..879103332 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 9fd432e5f..13b5edfff 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 05f6ec99f..2278eb7a3 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 c14dc1ddb..58b092b83 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();