#!/usr/bin/env php $argv */ $flag = static function (array $argv, string $name): ?string { $prefix = '--' . $name . '='; foreach ($argv as $arg) { if (str_starts_with($arg, $prefix)) { return substr($arg, strlen($prefix)); } } return null; }; /** * @param array $argv */ $hasFlag = static function (array $argv, string $name): bool { return in_array('--' . $name, $argv, true); }; switch ($command) { case 'db:migrate': $run('migrate'); // no break case 'db:rollback': $run('rollback'); // no break case 'db:seed': $run('seed:run'); // no break case 'auth:bootstrap-service-token': $container = Container::build(); /** @var ServiceTokenBootstrap $boot */ $boot = $container->get(ServiceTokenBootstrap::class); /** @var string $rawToken */ $rawToken = $container->get('settings.ui_service_token'); $boot->bootstrap($rawToken); exit(0); case 'auth:create-token': $kindArg = $flag($argv, 'kind') ?? ''; $roleArg = $flag($argv, 'role'); $quiet = $hasFlag($argv, 'quiet'); $kind = TokenKind::tryFrom($kindArg); if ($kind === null) { fwrite(STDERR, "Unknown --kind: {$kindArg}. Admin tokens are the only kind supported here.\n"); exit(1); } if ($kind === TokenKind::Service) { fwrite(STDERR, "Refusing to create a service token via this command. Use UI_SERVICE_TOKEN + auth:bootstrap-service-token.\n"); exit(1); } if ($kind === TokenKind::Reporter || $kind === TokenKind::Consumer) { fwrite(STDERR, "Reporter/consumer tokens are bound to records and are issued via M04 endpoints, not this CLI.\n"); exit(1); } // kind=admin from here on. $role = $roleArg !== null ? Role::tryFrom(strtolower($roleArg)) : null; if ($role === null) { fwrite(STDERR, "Admin tokens require --role=viewer|operator|admin.\n"); exit(1); } $container = Container::build(); /** @var TokenIssuer $issuer */ $issuer = $container->get(TokenIssuer::class); /** @var TokenHasher $hasher */ $hasher = $container->get(TokenHasher::class); /** @var TokenRepository $repo */ $repo = $container->get(TokenRepository::class); $raw = $issuer->issue(TokenKind::Admin); $hash = $hasher->hash($raw); $repo->create(new TokenRecord( id: null, kind: TokenKind::Admin, hash: $hash, prefix: substr($raw, 0, 8), reporterId: null, consumerId: null, role: $role, expiresAt: null, revokedAt: null, lastUsedAt: null, )); if ($quiet) { fwrite(STDOUT, $raw); } else { fwrite(STDOUT, $raw . "\n"); fwrite(STDERR, "Created admin token (role={$role->value}). The token is only shown once.\n"); } exit(0); case null: case '--help': case '-h': fwrite(STDOUT, << Commands: db:migrate Run Phinx migrations db:rollback Roll back the most recent migration db:seed Run all seeders idempotently auth:bootstrap-service-token Provision UI_SERVICE_TOKEN row in api_tokens auth:create-token --kind=admin --role=admin|operator|viewer [--quiet] Create an admin token; raw token printed to stdout TXT); exit(0); default: fwrite(STDERR, "Unknown command: {$command}\n"); exit(1); }