From a9220e4e0159e7361432bd6576f1d82c827de784 Mon Sep 17 00:00:00 2001
From: Daniel Supernault
Date: Mon, 7 Aug 2023 23:48:58 -0600
Subject: [PATCH 1/9] Add Account Migrations
---
app/Models/ProfileAlias.php | 17 ++++++++++
...07_021252_create_profile_aliases_table.php | 32 +++++++++++++++++++
2 files changed, 49 insertions(+)
create mode 100644 app/Models/ProfileAlias.php
create mode 100644 database/migrations/2023_08_07_021252_create_profile_aliases_table.php
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/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');
+ }
+};
From 3c60362648086f7b07cc3a33b1e90164fe29df02 Mon Sep 17 00:00:00 2001
From: Daniel Supernault
Date: Mon, 7 Aug 2023 23:56:01 -0600
Subject: [PATCH 2/9] Add moved_to_profile_id migration
---
..._moved_to_profile_id_to_profiles_table.php | 28 +++++++++++++++++++
1 file changed, 28 insertions(+)
create mode 100644 database/migrations/2023_08_08_045430_add_moved_to_profile_id_to_profiles_table.php
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');
+ });
+ }
+};
From 3103af2fe494a2cd562aecff866e761d02e33dc4 Mon Sep 17 00:00:00 2001
From: Daniel Supernault
Date: Mon, 7 Aug 2023 23:58:02 -0600
Subject: [PATCH 3/9] Add Account Migration setting views
---
.../views/settings/aliases/index.blade.php | 121 ++++++++++++++++++
resources/views/settings/home.blade.php | 8 ++
2 files changed, 129 insertions(+)
create mode 100644 resources/views/settings/aliases/index.blade.php
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.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Aliases
+
+ @if(count($aliases))
+ @foreach($aliases as $alias)
+
+
+ {{ $alias->acct }}
+
+
+
+
+
+
+ @endforeach
+ @else
+
+ @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.
+
+
@if(config_cache('pixelfed.enforce_account_limit'))
Storage Usage
From eab16e7fd8a3a6c2274c418adb4d863b09a87d06 Mon Sep 17 00:00:00 2001
From: Daniel Supernault
Date: Mon, 7 Aug 2023 23:58:21 -0600
Subject: [PATCH 4/9] Add Help Center Documentation for Account Migration
---
.../views/site/help/your-profile.blade.php | 41 ++++++++++++++++++-
1 file changed, 40 insertions(+), 1 deletion(-)
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
+
+
+
+ How can I migrate my account?
+
+
+
+ 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.
+
+
+
+
+
+
+ How long does the migration take?
+
+
+
+ It can take a few hours to process post migration imports, please contact admins if it takes longer than 24 hours.
+
+
+
+
+
+
+ Why are my posts not migrated?
+
+
+
+ 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
@@ -191,4 +230,4 @@
@endif
-@endsection
\ No newline at end of file
+@endsection
From 9378c65396416ac39e46c9e2a7c2eac9d5cf7915 Mon Sep 17 00:00:00 2001
From: Daniel Supernault
Date: Mon, 7 Aug 2023 23:59:10 -0600
Subject: [PATCH 5/9] Add AccountMigration ActivityPub support
---
.../ActivityPub/ProfileTransformer.php | 21 ++++++++++++++++++-
1 file changed, 20 insertions(+), 1 deletion(-)
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;
}
}
From dc7973de62f9b61e366d7244dc669620c2bf9d51 Mon Sep 17 00:00:00 2001
From: Daniel Supernault
Date: Mon, 7 Aug 2023 23:59:29 -0600
Subject: [PATCH 6/9] Update Profile model, add aliases relation
---
app/Profile.php | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
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);
+ }
}
From 47e5c07061847acbb46ecfc201019360f9bc6e1b Mon Sep 17 00:00:00 2001
From: Daniel Supernault
Date: Tue, 8 Aug 2023 00:00:24 -0600
Subject: [PATCH 7/9] Add ProfileAliasController, hello account migrations!
---
.../Controllers/ProfileAliasController.php | 64 +++++++++++++++++++
1 file changed, 64 insertions(+)
create mode 100644 app/Http/Controllers/ProfileAliasController.php
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!');
+ }
+}
From 781d3c0ec3493dfca5197088d1855b6c81cdcca5 Mon Sep 17 00:00:00 2001
From: Daniel Supernault
Date: Tue, 8 Aug 2023 00:00:39 -0600
Subject: [PATCH 8/9] Update changelog
---
CHANGELOG.md | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
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)
From 526807f01c6cd0dce1e47c63fe966a8de80cf788 Mon Sep 17 00:00:00 2001
From: Daniel Supernault
Date: Tue, 8 Aug 2023 00:02:10 -0600
Subject: [PATCH 9/9] Update web routes
---
routes/web.php | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/routes/web.php b/routes/web.php
index bd4d978bf..bb091fce5 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -549,7 +549,7 @@ Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofact
Route::get('invites', 'UserInviteController@show')->name('settings.invites');
// Route::get('sponsor', 'SettingsController@sponsor')->name('settings.sponsor');
// Route::post('sponsor', 'SettingsController@sponsorStore');
- Route::prefix('import')->group(function() {
+ Route::group(['prefix' => 'import', 'middleware' => 'dangerzone'], function() {
Route::get('/', 'SettingsController@dataImport')->name('settings.import');
Route::prefix('instagram')->group(function() {
Route::get('/', 'ImportController@instagram')->name('settings.import.ig');
@@ -564,6 +564,12 @@ Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofact
Route::post('timeline', 'SettingsController@updateTimelineSettings');
Route::get('media', 'SettingsController@mediaSettings')->name('settings.media');
Route::post('media', 'SettingsController@updateMediaSettings');
+
+ Route::group(['prefix' => 'account/aliases', 'middleware' => 'dangerzone'], function() {
+ Route::get('manage', 'ProfileAliasController@index');
+ Route::post('manage', 'ProfileAliasController@store');
+ Route::post('manage/delete', 'ProfileAliasController@delete');
+ });
});
Route::group(['prefix' => 'site'], function () {