mirror of https://github.com/pixelfed/pixelfed.git
Merge pull request #2020 from pixelfed/staging
Update DeleteAccountPipeline, fixes #2016
This commit is contained in:
commit
6f96cafebd
|
@ -13,7 +13,7 @@ class UserDelete extends Command
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $signature = 'user:delete {id}';
|
protected $signature = 'user:delete {id} {--force}';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The console command description.
|
* The console command description.
|
||||||
|
@ -40,12 +40,24 @@ class UserDelete extends Command
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
$id = $this->argument('id');
|
$id = $this->argument('id');
|
||||||
$user = User::whereUsername($id)->orWhere('id', $id)->first();
|
$force = $this->option('force');
|
||||||
|
|
||||||
|
if(ctype_digit($id) == true) {
|
||||||
|
$user = User::find($id);
|
||||||
|
} else {
|
||||||
|
$user = User::whereUsername($id)->first();
|
||||||
|
}
|
||||||
|
|
||||||
if(!$user) {
|
if(!$user) {
|
||||||
$this->error('Could not find any user with that username or id.');
|
$this->error('Could not find any user with that username or id.');
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if($user->status == 'deleted' && $force == false) {
|
||||||
|
$this->error('Account has already been deleted.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if($user->is_admin == true) {
|
if($user->is_admin == true) {
|
||||||
$this->error('Cannot delete an admin account from CLI.');
|
$this->error('Cannot delete an admin account from CLI.');
|
||||||
exit;
|
exit;
|
||||||
|
@ -62,10 +74,12 @@ class UserDelete extends Command
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
$profile = $user->profile;
|
if($user->status !== 'deleted') {
|
||||||
$profile->status = $user->status = 'deleted';
|
$profile = $user->profile;
|
||||||
$profile->save();
|
$profile->status = $user->status = 'deleted';
|
||||||
$user->save();
|
$profile->save();
|
||||||
|
$user->save();
|
||||||
|
}
|
||||||
|
|
||||||
DeleteAccountPipeline::dispatch($user)->onQueue('high');
|
DeleteAccountPipeline::dispatch($user)->onQueue('high');
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,162 +10,170 @@ use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
use DB;
|
use DB;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
use App\{
|
use App\{
|
||||||
AccountLog,
|
AccountLog,
|
||||||
Activity,
|
Activity,
|
||||||
Avatar,
|
Avatar,
|
||||||
Bookmark,
|
Bookmark,
|
||||||
Collection,
|
Collection,
|
||||||
DirectMessage,
|
CollectionItem,
|
||||||
EmailVerification,
|
Contact,
|
||||||
Follower,
|
DirectMessage,
|
||||||
FollowRequest,
|
EmailVerification,
|
||||||
Hashtag,
|
Follower,
|
||||||
Like,
|
FollowRequest,
|
||||||
Media,
|
Hashtag,
|
||||||
Mention,
|
HashtagFollow,
|
||||||
Notification,
|
Like,
|
||||||
Profile,
|
Media,
|
||||||
Report,
|
Mention,
|
||||||
ReportComment,
|
Notification,
|
||||||
ReportLog,
|
OauthClient,
|
||||||
StatusHashtag,
|
Profile,
|
||||||
Status,
|
ProfileSponsor,
|
||||||
Story,
|
Report,
|
||||||
StoryView,
|
ReportComment,
|
||||||
User,
|
ReportLog,
|
||||||
UserDevice,
|
StatusHashtag,
|
||||||
UserFilter,
|
Status,
|
||||||
UserSetting,
|
Story,
|
||||||
|
StoryView,
|
||||||
|
User,
|
||||||
|
UserDevice,
|
||||||
|
UserFilter,
|
||||||
|
UserSetting,
|
||||||
};
|
};
|
||||||
|
|
||||||
class DeleteAccountPipeline implements ShouldQueue
|
class DeleteAccountPipeline implements ShouldQueue
|
||||||
{
|
{
|
||||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
|
|
||||||
protected $user;
|
protected $user;
|
||||||
|
|
||||||
/**
|
public function __construct(User $user)
|
||||||
* Create a new job instance.
|
{
|
||||||
*
|
$this->user = $user;
|
||||||
* @return void
|
}
|
||||||
*/
|
|
||||||
public function __construct(User $user)
|
|
||||||
{
|
|
||||||
$this->user = $user;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
public function handle()
|
||||||
* Execute the job.
|
{
|
||||||
*
|
$user = $this->user;
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function handle()
|
|
||||||
{
|
|
||||||
$user = $this->user;
|
|
||||||
DB::transaction(function() use ($user) {
|
|
||||||
AccountLog::chunk(200, function($logs) use ($user) {
|
|
||||||
foreach($logs as $log) {
|
|
||||||
if($log->user_id == $user->id) {
|
|
||||||
$log->forceDelete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
DB::transaction(function() use ($user) {
|
DB::transaction(function() use ($user) {
|
||||||
if($user->profile) {
|
AccountLog::chunk(200, function($logs) use ($user) {
|
||||||
$avatar = $user->profile->avatar;
|
foreach($logs as $log) {
|
||||||
|
if($log->user_id == $user->id) {
|
||||||
|
$log->forceDelete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
$avatar->forceDelete();
|
DB::transaction(function() use ($user) {
|
||||||
}
|
if($user->profile) {
|
||||||
|
$avatar = $user->profile->avatar;
|
||||||
|
$avatar->forceDelete();
|
||||||
|
}
|
||||||
|
|
||||||
Bookmark::whereProfileId($user->profile->id)->forceDelete();
|
$id = $user->profile_id;
|
||||||
|
|
||||||
EmailVerification::whereUserId($user->id)->forceDelete();
|
Bookmark::whereProfileId($user->profile_id)->forceDelete();
|
||||||
$id = $user->profile->id;
|
EmailVerification::whereUserId($user->id)->forceDelete();
|
||||||
|
StatusHashtag::whereProfileId($id)->delete();
|
||||||
|
FollowRequest::whereFollowingId($id)
|
||||||
|
->orWhere('follower_id', $id)
|
||||||
|
->forceDelete();
|
||||||
|
Follower::whereProfileId($id)
|
||||||
|
->orWhere('following_id', $id)
|
||||||
|
->forceDelete();
|
||||||
|
Like::whereProfileId($id)->forceDelete();
|
||||||
|
});
|
||||||
|
|
||||||
StatusHashtag::whereProfileId($id)->delete();
|
DB::transaction(function() use ($user) {
|
||||||
|
$pid = $this->user->profile_id;
|
||||||
|
|
||||||
FollowRequest::whereFollowingId($id)->orWhere('follower_id', $id)->forceDelete();
|
StoryView::whereProfileId($pid)->delete();
|
||||||
|
$stories = Story::whereProfileId($pid)->get();
|
||||||
|
foreach($stories as $story) {
|
||||||
|
$path = storage_path('app/'.$story->path);
|
||||||
|
if(is_file($path)) {
|
||||||
|
unlink($path);
|
||||||
|
}
|
||||||
|
$story->forceDelete();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
Follower::whereProfileId($id)->orWhere('following_id', $id)->forceDelete();
|
DB::transaction(function() use ($user) {
|
||||||
|
$medias = Media::whereUserId($user->id)->get();
|
||||||
|
foreach($medias as $media) {
|
||||||
|
$path = storage_path('app/'.$media->media_path);
|
||||||
|
$thumb = storage_path('app/'.$media->thumbnail_path);
|
||||||
|
if(is_file($path)) {
|
||||||
|
unlink($path);
|
||||||
|
}
|
||||||
|
if(is_file($thumb)) {
|
||||||
|
unlink($thumb);
|
||||||
|
}
|
||||||
|
$media->forceDelete();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
Like::whereProfileId($id)->forceDelete();
|
DB::transaction(function() use ($user) {
|
||||||
});
|
Mention::whereProfileId($user->profile_id)->forceDelete();
|
||||||
|
Notification::whereProfileId($user->profile_id)
|
||||||
|
->orWhere('actor_id', $user->profile_id)
|
||||||
|
->forceDelete();
|
||||||
|
});
|
||||||
|
|
||||||
DB::transaction(function() use ($user) {
|
DB::transaction(function() use ($user) {
|
||||||
$pid = $this->user->profile_id;
|
$collections = Collection::whereProfileId($user->profile_id)->get();
|
||||||
|
foreach ($collections as $collection) {
|
||||||
|
$collection->items()->delete();
|
||||||
|
$collection->delete();
|
||||||
|
}
|
||||||
|
Contact::whereUserId($user->id)->delete();
|
||||||
|
HashtagFollow::whereUserId($user->id)->delete();
|
||||||
|
OauthClient::whereUserId($user->id)->delete();
|
||||||
|
ProfileSponsor::whereProfileId($user->profile_id)->delete();
|
||||||
|
});
|
||||||
|
|
||||||
StoryView::whereProfileId($pid)->delete();
|
DB::transaction(function() use ($user) {
|
||||||
$stories = Story::whereProfileId($pid)->get();
|
Status::whereProfileId($user->profile_id)->forceDelete();
|
||||||
foreach($stories as $story) {
|
Report::whereUserId($user->id)->forceDelete();
|
||||||
$path = storage_path('app/'.$story->path);
|
$this->deleteProfile($user);
|
||||||
if(is_file($path)) {
|
});
|
||||||
unlink($path);
|
}
|
||||||
}
|
|
||||||
$story->forceDelete();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
DB::transaction(function() use ($user) {
|
protected function deleteProfile($user) {
|
||||||
$medias = Media::whereUserId($user->id)->get();
|
DB::transaction(function() use ($user) {
|
||||||
foreach($medias as $media) {
|
Profile::whereUserId($user->id)->delete();
|
||||||
$path = storage_path('app/'.$media->media_path);
|
$this->deleteUserSettings($user);
|
||||||
$thumb = storage_path('app/'.$media->thumbnail_path);
|
});
|
||||||
if(is_file($path)) {
|
}
|
||||||
unlink($path);
|
|
||||||
}
|
|
||||||
if(is_file($thumb)) {
|
|
||||||
unlink($thumb);
|
|
||||||
}
|
|
||||||
$media->forceDelete();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
DB::transaction(function() use ($user) {
|
protected function deleteUserSettings($user) {
|
||||||
Mention::whereProfileId($user->profile->id)->forceDelete();
|
|
||||||
Notification::whereProfileId($user->profile->id)->orWhere('actor_id', $user->profile->id)->forceDelete();
|
|
||||||
});
|
|
||||||
|
|
||||||
DB::transaction(function() use ($user) {
|
DB::transaction(function() use ($user) {
|
||||||
Status::whereProfileId($user->profile->id)->forceDelete();
|
UserDevice::whereUserId($user->id)->forceDelete();
|
||||||
Report::whereUserId($user->id)->forceDelete();
|
UserFilter::whereUserId($user->id)->forceDelete();
|
||||||
$this->deleteProfile($user);
|
UserSetting::whereUserId($user->id)->forceDelete();
|
||||||
});
|
$this->deleteUserColumns($user);
|
||||||
}
|
});
|
||||||
|
}
|
||||||
|
|
||||||
protected function deleteProfile($user) {
|
protected function deleteUserColumns($user)
|
||||||
DB::transaction(function() use ($user) {
|
{
|
||||||
Profile::whereUserId($user->id)->delete();
|
DB::transaction(function() use ($user) {
|
||||||
$this->deleteUserSettings($user);
|
$user->status = 'deleted';
|
||||||
});
|
$user->name = 'deleted';
|
||||||
}
|
$user->email = $user->id;
|
||||||
|
$user->password = '';
|
||||||
protected function deleteUserSettings($user) {
|
$user->remember_token = null;
|
||||||
|
$user->is_admin = false;
|
||||||
DB::transaction(function() use ($user) {
|
$user->{'2fa_enabled'} = false;
|
||||||
UserDevice::whereUserId($user->id)->forceDelete();
|
$user->{'2fa_secret'} = null;
|
||||||
UserFilter::whereUserId($user->id)->forceDelete();
|
$user->{'2fa_backup_codes'} = null;
|
||||||
UserSetting::whereUserId($user->id)->forceDelete();
|
$user->{'2fa_setup_at'} = null;
|
||||||
$this->deleteUserColumns($user);
|
$user->save();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function deleteUserColumns($user)
|
|
||||||
{
|
|
||||||
DB::transaction(function() use ($user) {
|
|
||||||
$user->status = 'deleted';
|
|
||||||
$user->name = 'deleted';
|
|
||||||
$user->email = $user->id;
|
|
||||||
$user->password = '';
|
|
||||||
$user->remember_token = null;
|
|
||||||
$user->is_admin = false;
|
|
||||||
$user->{'2fa_enabled'} = false;
|
|
||||||
$user->{'2fa_secret'} = null;
|
|
||||||
$user->{'2fa_backup_codes'} = null;
|
|
||||||
$user->{'2fa_setup_at'} = null;
|
|
||||||
$user->save();
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,10 @@ class UserObserver
|
||||||
*/
|
*/
|
||||||
public function saved(User $user)
|
public function saved(User $user)
|
||||||
{
|
{
|
||||||
|
if($user->status == 'deleted') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (empty($user->profile)) {
|
if (empty($user->profile)) {
|
||||||
$profile = DB::transaction(function() use($user) {
|
$profile = DB::transaction(function() use($user) {
|
||||||
$profile = new Profile();
|
$profile = new Profile();
|
||||||
|
|
Loading…
Reference in New Issue