diff --git a/CHANGELOG.md b/CHANGELOG.md index 1083ed8e1..bdfa38426 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,15 @@ # Release Notes -## [Unreleased](https://github.com/pixelfed/pixelfed/compare/v0.11.8...dev) +## [Unreleased](https://github.com/pixelfed/pixelfed/compare/v0.11.9...dev) + +## [v0.11.9 (2023-08-06)](https://github.com/pixelfed/pixelfed/compare/v0.11.8...v0.11.9) ### Added - Import from Instagram ([#4466](https://github.com/pixelfed/pixelfed/pull/4466)) ([cf3078c5](https://github.com/pixelfed/pixelfed/commit/cf3078c5)) - Sign-in with Mastodon ([#4545](https://github.com/pixelfed/pixelfed/pull/4545)) ([45b9404e](https://github.com/pixelfed/pixelfed/commit/45b9404e)) - Health check endpoint at /api/service/health-check ([ff58f970](https://github.com/pixelfed/pixelfed/commit/ff58f970)) - Reblogs in home feed ([#4563](https://github.com/pixelfed/pixelfed/pull/4563)) ([b86d47bf](https://github.com/pixelfed/pixelfed/commit/b86d47bf)) +- Account Migrations ([#4578](https://github.com/pixelfed/pixelfed/pull/4578)) ([a9220e4e](https://github.com/pixelfed/pixelfed/commit/a9220e4e)) ### Updates - Update Notifications.vue component, fix filtering logic to prevent endless spinner ([3df9b53f](https://github.com/pixelfed/pixelfed/commit/3df9b53f)) @@ -50,6 +53,11 @@ - Update Timeline component, improve reblog support ([29de91e5](https://github.com/pixelfed/pixelfed/commit/29de91e5)) - Update timeline settings, add photo reblogs only option ([e2705b9a](https://github.com/pixelfed/pixelfed/commit/e2705b9a)) - Update PostContent, add text cw warning ([911504fa](https://github.com/pixelfed/pixelfed/commit/911504fa)) +- Update ActivityPubFetchService, add validateUrl parameter to bypass url validation to fetch content from blocked instances ([3d1b6516](https://github.com/pixelfed/pixelfed/commit/3d1b6516)) +- Update RemoteStatusDelete pipeline ([71e92261](https://github.com/pixelfed/pixelfed/commit/71e92261)) +- Update RemoteStatusDelete pipeline ([fab8f25e](https://github.com/pixelfed/pixelfed/commit/fab8f25e)) +- Update RemoteStatusPipeline, fix reply check ([618b6727](https://github.com/pixelfed/pixelfed/commit/618b6727)) +- ([](https://github.com/pixelfed/pixelfed/commit/)) - ([](https://github.com/pixelfed/pixelfed/commit/)) ## [v0.11.8 (2023-05-29)](https://github.com/pixelfed/pixelfed/compare/v0.11.7...v0.11.8) diff --git a/app/Http/Controllers/ProfileAliasController.php b/app/Http/Controllers/ProfileAliasController.php new file mode 100644 index 000000000..024005a8e --- /dev/null +++ b/app/Http/Controllers/ProfileAliasController.php @@ -0,0 +1,64 @@ +middleware('auth'); + } + + public function index(Request $request) + { + $aliases = $request->user()->profile->aliases; + return view('settings.aliases.index', compact('aliases')); + } + + public function store(Request $request) + { + $this->validate($request, [ + 'acct' => 'required' + ]); + + $acct = $request->input('acct'); + + if($request->user()->profile->aliases->count() >= 3) { + return back()->with('error', 'You can only add 3 account aliases.'); + } + + $webfingerService = WebfingerService::lookup($acct); + if(!$webfingerService || !isset($webfingerService['url'])) { + return back()->with('error', 'Invalid account, cannot add alias at this time.'); + } + $alias = new ProfileAlias; + $alias->profile_id = $request->user()->profile_id; + $alias->acct = $acct; + $alias->uri = $webfingerService['url']; + $alias->save(); + + return back()->with('status', 'Successfully added alias!'); + } + + public function delete(Request $request) + { + $this->validate($request, [ + 'acct' => 'required', + 'id' => 'required|exists:profile_aliases' + ]); + + $alias = ProfileAlias::where('profile_id', $request->user()->profile_id) + ->where('acct', $request->input('acct')) + ->findOrFail($request->input('id')); + + $alias->delete(); + + return back()->with('status', 'Successfully deleted alias!'); + } +} diff --git a/app/Models/ProfileAlias.php b/app/Models/ProfileAlias.php new file mode 100644 index 000000000..b7a3bdc9c --- /dev/null +++ b/app/Models/ProfileAlias.php @@ -0,0 +1,17 @@ +belongsTo(Profile::class); + } +} diff --git a/app/Profile.php b/app/Profile.php index 69994bf5b..0ce1e7be0 100644 --- a/app/Profile.php +++ b/app/Profile.php @@ -7,6 +7,7 @@ use App\Util\Lexer\PrettyNumber; use App\HasSnowflakePrimary; use Illuminate\Database\Eloquent\{Model, SoftDeletes}; use App\Services\FollowerService; +use App\Models\ProfileAlias; class Profile extends Model { @@ -369,9 +370,13 @@ class Profile extends Model return $this->hasMany(Story::class); } - public function reported() { return $this->hasMany(Report::class, 'object_id'); } + + public function aliases() + { + return $this->hasMany(ProfileAlias::class); + } } diff --git a/app/Transformer/ActivityPub/ProfileTransformer.php b/app/Transformer/ActivityPub/ProfileTransformer.php index 29f53425c..1df7b6100 100644 --- a/app/Transformer/ActivityPub/ProfileTransformer.php +++ b/app/Transformer/ActivityPub/ProfileTransformer.php @@ -4,17 +4,26 @@ namespace App\Transformer\ActivityPub; use App\Profile; use League\Fractal; +use App\Services\AccountService; class ProfileTransformer extends Fractal\TransformerAbstract { public function transform(Profile $profile) { - return [ + $res = [ '@context' => [ 'https://w3id.org/security/v1', 'https://www.w3.org/ns/activitystreams', [ 'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers', + 'alsoKnownAs' => [ + '@id' => 'as:alsoKnownAs', + '@type' => '@id' + ], + 'movedTo' => [ + '@id' => 'as:movedTo', + '@type' => '@id' + ] ], ], 'id' => $profile->permalink(), @@ -42,5 +51,15 @@ class ProfileTransformer extends Fractal\TransformerAbstract 'sharedInbox' => config('app.url') . '/f/inbox' ] ]; + + if($profile->aliases->count()) { + $res['alsoKnownAs'] = $profile->aliases->map(fn($alias) => $alias->uri); + } + + if($profile->moved_to_profile_id) { + $res['movedTo'] = AccountService::get($profile->moved_to_profile_id)['url']; + } + + return $res; } } diff --git a/database/migrations/2023_08_07_021252_create_profile_aliases_table.php b/database/migrations/2023_08_07_021252_create_profile_aliases_table.php new file mode 100644 index 000000000..ed9ab6ada --- /dev/null +++ b/database/migrations/2023_08_07_021252_create_profile_aliases_table.php @@ -0,0 +1,32 @@ +id(); + $table->unsignedBigInteger('profile_id')->nullable()->index(); + $table->string('acct')->nullable(); + $table->string('uri')->nullable(); + $table->foreign('profile_id')->references('id')->on('profiles'); + $table->unique(['profile_id', 'acct'], 'profile_id_acct_unique'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('profile_aliases'); + } +}; diff --git a/database/migrations/2023_08_08_045430_add_moved_to_profile_id_to_profiles_table.php b/database/migrations/2023_08_08_045430_add_moved_to_profile_id_to_profiles_table.php new file mode 100644 index 000000000..a13bb1705 --- /dev/null +++ b/database/migrations/2023_08_08_045430_add_moved_to_profile_id_to_profiles_table.php @@ -0,0 +1,28 @@ +unsignedBigInteger('moved_to_profile_id')->nullable(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('profiles', function (Blueprint $table) { + $table->dropColumn('moved_to_profile_id'); + }); + } +}; diff --git a/resources/views/settings/aliases/index.blade.php b/resources/views/settings/aliases/index.blade.php new file mode 100644 index 000000000..af79f654d --- /dev/null +++ b/resources/views/settings/aliases/index.blade.php @@ -0,0 +1,121 @@ +@extends('layouts.app') + +@section('content') +@if (session('status')) +
+ {{ session('status') }} +
+@endif +@if ($errors->any()) +
+ @foreach($errors->all() as $error) +

{{ $error }}

+ @endforeach +
+@endif +@if (session('error')) +
+ {{ session('error') }} +
+@endif + +
+
+
+
+
+
+
+
+

Manage Aliases

+ + + + Back to Settings + +
+ +
+ +
+
+

If you want to move from another account to this one, you can create an alias here first.

+

This alias is needed before you can move your followers from the old account to this one. Don't worry, making this change is safe and can be undone. The process of moving the account starts from the old one.

+ +

Your followers will be migrated to your new account, and in some instances your posts too! For more information on Aliases and Account Migration, visit the Help Center.

+
+ +
+
+
+

Old Account

+

oldUsername@example.org

+
+ +
+

Old Account

+

oldUsername2@example.net

+
+ +
+

We support migration to and from Pixelfed, Mastodon and most other platforms that use the Mastodon Account Migration extension.

+
+ +
+
+
+
+ +
+
+
+
+
+ @csrf + +
+ +

Enter the username@domain of your old account

+ +
+ + +
+
+ +
+

Aliases

+
+ @if(count($aliases)) + @foreach($aliases as $alias) +
+
+ {{ $alias->acct }} +
+ +
+
+ @csrf + + + +
+
+
+ @endforeach + @else +
+

No aliases found!

+
+ @endif +
+
+
+
+
+
+
+ +@endsection diff --git a/resources/views/settings/home.blade.php b/resources/views/settings/home.blade.php index 2c02cdde9..97cffd5ec 100644 --- a/resources/views/settings/home.blade.php +++ b/resources/views/settings/home.blade.php @@ -87,6 +87,14 @@

Select up to 4 pronouns that will appear on your profile.

+ +
+ +
+ Manage account alias +

To move from another account to this one, first you need to create an alias.

+
+
@if(config_cache('pixelfed.enforce_account_limit'))

Storage Usage

diff --git a/resources/views/site/help/your-profile.blade.php b/resources/views/site/help/your-profile.blade.php index 76f1e7ebd..22a105d33 100644 --- a/resources/views/site/help/your-profile.blade.php +++ b/resources/views/site/help/your-profile.blade.php @@ -141,6 +141,45 @@


+

Migration

+

+ +

+
+ To migrate your account successfully, your old account must be on a Pixelfed or Mastodon server, or one that supports the Mastodon Account Migration extension. +
+

Navigate to the Account Aliases page in the Settings to begin.

+
+
+

+

+ +

+
+ It can take a few hours to process post migration imports, please contact admins if it takes longer than 24 hours. +
+
+

+

+ +

+
+ Post migrations are officially supported on Pixelfed servers running v0.11.9+ and higher, and when enabled by server admins. +
+ It can take a few hours to process post migration imports, please contact admins if it takes longer than 24 hours. +
+
+

+

Delete Your Account