From af28aecf216bfd1a95b998f2a7180311a3d1a495 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20van=20L=C3=BCck?= Date: Sun, 4 Dec 2022 22:54:27 +0100 Subject: [PATCH 01/13] Add a command to import emoji archives --- app/Console/Commands/ImportEmojis.php | 110 ++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 app/Console/Commands/ImportEmojis.php diff --git a/app/Console/Commands/ImportEmojis.php b/app/Console/Commands/ImportEmojis.php new file mode 100644 index 000000000..09f5480a5 --- /dev/null +++ b/app/Console/Commands/ImportEmojis.php @@ -0,0 +1,110 @@ +argument('path'); + + if (!file_exists($path) || !mime_content_type($path) == 'application/x-tar') { + $this->error('Path does not exist or is not a tarfile'); + return Command::FAILURE; + } + + $imported = 0; + $skipped = 0; + $failed = 0; + + $tar = new \PharData($path); + $tar->decompress(); + + foreach (new \RecursiveIteratorIterator($tar) as $entry) { + $this->line("Processing {$entry->getFilename()}"); + if (!$entry->isFile() || !$this->isImage($entry)) { + $failed++; + continue; + } + + $filename = pathinfo($entry->getFilename(), PATHINFO_FILENAME); + $extension = pathinfo($entry->getFilename(), PATHINFO_EXTENSION); + + // Skip macOS shadow files + if (str_starts_with($filename, '._')) { + continue; + } + + $shortcode = implode('', [ + $this->option('prefix'), + $filename, + $this->option('suffix'), + ]); + + $customEmoji = CustomEmoji::whereShortcode($shortcode)->first(); + + if ($customEmoji && !$this->option('overwrite')) { + $skipped++; + continue; + } + + $emoji = $customEmoji ?? new CustomEmoji(); + $emoji->shortcode = $shortcode; + $emoji->domain = config('pixelfed.domain.app'); + $emoji->disabled = $this->option('disabled'); + $emoji->save(); + + $fileName = $emoji->id . '.' . $extension; + Storage::putFileAs('public/emoji', $entry->getPathname(), $fileName); + $emoji->media_path = 'emoji/' . $fileName; + $emoji->save(); + $imported++; + Cache::forget('pf:custom_emoji'); + } + + $this->line("Imported: {$imported}"); + $this->line("Skipped: {$skipped}"); + $this->line("Failed: {$failed}"); + + //delete file + unlink(str_replace('.tar.gz', '.tar', $path)); + + return Command::SUCCESS; + } + + private function isImage($file) + { + $image = getimagesize($file->getPathname()); + return $image !== false; + } +} From c96bcd559df3ba8b6fae65cfee2e71d3b7184fa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20van=20L=C3=BCck?= Date: Thu, 8 Dec 2022 21:10:10 +0100 Subject: [PATCH 02/13] Check imported emojis for mimetype MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Nils van Lück --- app/Console/Commands/ImportEmojis.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/app/Console/Commands/ImportEmojis.php b/app/Console/Commands/ImportEmojis.php index 09f5480a5..77a0c29a4 100644 --- a/app/Console/Commands/ImportEmojis.php +++ b/app/Console/Commands/ImportEmojis.php @@ -52,7 +52,7 @@ class ImportEmojis extends Command foreach (new \RecursiveIteratorIterator($tar) as $entry) { $this->line("Processing {$entry->getFilename()}"); - if (!$entry->isFile() || !$this->isImage($entry)) { + if (!$entry->isFile() || !$this->isImage($entry) || !$this->isEmoji($entry->getPathname())) { $failed++; continue; } @@ -107,4 +107,12 @@ class ImportEmojis extends Command $image = getimagesize($file->getPathname()); return $image !== false; } + + private function isEmoji($filename) + { + $allowedMimeTypes = ['image/png', 'image/jpeg', 'image/webp']; + $mimeType = mime_content_type($filename); + + return in_array($mimeType, $allowedMimeTypes); + } } From 312bc0668518a4e653a24009c58ee3f68f93f091 Mon Sep 17 00:00:00 2001 From: Shlee Date: Sun, 11 Dec 2022 15:09:29 +1030 Subject: [PATCH 03/13] Update NotificationCard.vue --- resources/assets/js/components/NotificationCard.vue | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/resources/assets/js/components/NotificationCard.vue b/resources/assets/js/components/NotificationCard.vue index b2230cbca..d0452035d 100644 --- a/resources/assets/js/components/NotificationCard.vue +++ b/resources/assets/js/components/NotificationCard.vue @@ -34,7 +34,16 @@

- {{n.account.local == false ? '@':''}}{{truncate(n.account.username)}} commented on your post. + {{n.account.local == false ? '@':''}}{{truncate(n.account.username)}} commented on your + + post. + + + + + + post. +

From 031290d9873f51084387d176f1444d2b5f105d60 Mon Sep 17 00:00:00 2001 From: Shlee Date: Mon, 12 Dec 2022 00:31:34 +1030 Subject: [PATCH 04/13] Update NotificationCard.vue --- resources/assets/js/components/NotificationCard.vue | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/resources/assets/js/components/NotificationCard.vue b/resources/assets/js/components/NotificationCard.vue index d0452035d..5c6eb6da5 100644 --- a/resources/assets/js/components/NotificationCard.vue +++ b/resources/assets/js/components/NotificationCard.vue @@ -73,7 +73,16 @@

- {{n.account.local == false ? '@':''}}{{truncate(n.account.username)}} shared your post. + {{n.account.local == false ? '@':''}}{{truncate(n.account.username)}} shared your + + post. + + + + + + post. +

From 7dbdbf15a5fcfcd11726b4f3fabffa53cf08bb72 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Wed, 27 Dec 2023 02:51:47 -0700 Subject: [PATCH 05/13] Add Roles & Parental Controls --- app/Http/Controllers/Api/ApiV1Controller.php | 10 ++ app/Http/Controllers/UserRolesController.php | 10 ++ app/Models/UserRoles.php | 23 ++++ app/Providers/AuthServiceProvider.php | 2 +- app/Services/UserRoleService.php | 111 ++++++++++++++++++ ...3_12_27_081801_create_user_roles_table.php | 30 +++++ ...27_082024_add_has_roles_to_users_table.php | 28 +++++ 7 files changed, 213 insertions(+), 1 deletion(-) create mode 100644 app/Http/Controllers/UserRolesController.php create mode 100644 app/Models/UserRoles.php create mode 100644 app/Services/UserRoleService.php create mode 100644 database/migrations/2023_12_27_081801_create_user_roles_table.php create mode 100644 database/migrations/2023_12_27_082024_add_has_roles_to_users_table.php diff --git a/app/Http/Controllers/Api/ApiV1Controller.php b/app/Http/Controllers/Api/ApiV1Controller.php index 798d9ee55..6f314e0b3 100644 --- a/app/Http/Controllers/Api/ApiV1Controller.php +++ b/app/Http/Controllers/Api/ApiV1Controller.php @@ -98,6 +98,7 @@ use App\Jobs\MediaPipeline\MediaSyncLicensePipeline; use App\Services\DiscoverService; use App\Services\CustomEmojiService; use App\Services\MarkerService; +use App\Services\UserRoleService; use App\Models\Conversation; use App\Jobs\FollowPipeline\FollowAcceptPipeline; use App\Jobs\FollowPipeline\FollowRejectPipeline; @@ -1623,6 +1624,8 @@ class ApiV1Controller extends Controller ]); $user = $request->user(); + abort_if($user->has_roles && !UserRoleService::can('can-post', $user->id), 403, 'Invalid permissions for this action'); + AccountService::setLastActive($user->id); if($user->last_active_at == null) { @@ -1792,6 +1795,7 @@ class ApiV1Controller extends Controller abort_if(!$request->user(), 403); $user = $request->user(); + abort_if($user->has_roles && !UserRoleService::can('can-post', $user->id), 403, 'Invalid permissions for this action'); AccountService::setLastActive($user->id); $media = Media::whereUserId($user->id) @@ -1831,6 +1835,7 @@ class ApiV1Controller extends Controller ]); $user = $request->user(); + abort_if($user->has_roles && !UserRoleService::can('can-post', $user->id), 403, 'Invalid permissions for this action'); if($user->last_active_at == null) { return []; @@ -2419,8 +2424,13 @@ class ApiV1Controller extends Controller $max = $request->input('max_id'); $limit = $request->input('limit') ?? 20; $user = $request->user(); + $remote = $request->has('remote'); $local = $request->has('local'); + $userRoleKey = $remote ? 'can-view-network-feed' : 'can-view-public-feed'; + if($user->has_roles && !UserRoleService::can($userRoleKey, $user->id)) { + return []; + } $filtered = $user ? UserFilterService::filters($user->profile_id) : []; AccountService::setLastActive($user->id); $domainBlocks = UserFilterService::domainBlocks($user->profile_id); diff --git a/app/Http/Controllers/UserRolesController.php b/app/Http/Controllers/UserRolesController.php new file mode 100644 index 000000000..dbd34d0da --- /dev/null +++ b/app/Http/Controllers/UserRolesController.php @@ -0,0 +1,10 @@ + 'array' + ]; + + public function user() + { + return $this->belongsTo(User::class); + } +} diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php index 0ec8c1895..8e1a6a98d 100644 --- a/app/Providers/AuthServiceProvider.php +++ b/app/Providers/AuthServiceProvider.php @@ -14,7 +14,7 @@ class AuthServiceProvider extends ServiceProvider * @var array */ protected $policies = [ - 'App\Model' => 'App\Policies\ModelPolicy', + // 'App\Model' => 'App\Policies\ModelPolicy', ]; /** diff --git a/app/Services/UserRoleService.php b/app/Services/UserRoleService.php new file mode 100644 index 000000000..fef5356c2 --- /dev/null +++ b/app/Services/UserRoleService.php @@ -0,0 +1,111 @@ +first()) { + return $roles->roles; + } + + return self::defaultRoles(); + } + + public static function roleKeys() + { + return array_keys(self::defaultRoles()); + } + + public static function defaultRoles() + { + return [ + 'account-force-private' => true, + 'account-ignore-follow-requests' => true, + + 'can-view-public-feed' => true, + 'can-view-network-feed' => true, + 'can-view-discover' => true, + + 'can-post' => true, + 'can-comment' => true, + 'can-like' => true, + 'can-share' => true, + + 'can-follow' => false, + 'can-make-public' => false, + ]; + } + + public static function getRoles($id) + { + $myRoles = self::get($id); + $roleData = collect(self::roleData()) + ->map(function($role, $k) use($myRoles) { + $role['value'] = $myRoles[$k]; + return $role; + }) + ->toArray(); + return $roleData; + } + + public static function roleData() + { + return [ + 'account-force-private' => [ + 'title' => 'Force Private Account', + 'action' => 'Prevent changing account from private' + ], + 'account-ignore-follow-requests' => [ + 'title' => 'Ignore Follow Requests', + 'action' => 'Hide follow requests and associated notifications' + ], + 'can-view-public-feed' => [ + 'title' => 'Hide Public Feed', + 'action' => 'Hide the public feed timeline' + ], + 'can-view-network-feed' => [ + 'title' => 'Hide Network Feed', + 'action' => 'Hide the network feed timeline' + ], + 'can-view-discover' => [ + 'title' => 'Hide Discover', + 'action' => 'Hide the discover feature' + ], + 'can-post' => [ + 'title' => 'Can post', + 'action' => 'Allows new posts to be shared' + ], + 'can-comment' => [ + 'title' => 'Can comment', + 'action' => 'Allows new comments to be posted' + ], + 'can-like' => [ + 'title' => 'Can Like', + 'action' => 'Allows the ability to like posts and comments' + ], + 'can-share' => [ + 'title' => 'Can Share', + 'action' => 'Allows the ability to share posts and comments' + ], + 'can-follow' => [ + 'title' => 'Can Follow', + 'action' => 'Allows the ability to follow accounts' + ], + 'can-make-public' => [ + 'title' => 'Can make account public', + 'action' => 'Allows the ability to make account public' + ], + ]; + } +} diff --git a/database/migrations/2023_12_27_081801_create_user_roles_table.php b/database/migrations/2023_12_27_081801_create_user_roles_table.php new file mode 100644 index 000000000..4e6af18d0 --- /dev/null +++ b/database/migrations/2023_12_27_081801_create_user_roles_table.php @@ -0,0 +1,30 @@ +id(); + $table->unsignedBigInteger('profile_id')->unique()->index(); + $table->unsignedInteger('user_id')->unique()->index(); + $table->json('roles')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('user_roles'); + } +}; diff --git a/database/migrations/2023_12_27_082024_add_has_roles_to_users_table.php b/database/migrations/2023_12_27_082024_add_has_roles_to_users_table.php new file mode 100644 index 000000000..c60b81deb --- /dev/null +++ b/database/migrations/2023_12_27_082024_add_has_roles_to_users_table.php @@ -0,0 +1,28 @@ +boolean('has_roles')->default(false); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('users', function (Blueprint $table) { + $table->dropColumn('has_roles'); + }); + } +}; From 7b6c9c7428d704552e38d42314272a1b83967a51 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Mon, 1 Jan 2024 16:19:24 -0700 Subject: [PATCH 06/13] Update migrations --- .../migrations/2023_12_27_081801_create_user_roles_table.php | 1 + .../2023_12_27_082024_add_has_roles_to_users_table.php | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/database/migrations/2023_12_27_081801_create_user_roles_table.php b/database/migrations/2023_12_27_081801_create_user_roles_table.php index 4e6af18d0..59b8ab390 100644 --- a/database/migrations/2023_12_27_081801_create_user_roles_table.php +++ b/database/migrations/2023_12_27_081801_create_user_roles_table.php @@ -16,6 +16,7 @@ return new class extends Migration $table->unsignedBigInteger('profile_id')->unique()->index(); $table->unsignedInteger('user_id')->unique()->index(); $table->json('roles')->nullable(); + $table->json('meta')->nullable(); $table->timestamps(); }); } diff --git a/database/migrations/2023_12_27_082024_add_has_roles_to_users_table.php b/database/migrations/2023_12_27_082024_add_has_roles_to_users_table.php index c60b81deb..09246e37b 100644 --- a/database/migrations/2023_12_27_082024_add_has_roles_to_users_table.php +++ b/database/migrations/2023_12_27_082024_add_has_roles_to_users_table.php @@ -13,6 +13,8 @@ return new class extends Migration { Schema::table('users', function (Blueprint $table) { $table->boolean('has_roles')->default(false); + $table->unsignedInteger('parent_id')->nullable(); + $table->tinyInteger('role_id')->unsigned()->nullable()->index(); }); } @@ -23,6 +25,8 @@ return new class extends Migration { Schema::table('users', function (Blueprint $table) { $table->dropColumn('has_roles'); + $table->dropColumn('parent_id'); + $table->dropColumn('role_id'); }); } }; From d39946b045be826ef0079d9a8a06c7312f7ec93a Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Tue, 2 Jan 2024 22:04:27 -0700 Subject: [PATCH 07/13] Update ApiV1Controller, add permissions check --- app/Http/Controllers/Api/ApiV1Controller.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/app/Http/Controllers/Api/ApiV1Controller.php b/app/Http/Controllers/Api/ApiV1Controller.php index 6f314e0b3..c1dd8cbf4 100644 --- a/app/Http/Controllers/Api/ApiV1Controller.php +++ b/app/Http/Controllers/Api/ApiV1Controller.php @@ -1245,6 +1245,7 @@ class ApiV1Controller extends Controller abort_if(!$request->user(), 403); $user = $request->user(); + abort_if($user->has_roles && !UserRoleService::can('can-like', $user->id), 403, 'Invalid permissions for this action'); AccountService::setLastActive($user->id); @@ -1306,6 +1307,7 @@ class ApiV1Controller extends Controller abort_if(!$request->user(), 403); $user = $request->user(); + abort_if($user->has_roles && !UserRoleService::can('can-like', $user->id), 403, 'Invalid permissions for this action'); AccountService::setLastActive($user->id); @@ -3175,6 +3177,7 @@ class ApiV1Controller extends Controller abort_if(!$request->user(), 403); $user = $request->user(); + abort_if($user->has_roles && !UserRoleService::can('can-share', $user->id), 403, 'Invalid permissions for this action'); AccountService::setLastActive($user->id); $status = Status::whereScope('public')->findOrFail($id); @@ -3222,6 +3225,7 @@ class ApiV1Controller extends Controller abort_if(!$request->user(), 403); $user = $request->user(); + abort_if($user->has_roles && !UserRoleService::can('can-share', $user->id), 403, 'Invalid permissions for this action'); AccountService::setLastActive($user->id); $status = Status::whereScope('public')->findOrFail($id); @@ -3272,6 +3276,13 @@ class ApiV1Controller extends Controller '_pe' => 'sometimes' ]); + $user = $request->user(); + abort_if( + $user->has_roles && !UserRoleService::can('can-view-hashtag-feed', $user->id), + 403, + 'Invalid permissions for this action' + ); + if(config('database.default') === 'pgsql') { $tag = Hashtag::where('name', 'ilike', $hashtag) ->orWhere('slug', 'ilike', $hashtag) From 75b0f2dda043b26046f40417d9c1440734335bcf Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Tue, 2 Jan 2024 22:06:18 -0700 Subject: [PATCH 08/13] Update ComposeController, add permissions check --- app/Http/Controllers/ComposeController.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/Http/Controllers/ComposeController.php b/app/Http/Controllers/ComposeController.php index 9be50f346..e79625861 100644 --- a/app/Http/Controllers/ComposeController.php +++ b/app/Http/Controllers/ComposeController.php @@ -54,6 +54,7 @@ use App\Util\Lexer\Autolink; use App\Util\Lexer\Extractor; use App\Util\Media\License; use Image; +use App\Services\UserRoleService; class ComposeController extends Controller { @@ -92,6 +93,7 @@ class ComposeController extends Controller $user = Auth::user(); $profile = $user->profile; + abort_if($user->has_roles && !UserRoleService::can('can-post', $user->id), 403, 'Invalid permissions for this action'); $limitKey = 'compose:rate-limit:media-upload:' . $user->id; $limitTtl = now()->addMinutes(15); @@ -184,6 +186,7 @@ class ComposeController extends Controller ]); $user = Auth::user(); + abort_if($user->has_roles && !UserRoleService::can('can-post', $user->id), 403, 'Invalid permissions for this action'); $limitKey = 'compose:rate-limit:media-updates:' . $user->id; $limitTtl = now()->addMinutes(15); From cbe75ce8712f6d703b67738579e22dfa6226e1c2 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Tue, 2 Jan 2024 22:06:54 -0700 Subject: [PATCH 09/13] Update UserRolesController --- app/Http/Controllers/UserRolesController.php | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/UserRolesController.php b/app/Http/Controllers/UserRolesController.php index dbd34d0da..65a71d19d 100644 --- a/app/Http/Controllers/UserRolesController.php +++ b/app/Http/Controllers/UserRolesController.php @@ -3,8 +3,21 @@ namespace App\Http\Controllers; use Illuminate\Http\Request; +use App\Services\UserRoleService; class UserRolesController extends Controller { - // + public function __construct() + { + $this->middleware('auth'); + } + + public function getRoles(Request $request) + { + $this->validate($request, [ + 'id' => 'required' + ]); + + return UserRoleService::getRoles($request->user()->id); + } } From 0ef6812709fa36ed8ae79da144ba114fcdc02fe6 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Tue, 2 Jan 2024 22:07:42 -0700 Subject: [PATCH 10/13] Update UserRoleService, add useDefaultFallback parameter --- app/Services/UserRoleService.php | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/app/Services/UserRoleService.php b/app/Services/UserRoleService.php index fef5356c2..500a4666e 100644 --- a/app/Services/UserRoleService.php +++ b/app/Services/UserRoleService.php @@ -6,12 +6,19 @@ use App\Models\UserRoles; class UserRoleService { - public static function can($action, $id) + public static function can($action, $id, $useDefaultFallback = true) { + $default = self::defaultRoles(); $roles = self::get($id); - - return in_array($action, $roles) ? $roles[$action] : null; - } + return + in_array($action, array_keys($roles)) ? + $roles[$action] : + ( + $useDefaultFallback ? + $default[$action] : + false + ); + } public static function get($id) { @@ -36,6 +43,7 @@ class UserRoleService 'can-view-public-feed' => true, 'can-view-network-feed' => true, 'can-view-discover' => true, + 'can-view-hashtag-feed' => false, 'can-post' => true, 'can-comment' => true, From fd44c80ce9723cf91ece4767539f0c503b2f833f Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Wed, 3 Jan 2024 01:54:30 -0700 Subject: [PATCH 11/13] Update meta tags, improve descriptions and seo/og tags --- app/Services/AccountService.php | 35 ++++++++++++++++ resources/views/layouts/app.blade.php | 12 +++--- resources/views/profile/show.blade.php | 35 +++++++++++----- resources/views/status/show.blade.php | 56 +++++++++++++++++++++----- 4 files changed, 110 insertions(+), 28 deletions(-) diff --git a/app/Services/AccountService.php b/app/Services/AccountService.php index 98e878845..5ffc1e9b5 100644 --- a/app/Services/AccountService.php +++ b/app/Services/AccountService.php @@ -13,6 +13,7 @@ use League\Fractal; use League\Fractal\Serializer\ArraySerializer; use Illuminate\Support\Facades\DB; use Illuminate\Support\Str; +use \NumberFormatter; class AccountService { @@ -244,4 +245,38 @@ class AccountService return UserDomainBlock::whereProfileId($pid)->whereDomain($domain)->exists(); } + + public static function formatNumber($num) { + if(!$num || $num < 1) { + return "0"; + } + $num = intval($num); + $formatter = new NumberFormatter('en_US', NumberFormatter::DECIMAL); + $formatter->setAttribute(NumberFormatter::MAX_FRACTION_DIGITS, 1); + + if ($num >= 1000000000) { + return $formatter->format($num / 1000000000) . 'B'; + } else if ($num >= 1000000) { + return $formatter->format($num / 1000000) . 'M'; + } elseif ($num >= 1000) { + return $formatter->format($num / 1000) . 'K'; + } else { + return $formatter->format($num); + } + } + + public static function getMetaDescription($id) + { + $account = self::get($id, true); + + if(!$account) return ""; + + $posts = self::formatNumber($account['statuses_count']) . ' Posts, '; + $following = self::formatNumber($account['following_count']) . ' Following, '; + $followers = self::formatNumber($account['followers_count']) . ' Followers'; + $note = $account['note'] && strlen($account['note']) ? + ' · ' . \Purify::clean(strip_tags(str_replace("\n", '', str_replace("\r", '', $account['note'])))) : + ''; + return $posts . $following . $followers . $note; + } } diff --git a/resources/views/layouts/app.blade.php b/resources/views/layouts/app.blade.php index 94f90ed97..0136842bb 100644 --- a/resources/views/layouts/app.blade.php +++ b/resources/views/layouts/app.blade.php @@ -12,9 +12,9 @@ {{ $title ?? config_cache('app.name') }} - - - + + + @stack('meta') @@ -73,9 +73,9 @@ {{ $title ?? config('app.name', 'Pixelfed') }} - - - + + + @stack('meta') diff --git a/resources/views/profile/show.blade.php b/resources/views/profile/show.blade.php index 5107c0ab3..dfa8edabb 100644 --- a/resources/views/profile/show.blade.php +++ b/resources/views/profile/show.blade.php @@ -1,4 +1,13 @@ -@extends('layouts.app',['title' => $profile->username . " on " . config('app.name')]) +@extends('layouts.app', [ + 'title' => $profile->name . ' (@' . $acct . ') - Pixelfed', + 'ogTitle' => $profile->name . ' (@' . $acct . ')', + 'ogType' => 'profile' +]) + +@php +$acct = $profile->username . '@' . config('pixelfed.domain.app'); +$metaDescription = \App\Services\AccountService::getMetaDescription($profile->id); +@endphp @section('content') @if (session('error')) @@ -8,9 +17,6 @@ @endif -@if($profile->website) -{{$profile->website}} -@endif
- + @endsection -@push('meta') - - - - - - @if($status->viewType() == "video" || $status->viewType() == "video:album") - - @endif +@push('meta')@if($mediaCount && $s['pf_type'] === "photo" || $s['pf_type'] === "photo:album") + + @elseif($mediaCount && $s['pf_type'] === "video" || $s['pf_type'] === "video:album") + @endif + + + + + @endpush @push('scripts') From 5087a878854cb30b147e527985bb89e5180dfb4f Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Wed, 3 Jan 2024 02:00:47 -0700 Subject: [PATCH 12/13] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 10b13f261..13baca035 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -84,6 +84,7 @@ - Update AdminShadowFilter, fix deleted profile bug ([a492a95a](https://github.com/pixelfed/pixelfed/commit/a492a95a)) - Update FollowerService, add $silent param to remove method to more efficently purge relationships ([1664a5bc](https://github.com/pixelfed/pixelfed/commit/1664a5bc)) - Update AP ProfileTransformer, add published attribute ([adfaa2b1](https://github.com/pixelfed/pixelfed/commit/adfaa2b1)) +- Update meta tags, improve descriptions and seo/og tags ([fd44c80c](https://github.com/pixelfed/pixelfed/commit/fd44c80c)) - ([](https://github.com/pixelfed/pixelfed/commit/)) ## [v0.11.9 (2023-08-21)](https://github.com/pixelfed/pixelfed/compare/v0.11.8...v0.11.9) From bca248499417963d3e859b46de88fe9ca1aba3d0 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Wed, 3 Jan 2024 04:11:29 -0700 Subject: [PATCH 13/13] Update Webfinger util, add avatar entity. Fixes #1629 --- app/Util/Webfinger/Webfinger.php | 91 +++++++++++++++++++------------- 1 file changed, 54 insertions(+), 37 deletions(-) diff --git a/app/Util/Webfinger/Webfinger.php b/app/Util/Webfinger/Webfinger.php index 879103332..c900358e6 100644 --- a/app/Util/Webfinger/Webfinger.php +++ b/app/Util/Webfinger/Webfinger.php @@ -4,43 +4,60 @@ namespace App\Util\Webfinger; class Webfinger { - protected $user; - protected $subject; - protected $aliases; - protected $links; + protected $user; + protected $subject; + protected $aliases; + protected $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 __construct($user) + { + $avatar = $user ? $user->avatarUrl() : url('/storage/avatars/default.jpg'); + $avatarPath = parse_url($avatar, PHP_URL_PATH); + $extension = pathinfo($avatarPath, PATHINFO_EXTENSION); + $mimeTypes = [ + 'jpg' => 'image/jpeg', + 'jpeg' => 'image/jpeg', + 'png' => 'image/png', + 'gif' => 'image/gif', + 'svg' => 'image/svg', + ]; + $avatarType = $mimeTypes[$extension] ?? 'application/octet-stream'; - public function generate() - { - return [ - 'subject' => $this->subject, - 'aliases' => $this->aliases, - 'links' => $this->links, - ]; - } + $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(), + ], + [ + 'rel' => 'http://webfinger.net/rel/avatar', + 'type' => $avatarType, + 'href' => $avatar, + ], + ]; + } + + public function generate() + { + return [ + 'subject' => $this->subject, + 'aliases' => $this->aliases, + 'links' => $this->links, + ]; + } }