Skip to content

Commit

Permalink
Merge pull request #1198 from cultuurnet/PPF-511/migration-auth0
Browse files Browse the repository at this point in the history
PPF-508 Add migration auth0 -> keycloak clients
  • Loading branch information
grubolsch authored Jun 18, 2024
2 parents 1a99b01 + 62b69db commit 969fdb4
Show file tree
Hide file tree
Showing 2 changed files with 184 additions and 0 deletions.
79 changes: 79 additions & 0 deletions app/Console/Commands/Migrations/MigrateAuth0ToKeycloakClients.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?php

declare(strict_types=1);

namespace App\Console\Commands\Migrations;

use App\Domain\Integrations\Environment;
use App\Keycloak\Client;
use App\Keycloak\Repositories\KeycloakClientRepository;
use Illuminate\Console\Command;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Ramsey\Uuid\Uuid;

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

public function __construct(private readonly KeycloakClientRepository $keycloakClientRepository)
{
parent::__construct();
}

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

$total = count($auth0Clients);
if ($total <= 0) {
$this->warn('No clients found to migrate');
return self::SUCCESS;
}

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

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

foreach ($auth0Clients as $auth0Client) {
$client = new Client(
Uuid::fromString($auth0Client->id),
Uuid::fromString($auth0Client->integration_id),
$auth0Client->auth0_client_id,
$auth0Client->auth0_client_secret,
Environment::from($auth0Client->auth0_tenant),
);
$this->keycloakClientRepository->create($client);

$this->info(sprintf('Converted client %s', $auth0Client->id));

$bar->advance();
}

$bar->finish();

return self::SUCCESS;
}

private function findAuth0Clients(): 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');

return $query->get();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
<?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 Ramsey\Uuid\Uuid;
use Symfony\Component\Console\Command\Command;
use Tests\TestCase;

final class MigrateAuth0ToKeycloakClientsTest extends TestCase
{
use RefreshDatabase;

private const CLIENT_ID_1 = '27c500be-4cc4-4cb2-97d6-c966a27716c4';

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


public function test_complex_query_clients_already_exist_in_keycloak_table(): void
{
$integrationId = Uuid::uuid4()->toString();
$id1 = Uuid::uuid4()->toString();
$id2 = Uuid::uuid4()->toString();

DB::table('auth0_clients')->insert([
'id' => $id1,
'integration_id' => $integrationId,
'auth0_client_id' => 'deleted_client',
'auth0_client_secret' => 'secret1',
'auth0_tenant' => 'acc',
'created_at' => now(),
'updated_at' => now(),
'deleted_at' => now(),
]);

DB::table('auth0_clients')->insert([
'id' => $id2,
'integration_id' => $integrationId,
'auth0_client_id' => 'client_already_exist',
'auth0_client_secret' => 'secret1',
'auth0_tenant' => 'test',
'created_at' => now(),
'updated_at' => now(),
]);

DB::table('keycloak_clients')->insert([
'id' => $id2,
'integration_id' => $integrationId,
'client_id' => 'client_already_exist',
'client_secret' => 'secret1',
'realm' => 'test',
'created_at' => now(),
'updated_at' => now(),
]);

$this->getPendingCommand('migrate:keycloak')
->expectsOutput('No clients found to migrate')
->assertExitCode(Command::SUCCESS);

$this->assertDatabaseCount('auth0_clients', 2);
$this->assertDatabaseCount('keycloak_clients', 1);
}

public function test_migration_with_clients(): void
{
DB::table('auth0_clients')->insert([
'id' => self::CLIENT_ID_1,
'integration_id' => '3c570fb7-ff26-4284-a848-ae8c9c8e205d',
'auth0_client_id' => 'auth0_client1',
'auth0_client_secret' => 'secret1',
'auth0_tenant' => 'acc',
'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 27c500be-4cc4-4cb2-97d6-c966a27716c4')
->assertExitCode(Command::SUCCESS);

$this->assertDatabaseHas('keycloak_clients', [
'id' => self::CLIENT_ID_1,
'integration_id' => '3c570fb7-ff26-4284-a848-ae8c9c8e205d',
'client_id' => 'auth0_client1',
'client_secret' => 'secret1',
'realm' => 'acc',
]);
}

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

0 comments on commit 969fdb4

Please sign in to comment.