mirror of
https://github.com/Kovah/LinkAce.git
synced 2025-03-20 06:39:38 +01:00
Properly migrate existing API tokens, adjust register user command
This commit is contained in:
parent
2dd2810a30
commit
d37307785f
@ -3,43 +3,57 @@
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Actions\Fortify\CreateNewUser;
|
||||
use App\Actions\Settings\SetDefaultSettingsForUser;
|
||||
use App\Models\User;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class RegisterUserCommand extends Command
|
||||
{
|
||||
protected $signature = 'registeruser {name? : Username} {email? : User email address}';
|
||||
protected $description = 'Register a new user with a given user name and an email address.';
|
||||
|
||||
private ?string $userName;
|
||||
private ?string $userEmail;
|
||||
private ?string $userPassword;
|
||||
private bool $validationFailed = false;
|
||||
|
||||
public function handle(): void
|
||||
{
|
||||
$name = $this->argument('name');
|
||||
$email = $this->argument('email');
|
||||
$this->userName = $this->argument('name');
|
||||
$this->userEmail = $this->argument('email');
|
||||
|
||||
if (empty($name)) {
|
||||
$name = $this->ask('Please enter the user name');
|
||||
do {
|
||||
$this->askForUserDetails();
|
||||
|
||||
try {
|
||||
(new CreateNewUser)->create([
|
||||
'name' => $this->userName,
|
||||
'email' => $this->userEmail,
|
||||
'password' => $this->userPassword,
|
||||
'password_confirmation' => $this->userPassword,
|
||||
]);
|
||||
|
||||
$this->validationFailed = false;
|
||||
} catch (ValidationException $e) {
|
||||
$this->validationFailed = true;
|
||||
foreach ($e->errors() as $error) {
|
||||
$this->error(implode(' ', $error));
|
||||
}
|
||||
}
|
||||
} while ($this->validationFailed);
|
||||
|
||||
$this->info('User ' . $this->userName . ' registered.');
|
||||
}
|
||||
|
||||
protected function askForUserDetails(): void
|
||||
{
|
||||
if (empty($this->userName) || $this->validationFailed) {
|
||||
$this->userName = $this->ask('Please enter the user name containing only alpha-numeric characters, dashes or underscores', $this->userName);
|
||||
}
|
||||
|
||||
if (empty($email)) {
|
||||
$email = $this->ask('Please enter the user email address');
|
||||
if (empty($this->userEmail) || $this->validationFailed) {
|
||||
$this->userEmail = $this->ask('Please enter the user email address', $this->userEmail);
|
||||
}
|
||||
|
||||
// Check if the user exists
|
||||
if (User::where('email', $email)->first()) {
|
||||
$this->error('An user with the email address "' . $email . '" already exists!');
|
||||
return;
|
||||
}
|
||||
|
||||
$password = $this->secret('Please enter a password for ' . $name);
|
||||
|
||||
(new CreateNewUser)->create([
|
||||
'name' => $name,
|
||||
'email' => $email,
|
||||
'password' => $password,
|
||||
'password_confirmation' => $password,
|
||||
]);
|
||||
|
||||
$this->info('User ' . $name . ' registered.');
|
||||
$this->userPassword = $this->secret('Please enter a password for ' . $this->userName);
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,6 @@ use Spatie\Permission\Traits\HasRoles;
|
||||
* @property string $email
|
||||
* @property string $password
|
||||
* @property string|null $remember_token
|
||||
* @property string|null $api_token
|
||||
* @property string|null $two_factor_recovery_codes
|
||||
* @property string|null $two_factor_secret
|
||||
* @property Carbon|null $created_at
|
||||
@ -42,14 +41,12 @@ class User extends Authenticatable implements Auditable
|
||||
'name',
|
||||
'email',
|
||||
'password',
|
||||
'api_token',
|
||||
'blocked_at',
|
||||
];
|
||||
|
||||
protected $hidden = [
|
||||
'password',
|
||||
'remember_token',
|
||||
'api_token',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
|
@ -1,5 +1,6 @@
|
||||
<?php
|
||||
|
||||
use App\Enums\ApiToken;
|
||||
use App\Enums\ModelAttribute;
|
||||
use App\Enums\Role;
|
||||
use App\Models\LinkList;
|
||||
@ -8,11 +9,12 @@ use App\Models\Tag;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class MigrateUserData extends Migration
|
||||
{
|
||||
private bool $guestAccessEnabled;
|
||||
private bool $guestAccessEnabled = false;
|
||||
|
||||
public function up()
|
||||
{
|
||||
@ -24,6 +26,7 @@ class MigrateUserData extends Migration
|
||||
$this->migrateNoteVisibility();
|
||||
|
||||
$this->addUserRoles();
|
||||
$this->migrateApiTokens();
|
||||
}
|
||||
|
||||
protected function migrateLinkVisibility(): void
|
||||
@ -54,7 +57,7 @@ class MigrateUserData extends Migration
|
||||
$table->integer('visibility')->default(ModelAttribute::VISIBILITY_PRIVATE)->after('is_private');
|
||||
});
|
||||
|
||||
LinkList::withTrashed()->get()->each(function ($list) {
|
||||
LinkList::withTrashed()->get()->each(function (LinkList $list) {
|
||||
$list->visibility = match ((bool)$list->is_private) {
|
||||
true => ModelAttribute::VISIBILITY_PRIVATE,
|
||||
false => $this->guestAccessEnabled
|
||||
@ -74,7 +77,7 @@ class MigrateUserData extends Migration
|
||||
$table->integer('visibility')->default(ModelAttribute::VISIBILITY_PRIVATE)->after('is_private');
|
||||
});
|
||||
|
||||
Tag::withTrashed()->get()->each(function ($tag) {
|
||||
Tag::withTrashed()->get()->each(function (Tag $tag) {
|
||||
$tag->visibility = match ((bool)$tag->is_private) {
|
||||
true => ModelAttribute::VISIBILITY_PRIVATE,
|
||||
false => $this->guestAccessEnabled
|
||||
@ -94,7 +97,7 @@ class MigrateUserData extends Migration
|
||||
$table->integer('visibility')->default(ModelAttribute::VISIBILITY_PRIVATE)->after('is_private');
|
||||
});
|
||||
|
||||
Note::withTrashed()->get()->each(function ($note) {
|
||||
Note::withTrashed()->get()->each(function (Note $note) {
|
||||
$note->visibility = match ((bool)$note->is_private) {
|
||||
true => ModelAttribute::VISIBILITY_PRIVATE,
|
||||
false => $this->guestAccessEnabled
|
||||
@ -110,7 +113,7 @@ class MigrateUserData extends Migration
|
||||
|
||||
protected function addUserRoles(): void
|
||||
{
|
||||
\Illuminate\Support\Facades\Artisan::call('db:seed', ['--class' => 'RolesAndPermissionsSeeder']);
|
||||
Artisan::call('db:seed', ['--class' => 'RolesAndPermissionsSeeder']);
|
||||
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->timestamp('blocked_at')->nullable()->after('api_token');
|
||||
@ -122,4 +125,19 @@ class MigrateUserData extends Migration
|
||||
$newAdmin->assignRole(Role::ADMIN);
|
||||
}
|
||||
}
|
||||
|
||||
public function migrateApiTokens(): void
|
||||
{
|
||||
User::all()->each(function (User $user) {
|
||||
$user->tokens()->create([
|
||||
'name' => 'MigratedApiToken',
|
||||
'token' => hash('sha256', $user->api_token),
|
||||
'abilities' => [ApiToken::ABILITY_USER_ACCESS],
|
||||
]);
|
||||
});
|
||||
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->dropColumn('api_token');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,6 @@
|
||||
namespace Tests\Commands;
|
||||
|
||||
use App\Models\User;
|
||||
use App\Settings\SettingsAudit;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
@ -25,8 +24,6 @@ class RegisterUserCommandTest extends TestCase
|
||||
|
||||
$databaseUser = User::latest('id')->first();
|
||||
|
||||
//var_dump(User::all());
|
||||
|
||||
$this->assertEquals('Test', $databaseUser->name);
|
||||
$this->assertEquals('test@linkace.org', $databaseUser->email);
|
||||
}
|
||||
@ -36,7 +33,7 @@ class RegisterUserCommandTest extends TestCase
|
||||
User::factory()->create(); // Create admin dummy user
|
||||
|
||||
$this->artisan('registeruser')
|
||||
->expectsQuestion('Please enter the user name', 'Test')
|
||||
->expectsQuestion('Please enter the user name containing only alpha-numeric characters, dashes or underscores', 'Test')
|
||||
->expectsQuestion('Please enter the user email address', 'test@linkace.org')
|
||||
->expectsQuestion('Please enter a password for Test', 'testpassword')
|
||||
->expectsOutput('User Test registered.')
|
||||
@ -50,13 +47,20 @@ class RegisterUserCommandTest extends TestCase
|
||||
|
||||
public function testCommandWithDuplicateUser(): void
|
||||
{
|
||||
User::factory()->create(['email' => 'test@linkace.org']);
|
||||
User::factory()->create(['name' => 'Test', 'email' => 'test@linkace.org']);
|
||||
|
||||
$this->artisan('registeruser', [
|
||||
'name' => 'Test',
|
||||
'email' => 'test@linkace.org',
|
||||
])
|
||||
->expectsOutput('An user with the email address "test@linkace.org" already exists!')
|
||||
->assertExitCode(0);
|
||||
->expectsQuestion('Please enter a password for Test', 'testpassword')
|
||||
->expectsOutput('The name has already been taken.')
|
||||
->expectsOutput('The email has already been taken.')
|
||||
->expectsQuestion('Please enter the user name containing only alpha-numeric characters, dashes or underscores', 'Test2')
|
||||
->expectsQuestion('Please enter the user email address', 'test2@linkace.org')
|
||||
->expectsQuestion('Please enter a password for Test2', 'testpassword')
|
||||
->expectsOutput('User Test2 registered.')
|
||||
->assertExitCode(0)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,11 @@ use App\Models\Link;
|
||||
use App\Models\LinkList;
|
||||
use App\Models\Note;
|
||||
use App\Models\Tag;
|
||||
use App\Models\User;
|
||||
use App\Settings\SystemSettings;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Laravel\Sanctum\Sanctum;
|
||||
use Laravel\Sanctum\SanctumServiceProvider;
|
||||
use Tests\TestCase;
|
||||
|
||||
class UserDataMigrationTest extends TestCase
|
||||
@ -260,4 +264,34 @@ class UserDataMigrationTest extends TestCase
|
||||
'visibility' => 1, // is public
|
||||
]);
|
||||
}
|
||||
|
||||
public function testUserApiTokenMigration(): void
|
||||
{
|
||||
$this->migrateUpTo('2022_06_23_112431_migrate_user_data.php');
|
||||
|
||||
DB::table('users')->insert([
|
||||
'name' => 'test',
|
||||
'email' => 'test@linkace.org',
|
||||
'password' => 'test',
|
||||
'api_token' => 'testApiToken',
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
|
||||
$this->artisan('migrate');
|
||||
|
||||
$this->assertDatabaseHas('personal_access_tokens', [
|
||||
'tokenable_type' => 'App\Models\User',
|
||||
'tokenable_id' => '1',
|
||||
'name' => 'MigratedApiToken',
|
||||
'abilities' => '["user_access"]',
|
||||
]);
|
||||
|
||||
// Test if the token is valid
|
||||
Link::factory()->create(['url' => 'https://token-test.com']);
|
||||
|
||||
$this->get('links/feed', [
|
||||
'Authorization' => 'Bearer testApiToken'
|
||||
])->assertOk()->assertSee('https://token-test.com');
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user