Skip to content

Commit

Permalink
add migration auth0 -> keycloak clients
Browse files Browse the repository at this point in the history
  • Loading branch information
Koen Eelen committed Jun 12, 2024
1 parent 7853a18 commit 5249a12
Show file tree
Hide file tree
Showing 2 changed files with 166 additions and 0 deletions.
88 changes: 88 additions & 0 deletions app/Console/Commands/Migrations/MigrateAuth0ToKeycloakClients.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<?php

declare(strict_types=1);

namespace App\Console\Commands\Migrations;

use Illuminate\Console\Command;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;

final class MigrateAuth0ToKeycloakClients extends Command
{
protected $signature = 'migrate:keycloak {updated_at?}';//updated_at format =
protected $description = 'Copy all auth0 clients to keycloak clients - does NOT remove the auth0 clients.';

public function __construct()
{
parent::__construct();
}

public function handle(): int
{
$updatedAt = $this->argument('updated_at');
$auth0Clients = $this->findAuth0Clients($updatedAt);

if ($updatedAt !== null && !preg_match('/^\d{4}-\d{2}-\d{2}$/', $updatedAt)) {
$this->warn('Invalid format used for updated at, use the format YYYY-MM-DD');
return self::FAILURE;
}

$total = count($auth0Clients);
if ($total <= 0) {
$this->warn($updatedAt ? 'No clients found to migrate starting from ' . $updatedAt : 'No clients found to migrate ');
return self::FAILURE;
}

if (!$this->confirm(
sprintf(
'Are you sure you want to copy %s auth0 clients to Keycloak %s?',
$total,
$updatedAt ? 'starting from ' . $updatedAt : ''
)
)) {
return self::FAILURE;
}

$bar = $this->output->createProgressBar($total);
$bar->start();

foreach ($auth0Clients as $client) {
DB::table('keycloak_clients')->insert([
'id' => $client->id,
'integration_id' => $client->integration_id,
'client_id' => $client->auth0_client_id,
'client_secret' => $client->auth0_client_secret,
'realm' => $client->auth0_tenant,
'created_at' => $client->created_at,
'updated_at' => $client->updated_at,
'deleted_at' => $client->deleted_at,
]);

$this->info(sprintf('Converted client %s - last updated at %s', $client->id, $client->updated_at));

$bar->advance();
}

$bar->finish();

return self::SUCCESS;
}

private function findAuth0Clients(?string $updatedAt): Collection
{
$query = DB::table('auth0_clients')
->orderBy('updated_at', 'asc')
->whereNotIn('auth0_clients.id', function ($query) {
$query->select('id')
->from('keycloak_clients');
})
->whereNull('deleted_at');

if ($updatedAt !== null) {
$query->where('updated_at', '>', $updatedAt);
}

return $query->get();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?php

declare(strict_types=1);

namespace Tests\Console\Commands\Migrations;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\DB;
use Illuminate\Testing\PendingCommand;
use Symfony\Component\Console\Command\Command;
use Tests\TestCase;

final class MigrateAuth0ToKeycloakClientsTest extends TestCase
{
use RefreshDatabase;

public function test_invalid_date_format(): void
{
$this->getPendingCommand('migrate:keycloak', ['updated_at' => 'invalid-date'])
->expectsOutput('Invalid format used for updated at, use the format YYYY-MM-DD')
->assertExitCode(Command::FAILURE);
}

public function test_no_clients_to_migrate(): void
{
$this->getPendingCommand('migrate:keycloak')
->expectsOutput('No clients found to migrate ')
->assertExitCode(Command::FAILURE);
}

public function test_no_clients_to_migrate_with_date(): void
{
$this->getPendingCommand('migrate:keycloak', ['updated_at' => '2023-01-01'])
->expectsOutput('No clients found to migrate starting from 2023-01-01')
->assertExitCode(Command::FAILURE);
}

public function test_migration_with_clients(): void
{
DB::table('auth0_clients')->insert([
'id' => 'client1',
'integration_id' => 'integration1',
'auth0_client_id' => 'auth0_client1',
'auth0_client_secret' => 'secret1',
'auth0_tenant' => 'tenant1',
'created_at' => now(),
'updated_at' => now(),
]);

$this->getPendingCommand('migrate:keycloak')
->expectsConfirmation('Are you sure you want to copy 1 auth0 clients to Keycloak ?', 'yes')
->expectsOutput('Converted client client1 - last updated at ' . now())
->assertExitCode(Command::SUCCESS);

$this->assertDatabaseHas('keycloak_clients', [
'id' => 'client1',
'integration_id' => 'integration1',
'client_id' => 'auth0_client1',
'client_secret' => 'secret1',
'realm' => 'tenant1',
]);
}

protected function tearDown(): void
{
DB::table('auth0_clients')->where('id', 'client1')->delete();
DB::table('keycloak_clients')->where('id', 'client1')->delete();

parent::tearDown();
}

private function getPendingCommand(string $command, array $params = []): PendingCommand
{
$command = $this->artisan($command, $params);
$this->assertInstanceOf(PendingCommand::class, $command);
return $command;
}
}

0 comments on commit 5249a12

Please sign in to comment.