From a44b812b131a35888b0b6937932b6c43fc71ced4 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Thu, 3 Mar 2022 20:51:13 -0700 Subject: [PATCH 01/11] Update SpaController, redirect web ui hashtags to legacy page for unauthenticated users --- app/Http/Controllers/SpaController.php | 9 +++++++++ routes/web.php | 1 + 2 files changed, 10 insertions(+) diff --git a/app/Http/Controllers/SpaController.php b/app/Http/Controllers/SpaController.php index 664286f78..a64a880b5 100644 --- a/app/Http/Controllers/SpaController.php +++ b/app/Http/Controllers/SpaController.php @@ -126,4 +126,13 @@ class SpaController extends Controller } return redirect('/i/web/profile/' . $id); } + + public function hashtagRedirect(Request $request, $tag) + { + if(!$request->user()) { + return redirect('/discover/tags/' . $tag); + } + + return view('layouts.spa'); + } } diff --git a/routes/web.php b/routes/web.php index 0cb0c9507..cd46c012f 100644 --- a/routes/web.php +++ b/routes/web.php @@ -351,6 +351,7 @@ Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofact Route::post('warning', 'AccountInterstitialController@read'); Route::get('my2020', 'SeasonalController@yearInReview'); + Route::get('web/hashtag/{tag}', 'SpaController@hashtagRedirect'); Route::get('web/username/{id}', 'SpaController@usernameRedirect'); Route::get('web/post/{id}', 'SpaController@webPost'); Route::get('web/profile/{id}', 'SpaController@webProfile'); From 3e670774c039277993eb2f48c04035f796ca22fb Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Thu, 3 Mar 2022 21:47:08 -0700 Subject: [PATCH 02/11] Update ApiV1Controller, fixes #3288 --- app/Http/Controllers/Api/ApiV1Controller.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Controllers/Api/ApiV1Controller.php b/app/Http/Controllers/Api/ApiV1Controller.php index 7e11a6591..f01bb1a7c 100644 --- a/app/Http/Controllers/Api/ApiV1Controller.php +++ b/app/Http/Controllers/Api/ApiV1Controller.php @@ -2547,7 +2547,7 @@ class ApiV1Controller extends Controller $sortBy = $request->input('sort', 'all'); - if($sortBy == 'all' && $status['replies_count'] && $request->has('refresh_cache')) { + if($sortBy == 'all' && isset($status['replies_count']) && $status['replies_count'] && $request->has('refresh_cache')) { if(!Cache::has('status:replies:all-rc:' . $id)) { Cache::forget('status:replies:all:' . $id); Cache::put('status:replies:all-rc:' . $id, true, 300); From b78bff72db6fdf30e7634a39f5f9f2391a37c8f6 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Thu, 3 Mar 2022 21:55:15 -0700 Subject: [PATCH 03/11] Update AP Helpers, fixes #3287 --- app/Util/ActivityPub/Helpers.php | 64 +++++++++++++++++++++++++++----- 1 file changed, 54 insertions(+), 10 deletions(-) diff --git a/app/Util/ActivityPub/Helpers.php b/app/Util/ActivityPub/Helpers.php index a18a57ff0..0f230f24f 100644 --- a/app/Util/ActivityPub/Helpers.php +++ b/app/Util/ActivityPub/Helpers.php @@ -71,11 +71,25 @@ class Helpers { $mimeTypes = explode(',', config_cache('pixelfed.media_types')); $mediaTypes = in_array('video/mp4', $mimeTypes) ? ['Document', 'Image', 'Video'] : ['Document', 'Image']; + // Peertube + // $mediaTypes = in_array('video/mp4', $mimeTypes) ? ['Document', 'Image', 'Video', 'Link'] : ['Document', 'Image']; + if(!isset($activity['attachment']) || empty($activity['attachment'])) { return false; } + // peertube + // $attachment = is_array($activity['url']) ? + // collect($activity['url']) + // ->filter(function($media) { + // return $media['type'] == 'Link' && $media['mediaType'] == 'video/mp4'; + // }) + // ->take(1) + // ->values() + // ->toArray()[0] : $activity['attachment']; + $attachment = $activity['attachment']; + $valid = Validator::make($attachment, [ '*.type' => [ 'required', @@ -88,7 +102,7 @@ class Helpers { 'string', Rule::in($mimeTypes) ], - '*.name' => 'nullable|string|max:255' + '*.name' => 'sometimes|nullable|string|max:255' ])->passes(); return $valid; @@ -247,6 +261,19 @@ class Helpers { return self::fetchFromUrl($url); } + public static function pluckval($val) + { + if(is_string($val)) { + return $val; + } + + if(is_array($val)) { + return !empty($val) ? $val[0] : null; + } + + return null; + } + public static function statusFirstOrFetch($url, $replyTo = false) { $url = self::validateUrl($url); @@ -330,7 +357,7 @@ class Helpers { } } - $id = isset($res['id']) ? $res['id'] : $url; + $id = isset($res['id']) ? self::pluckval($res['id']) : self::pluckval($url); $idDomain = parse_url($id, PHP_URL_HOST); $urlDomain = parse_url($url, PHP_URL_HOST); @@ -338,9 +365,20 @@ class Helpers { return; } - if(isset($activity['object']['attributedTo'])) { - $actorDomain = parse_url($activity['object']['attributedTo'], PHP_URL_HOST); - if(!self::validateUrl($activity['object']['attributedTo']) || + $attributedTo = is_string($activity['object']['attributedTo']) ? + $activity['object']['attributedTo'] : + (is_array($activity['object']['attributedTo']) ? + collect($activity['object']['attributedTo']) + ->filter(function($o) { + return $o && isset($o['type']) && $o['type'] == 'Person'; + }) + ->pluck('id') + ->first() : null + ); + + if($attributedTo) { + $actorDomain = parse_url($attributedTo, PHP_URL_HOST); + if(!self::validateUrl($attributedTo) || $idDomain !== $actorDomain || $actorDomain !== $urlDomain ) @@ -353,14 +391,14 @@ class Helpers { return; } - $profile = self::profileFirstOrNew($activity['object']['attributedTo']); + $profile = self::profileFirstOrNew($attributedTo); if(isset($activity['object']['inReplyTo']) && !empty($activity['object']['inReplyTo']) || $replyTo == true) { - $reply_to = self::statusFirstOrFetch($activity['object']['inReplyTo'], false); + $reply_to = self::statusFirstOrFetch(self::pluckval($activity['object']['inReplyTo']), false); $reply_to = optional($reply_to)->id; } else { $reply_to = null; } - $ts = is_array($res['published']) ? $res['published'][0] : $res['published']; + $ts = self::pluckval($res['published']); if($scope == 'public' && in_array($urlDomain, InstanceService::getUnlistedDomains())) { $scope = 'unlisted'; @@ -399,8 +437,8 @@ class Helpers { return DB::transaction(function() use($profile, $res, $url, $ts, $reply_to, $cw, $scope, $id) { $status = new Status; $status->profile_id = $profile->id; - $status->url = isset($res['url']) ? $res['url'] : $url; - $status->uri = isset($res['url']) ? $res['url'] : $url; + $status->url = isset($res['url']) && is_string($res['url']) ? $res['url'] : $url; + $status->uri = isset($res['url']) && is_string($res['url']) ? $res['url'] : $url; $status->object_url = $id; $status->caption = strip_tags($res['content']); $status->rendered = Purify::clean($res['content']); @@ -486,10 +524,16 @@ class Helpers { public static function importNoteAttachment($data, Status $status) { if(self::verifyAttachments($data) == false) { + // \Log::info('importNoteAttachment::failedVerification.', [$data['id']]); $status->viewType(); return; } $attachments = isset($data['object']) ? $data['object']['attachment'] : $data['attachment']; + // peertube + // if(!$attachments) { + // $obj = isset($data['object']) ? $data['object'] : $data; + // $attachments = is_array($obj['url']) ? $obj['url'] : null; + // } $user = $status->profile; $storagePath = MediaPathService::get($user, 2); $allowed = explode(',', config_cache('pixelfed.media_types')); From 539752067fde2c49a19c9ed926804b3704fdcac3 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Thu, 3 Mar 2022 21:57:13 -0700 Subject: [PATCH 04/11] Update AP Helpers, fixes #3290 --- app/Util/ActivityPub/Helpers.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Util/ActivityPub/Helpers.php b/app/Util/ActivityPub/Helpers.php index 0f230f24f..b9a4f26e1 100644 --- a/app/Util/ActivityPub/Helpers.php +++ b/app/Util/ActivityPub/Helpers.php @@ -629,7 +629,7 @@ class Helpers { $profile->bio = isset($res['summary']) ? Purify::clean($res['summary']) : null; $profile->sharedInbox = isset($res['endpoints']) && isset($res['endpoints']['sharedInbox']) ? $res['endpoints']['sharedInbox'] : null; $profile->inbox_url = $res['inbox']; - $profile->outbox_url = $res['outbox']; + $profile->outbox_url = isset($res['outbox']) ? $res['outbox'] : null; $profile->remote_url = $res['id']; $profile->public_key = $res['publicKey']['publicKeyPem']; $profile->key_id = $res['publicKey']['id']; From fe7687851c36c364cd4c99ba0a608f2e1798d830 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Sun, 6 Mar 2022 03:45:19 -0700 Subject: [PATCH 05/11] Update AccountController, refresh relationship after handling follow request --- app/Http/Controllers/AccountController.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php index 073bbfa81..fc3ff69d3 100644 --- a/app/Http/Controllers/AccountController.php +++ b/app/Http/Controllers/AccountController.php @@ -406,6 +406,7 @@ class AccountController extends Controller Cache::forget('profile:follower_count:'.$pid); Cache::forget('profile:following_count:'.$pid); + RelationshipService::refresh($pid, $follower->id); return response()->json(['msg' => 'success'], 200); } From aba0c97cee01db0775cc4e00f252be5c20c4612e Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Tue, 8 Mar 2022 20:56:08 -0700 Subject: [PATCH 06/11] Add CollectionService --- app/Services/CollectionService.php | 141 +++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 app/Services/CollectionService.php diff --git a/app/Services/CollectionService.php b/app/Services/CollectionService.php new file mode 100644 index 000000000..33a3303ff --- /dev/null +++ b/app/Services/CollectionService.php @@ -0,0 +1,141 @@ +orderBy('order') + ->get() + ->each(function($item) use ($id) { + self::addItem($id, $item->object_id, $item->order); + }) + ->map(function($item) { + return (string) $item->object_id; + }) + ->values() + ->toArray(); + }); + } + + public static function count($id) + { + $count = Redis::zcard(self::CACHE_KEY . 'items:' . $id); + if(!$count) { + self::coldBootItems($id); + $count = Redis::zcard(self::CACHE_KEY . 'items:' . $id); + } + return $count; + } + + public static function getCollection($id) + { + $collection = Cache::remember(self::CACHE_KEY . 'get:' . $id, 86400, function() use($id) { + $collection = Collection::find($id); + if(!$collection) { + return false; + } + $account = AccountService::get($collection->profile_id); + if(!$account) { + return false; + } + return [ + 'id' => (string) $collection->id, + 'pid' => (string) $collection->profile_id, + 'username' => $account['username'], + 'visibility' => $collection->visibility, + 'title' => $collection->title, + 'description' => $collection->description, + 'thumb' => self::getThumb($id), + 'url' => $collection->url(), + 'published_at' => $collection->published_at + ]; + }); + + if($collection) { + $collection['post_count'] = self::count($id); + } + + return $collection; + } + + public static function setCollection($id, $collection) + { + $account = AccountService::get($collection->profile_id); + if(!$account) { + return false; + } + $res = [ + 'id' => (string) $collection->id, + 'pid' => (string) $collection->profile_id, + 'username' => $account['username'], + 'visibility' => $collection->visibility, + 'title' => $collection->title, + 'description' => $collection->description, + 'thumb' => self::getThumb($id), + 'url' => $collection->url(), + 'published_at' => $collection->published_at + ]; + Cache::put(self::CACHE_KEY . 'get:' . $id, $res, 86400); + $res['post_count'] = self::count($id); + return $res; + } + + public static function deleteCollection($id) + { + Redis::del(self::CACHE_KEY . 'items:' . $id); + Cache::forget(self::CACHE_KEY . 'get:' . $id); + } + + public static function getThumb($id) + { + $item = self::getItems($id, 0, 1); + if(!$item || empty($item)) { + return '/storage/no-preview.png'; + } + $status = StatusService::get($item[0]); + if(!$status) { + return '/storage/no-preview.png'; + } + + if(!isset($status['media_attachments']) || empty($status['media_attachments'])) { + return '/storage/no-preview.png'; + } + + return $status['media_attachments'][0]['url']; + } +} From c7e1e473caac118ab20aaca5419fe98191632209 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Tue, 8 Mar 2022 20:57:18 -0700 Subject: [PATCH 07/11] Update CollectionController, fixes #3289 --- app/Http/Controllers/CollectionController.php | 139 +++++++++++------- 1 file changed, 85 insertions(+), 54 deletions(-) diff --git a/app/Http/Controllers/CollectionController.php b/app/Http/Controllers/CollectionController.php index 992aa97e6..6ddba8239 100644 --- a/app/Http/Controllers/CollectionController.php +++ b/app/Http/Controllers/CollectionController.php @@ -17,6 +17,8 @@ use App\Transformer\Api\{ }; use League\Fractal\Serializer\ArraySerializer; use League\Fractal\Pagination\IlluminatePaginatorAdapter; +use App\Services\CollectionService; +use App\Services\FollowerService; use App\Services\StatusService; class CollectionController extends Controller @@ -30,18 +32,25 @@ class CollectionController extends Controller 'profile_id' => $profile->id, 'published_at' => null ]); + $collection->visibility = 'draft'; + $collection->save(); return view('collection.create', compact('collection')); } public function show(Request $request, int $id) { $user = $request->user(); - $collection = Collection::findOrFail($id); - if($collection->published_at == null || $collection->visibility != 'public') { - if(!$user || $user->profile_id != $collection->profile_id) { - abort_unless($user && $user->is_admin, 404); - } - } + $collection = CollectionService::getCollection($id); + abort_if(!$collection, 404); + if($collection['published_at'] == null || $collection['visibility'] != 'public') { + abort_if(!$user, 404); + if($user->profile_id != $collection['pid']) { + if(!$user->is_admin) { + abort_if($collection['visibility'] != 'private', 404); + abort_if(!FollowerService::follows($user->profile_id, $collection['pid']), 404); + } + } + } return view('collection.show', compact('collection')); } @@ -57,7 +66,7 @@ class CollectionController extends Controller $this->validate($request, [ 'title' => 'nullable', 'description' => 'nullable', - 'visibility' => 'nullable|string|in:public,private' + 'visibility' => 'nullable|string|in:public,private,draft' ]); $profile = Auth::user()->profile; @@ -67,7 +76,7 @@ class CollectionController extends Controller $collection->visibility = e($request->input('visibility')); $collection->save(); - return 200; + return CollectionService::setCollection($collection->id, $collection); } public function publish(Request $request, int $id) @@ -76,7 +85,7 @@ class CollectionController extends Controller $this->validate($request, [ 'title' => 'nullable', 'description' => 'nullable', - 'visibility' => 'required|alpha|in:public,private' + 'visibility' => 'required|alpha|in:public,private,draft' ]); $profile = Auth::user()->profile; $collection = Collection::whereProfileId($profile->id)->findOrFail($id); @@ -88,8 +97,7 @@ class CollectionController extends Controller $collection->visibility = e($request->input('visibility')); $collection->published_at = now(); $collection->save(); - - return $collection->url(); + return CollectionService::setCollection($collection->id, $collection); } public function delete(Request $request, int $id) @@ -105,6 +113,8 @@ class CollectionController extends Controller return 200; } + CollectionService::deleteCollection($id); + return redirect('/'); } @@ -139,82 +149,98 @@ class CollectionController extends Controller 'order' => $count, ]); - return 200; + CollectionService::addItem( + $collection->id, + $status->id, + $count + ); + + return StatusService::get($status->id); } - public function get(Request $request, $id) + public function getCollection(Request $request, $id) { - $user = $request->user(); - $collection = Collection::findOrFail($id); - if($collection->published_at == null || $collection->visibility != 'public') { - if(!$user || $user->profile_id != $collection->profile_id) { - abort_unless($user && $user->is_admin, 404); - } - } + $user = $request->user(); + $collection = CollectionService::getCollection($id); + if($collection['published_at'] == null || $collection['visibility'] != 'public') { + abort_unless($user, 404); + if($user->profile_id != $collection['pid']) { + if(!$user->is_admin) { + abort_if($collection['visibility'] != 'private', 404); + abort_if(!FollowerService::follows($user->profile_id, $collection['pid']), 404); + } + } + } - return [ - 'id' => (string) $collection->id, - 'visibility' => $collection->visibility, - 'title' => $collection->title, - 'description' => $collection->description, - 'thumb' => $collection->posts()->first()->thumb(), - 'url' => $collection->url(), - 'post_count' => $collection->posts()->count(), - 'published_at' => $collection->published_at - ]; + return $collection; } public function getItems(Request $request, int $id) { - $collection = Collection::findOrFail($id); - if($collection->visibility !== 'public') { - abort_if(!Auth::check() || Auth::user()->profile_id != $collection->profile_id, 404); - } + $user = $request->user(); + $collection = CollectionService::getCollection($id); + if($collection['published_at'] == null || $collection['visibility'] != 'public') { + abort_unless($user, 404); + if($user->profile_id != $collection['pid']) { + if(!$user->is_admin) { + abort_if($collection['visibility'] != 'private', 404); + abort_if(!FollowerService::follows($user->profile_id, $collection['pid']), 404); + } + } + } + $page = $request->input('page') ?? 1; + $start = $page == 1 ? 0 : ($page * 10 - 10); + $end = $start + 10; + $items = CollectionService::getItems($id, $start, $end); - $res = CollectionItem::whereCollectionId($id) - ->pluck('object_id') + return collect($items) ->map(function($id) { return StatusService::get($id); }) - ->filter(function($post) { - return $post && isset($post['account']); + ->filter(function($item) { + return $item && isset($item['account'], $item['media_attachments']); }) ->values(); - - return response()->json($res); } public function getUserCollections(Request $request, int $id) { $user = $request->user(); $pid = $user ? $user->profile_id : null; + $follows = false; + $visibility = ['public']; $profile = Profile::whereNull('status') ->whereNull('domain') ->findOrFail($id); - if($profile->is_private) { - abort_if(!$pid, 404); - abort_if(!$profile->id != $pid, 404); + if($pid) { + $follows = FollowerService::follows($pid, $profile->id); } - $visibility = $pid == $profile->id ? ['public', 'private'] : ['public']; + if($profile->is_private) { + abort_if(!$pid, 404); + if(!$user->is_admin) { + abort_if($profile->id != $pid && $follows == false, 404); + } + } + + $owner = $pid ? $pid == $profile->id : false; + + if($follows) { + $visibility = ['public', 'private']; + } + + if($pid && $pid == $profile->id) { + $visibility = ['public', 'private', 'draft']; + } return Collection::whereProfileId($profile->id) ->whereIn('visibility', $visibility) ->orderByDesc('id') ->paginate(9) ->map(function($collection) { - return [ - 'id' => (string) $collection->id, - 'visibility' => $collection->visibility, - 'title' => $collection->title, - 'description' => $collection->description, - 'thumb' => $collection->posts()->first()->thumb(), - 'url' => $collection->url(), - 'post_count' => $collection->posts()->count(), - 'published_at' => $collection->published_at - ]; + return CollectionService::getCollection($collection->id); }); } @@ -240,6 +266,11 @@ class CollectionController extends Controller ->whereIn('type', ['photo', 'photo:album', 'video']) ->findOrFail($postId); + CollectionService::removeItem( + $collection->id, + $status->id + ); + $item = CollectionItem::whereCollectionId($collection->id) ->whereObjectType('App\Status') ->whereObjectId($status->id) From 6f8524515ea804194a21be714787d22338af4591 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Tue, 8 Mar 2022 20:58:45 -0700 Subject: [PATCH 08/11] Update compiled assets --- public/js/collectioncompose.js | Bin 10008 -> 10086 bytes public/js/collections.js | Bin 15283 -> 19860 bytes public/js/profile-chunk-uopy3z.js | Bin 170889 -> 173784 bytes public/mix-manifest.json | Bin 3315 -> 3315 bytes 4 files changed, 0 insertions(+), 0 deletions(-) diff --git a/public/js/collectioncompose.js b/public/js/collectioncompose.js index 0cb69fed1b872551d87be7df906cc3c7571d411c..60a393b6c68e5558d3018de493507a7885bdd543 100644 GIT binary patch delta 157 zcmbQ?_snmDAmd~;Mg!KAqQtb4%`uFVI9T*bi*h!<Bro~>2~#GbsDSAFwGzJKi8IwgAXWg1EfN}4*83&o^F t!DcJf*6KtegJE?F8=@k delta 130 zcmaFnH^Xm(Afs?uW^raxW=>{FrIk`aQD#|UN$O;NMkBU@(xjZsFRsRDKiN@Iaq?PKx6Sv(+xY=0Nh%=# diff --git a/public/js/collections.js b/public/js/collections.js index 1a1759102107e060722589a5decb821848b69e60..39304b0dde84f928bcc7ef5d3c64379722d18928 100644 GIT binary patch literal 19860 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 delta 2863 zcmb7GU5Fdk6-KsWZ+6#NY5yE6YkM@_XzyK(W;Lsow30l#{@FEM2fKEfgcNyW6zOU; z_Gqp;bG2(%p17fyl0bi)6B0_G+b9V+&sCc+s&M$tM0m{5IhmhL zrsrtB(y&Ux;Fe@vd-2Nvhvx#hQ67y7wZtv_woww?jz$TGj{?#lzkFH#0TZ&W>m0Uk zn?m{6wppZ4ZTt84xSmi9-C`Tk5!)_aLTh<`h~;@KMvVer)diBg%|yetB*T58!BoUY z47JQE#fB+p-nS^3@Qdxwz}$`}`$`SlW|nvye!k-dT)i(D;SEc$a;^)R(59=@n5goy zlWSI(C_yB&2lQP7@XXGqpnun29`34en5{FlTogq`sC>i1BYN1?|K+Y5@Odx)a7eM;6|{KL_dlNm%WFtgmjfb%Sl3YrWAw7}%yITkj6M9YEJNc3(JU=%Q*kYQ4$@ zUnwh&zF}BpzM-1DRP=(Ya@$xlEXC9f)v23?Ao7e%^LQ|g5+e!4QB7v8i7Jigx&w&^ z&PKoa7E4l$yAzXV>N9dQn#O|(Z$9u+z=V~d$R4g5WrwQuhEr9G^}2}(P%L7?vqKjU z<>KI2v}%+Yp~{`uY-aLenNZhNSlJK|8W@KYBV(;x@LvJ=PjEjh4^QC51Y8-u26T9D zi;ny*FvMxIc+ubvrq5)8L15?r+#ZcDbJwM+s4|O?%{&>j$yA%w_&Qq=tVTG+EKJ(0 z;;5d*(_Yw|le}Cs)iy>ryeHNA<5^`b3#9pW`eiYk`QRf`yu&>oirZFWjo z6g0BxQku8?*pq_5L@2UaHfm16tGM`jyi%#mC(_9xEQjsB&BMFl`K`n4u)cLzdT8#7 ztjO|ew<#Rma+P`1k^Sy2**z|0lgUhW%O$K-PW(twtj(rjVV{VcTxG>F{9_^*w$NuU z!+wJ*W*3c(H5%L}{hui_+MY7AnS^hUB$HY;1z+qR4_NTy1K}%HL7;!!&w+ysNv1OC zWY>nNV_R^N(z1!fR$hsuu}wfS?N*#c-(T7h^AN#(^TYcsAd05Rd%t? zZQ-~IVmX^lefL=QmPdBJ6U(NXuW*~R$Cr={9B=T;ec|&)kAqg%F9%0JC!h$!^Z4E< zHmlLkz8A^6n0xZ;=CE95G4$V3c{ZzQ+C7w4?o{r7aBt;GJGIy+UYh*wGL$<~<=W&*vOwR@8H)%a>VqZE(0bJqD+x131yH&n&}Rl7!rc(hAa>(|hl) ziFi_Wl|ozY)XYw}5!sDze~X;-zZf6Jrj%W8{G3}SvLt&8(Nk&2hf(17auw;w!AFr+ z4o<>nQ^V78%tJzi>Mw@wn2yPkKkOap4{u9PUur7~Mc4QAXx4Oe!rwKE9A1r14R9hm z^`a$v_(J4o@WZJ^H1zAKeMtX)a2)8y2D^!|LHA@b>6U(%4KS5ePj z>2x3sx9Li7m9Bo%&vr<5JmLq5$hD%wE&GzJG>bymxI|0bMA{vQvq~nB$jvHqNHtek zYY2gf+}W?H2BHG zV;F-!C7NEWu_tRjjx*XpynXf1X?RZ?4e-_{TEtu2?Q1Dn$E$0}hFm{h)5viDI~J5 zp}-k!d7s z>Un&>uJ8AxVqR|qlu3v!NbvkJ1#_X_|9T8g&3N3)3)26L&SQ{U4CDJJ+5*7h=g7H- zYe={7KLO7l$>B}AR{M~<85@UNN3xx}6GtbJ<42DnZ5@39X*r3a6KD6xdTln>z?NGu^Z5%#Z_WH98s1Lr%gj!dRZx3v@^uo6o9CtvC J!1qrs{}-0|vVZ^p diff --git a/public/js/profile-chunk-uopy3z.js b/public/js/profile-chunk-uopy3z.js index a6d9b2c99bb58c99971b5155420e6d3517bb4a8c..bce0b77fad3fa99472756d7da0732af9d2671d64 100644 GIT binary patch delta 1989 zcmb7FU2GIp6wbZ-L$?Lm!a}z#w6jy)A3M9~F5_~MC#&$H;Fq|Z z$YwmJHm)h(uzHbw315!^Wa@PWh?jc98Y%Cp`Tn)tOqvyjNbEDB#HGYsj!Wx+a)RVb zKUi*M4{(Vf!^;a?o)Q#Jl68OKfZ@&x&+}Yyfrol$d9%9Zt=~HtWtf-!yu76-aFWaA zF_t9pL;j>TuexzO$oz{#1uDxa>ES_+%Xqx%o8v=W|0lqk@Tk|vn^ske(!1v}dhYTc z(x)ER&*^c>mU7zWJuK|Z~5nA=LbYxgJ~`| zNIDja&vFMxIax_$M+HNQ9`E5IFJ#0b*%cwnOL-67FLBf%ag>rr=UW=Am}s;+1lL=UOMPSRN%h{{TD5Mjr6wDX$1_2eE&Jwv*l9#Li^;#>pTrhQzGj+-r!o>)&52JL9GITDWsV746%+2|^QcFT^A*c!sYo^agD z@V&Ap8jFX+u+5GJw2N(MpQ#}n>kfBUZ1G?;(4*T@noJ|D#zYXI5JIg+4ba$u`m|%6 z=nFib^Be6++314AkFg3z!x;~L1nLLz0L*R0g*q}T$cFi{<)L)z;)k6)r;+UV(Gl z@!Iw+Lhca77D&h#`C8e0GM;ovP%_8C>}}Kv)1Q#O_wB{&;kyEE?sdx)?PX*Sy2?yc5e%xnIa(;zZa$JJmAs8!{7R2B<9Slk;?`nv|-Pp|`G6qNh&K8Hvp*uqlN-aFIt&2)v3c z&H5$sx9E+;6Z(EcO;8GAn|2|E9T<{NqZM#(C$6hoaJ+%tiJD<%173mY5;VSm=|$Ef z2_l!X!vyG>6EB0APP_)rQrKZ3R4_s9vnTLnw~44yy|S*gBE^7!)#mz#E;%qA#hq~T zC=MZ~nq20(FYqiAf2;o{MU zK~-ugWBAPTM$L~O!W-O~z-=(bVfyqG?$E?Z>_G6&6|&#e`AYgUh(vJ?NC=`x>SywGb)AYlwlNubh(xe z{-=c!mQcx`9luaCt_}xg=1Q0I6(i6Xx%tx$)yA#*<0N0LR>O*{;ERXgrSF2}1~uiOtPkrpOB5 zn<)~(wG(6%LYU1#02j8+iS#%*0DSpUpW|w#C7|Sz%LpPZ9Rv33EU!`xgS`n3Ghh)!3QAFF*>uPr I*YEKxe{c~ZBme*a delta 120 zcmV~$u?+$-3 Date: Tue, 8 Mar 2022 20:58:51 -0700 Subject: [PATCH 09/11] Update changelog --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 94395c279..d373fb025 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -67,6 +67,12 @@ - Updated admin diagnostics, add more configuration data to help diagnose potential issues. ([eab96fc3](https://github.com/pixelfed/pixelfed/commit/eab96fc3)) - Updated ConfigCacheService, fix discover features. ([ad48521a](https://github.com/pixelfed/pixelfed/commit/ad48521a)) - Updated MediaTransformer, fix type case bug. Fixes #3281. ([c1669253](https://github.com/pixelfed/pixelfed/commit/c1669253)) +- Updated SpaController, redirect web ui hashtags to legacy page for unauthenticated users. ([a44b812b](https://github.com/pixelfed/pixelfed/commit/a44b812b)) +- Updated ApiV1Controller, fixes #3288. ([3e670774](https://github.com/pixelfed/pixelfed/commit/3e670774)) +- Updated AP Helpers, fixes #3287. ([b78bff72](https://github.com/pixelfed/pixelfed/commit/b78bff72)) +- Updated AP Helpers, fixes #3290. ([53975206](https://github.com/pixelfed/pixelfed/commit/53975206)) +- Updated AccountController, refresh relationship after handling follow request. ([fe768785](https://github.com/pixelfed/pixelfed/commit/fe768785)) +- Updated CollectionController, fixes #3289. ([c7e1e473](https://github.com/pixelfed/pixelfed/commit/c7e1e473)) - ([](https://github.com/pixelfed/pixelfed/commit/)) ## [v0.11.2 (2022-01-09)](https://github.com/pixelfed/pixelfed/compare/v0.11.1...v0.11.2) From fa01c8924aa619ca4072215b143a5998718187c0 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Tue, 8 Mar 2022 21:00:21 -0700 Subject: [PATCH 10/11] Update collection view --- resources/views/collection/show.blade.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/resources/views/collection/show.blade.php b/resources/views/collection/show.blade.php index 5d8ef0fec..c835068f5 100644 --- a/resources/views/collection/show.blade.php +++ b/resources/views/collection/show.blade.php @@ -4,12 +4,12 @@
@@ -30,4 +30,4 @@ -@endpush \ No newline at end of file +@endpush From 62b07195deae0c09a01e85f4ccb3a466e10b6c85 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Tue, 8 Mar 2022 21:01:20 -0700 Subject: [PATCH 11/11] 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 cd46c012f..d9436a21e 100644 --- a/routes/web.php +++ b/routes/web.php @@ -237,7 +237,7 @@ Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofact Route::get('collection/items/{id}', 'CollectionController@getItems'); Route::post('collection/item', 'CollectionController@storeId'); Route::delete('collection/item', 'CollectionController@deleteId'); - Route::get('collection/{id}', 'CollectionController@get'); + Route::get('collection/{id}', 'CollectionController@getCollection'); Route::post('collection/{id}', 'CollectionController@store'); Route::delete('collection/{id}', 'CollectionController@delete'); Route::post('collection/{id}/publish', 'CollectionController@publish');