<?php namespace App\Console\Commands; use Illuminate\Console\Command; use App\{Profile, User}; use DB; use App\Util\Lexer\RestrictedNames; class FixUsernames extends Command { /** * The name and signature of the console command. * * @var string */ protected $signature = 'fix:usernames'; /** * The console command description. * * @var string */ protected $description = 'Fix invalid usernames'; /** * Create a new command instance. * * @return void */ public function __construct() { parent::__construct(); } /** * Execute the console command. * * @return mixed */ public function handle() { $this->line(' '); $this->info('Collecting data ...'); $this->line(' '); $this->restrictedCheck(); } protected function restrictedCheck() { $affected = collect([]); $restricted = RestrictedNames::get(); $users = User::chunk(100, function($users) use($affected, $restricted) { foreach($users as $user) { if($user->is_admin || $user->status == 'deleted') { continue; } if(in_array(strtolower($user->username), array_map('strtolower', $restricted))) { $affected->push($user); } $val = str_replace(['-', '_', '.'], '', $user->username); if(!ctype_alnum($val)) { $this->info('Found invalid username: ' . $user->username); $affected->push($user); } } }); if($affected->count() > 0) { $this->info('Found: ' . $affected->count() . ' affected usernames'); $opts = [ 'Random replace (assigns random username)', 'Best try replace (assigns alpha numeric username)', 'Manual replace (manually set username)', 'Skip (do not replace. Use at your own risk)' ]; foreach($affected as $u) { $old = $u->username; $this->info("Found user: {$old}"); $opt = $this->choice('Select fix method:', $opts, 3); switch ($opt) { case $opts[0]: $new = "user_" . str_random(6); $this->info('New username: ' . $new); break; case $opts[1]: $new = filter_var($old, FILTER_SANITIZE_STRING|FILTER_FLAG_STRIP_LOW); if(strlen($new) < 6) { $new = $new . '_' . str_random(4); } $this->info('New username: ' . $new); break; case $opts[2]: $new = $this->ask('Enter new username:'); $this->info('New username: ' . $new); break; case $opts[3]: $new = false; break; default: $new = "user_" . str_random(6); break; } if($new) { DB::transaction(function() use($u, $new) { $profile = $u->profile; $profile->username = $new; $u->username = $new; $u->save(); $profile->save(); }); } $this->info('Selected: ' . $opt); } $this->info('Fixed ' . $affected->count() . ' usernames!'); } else { $this->info('No restricted usernames found!'); } $this->line(' '); $this->versionZeroTenNineFix(); } protected function versionZeroTenNineFix() { $profiles = Profile::whereNotNull('domain') ->whereNull('private_key') ->where('username', 'not like', '@%@%') ->get(); $count = $profiles->count(); if($count > 0) { $this->info("Found {$count} remote usernames to fix ..."); $this->line(' '); } else { $this->info('No remote fixes found!'); $this->line(' '); return; } foreach($profiles as $p) { $this->info("Fixed $p->username => $p->webfinger"); $p->username = $p->webfinger ?? "@{$p->username}@{$p->domain}"; if(Profile::whereUsername($p->username)->exists()) { return; } $p->save(); } if($count > 0) { $this->line(' '); } } }