CluPilotCloud/app/Provisioning/Steps/Customer/CreateCustomerAdmin.php

61 lines
2.1 KiB
PHP

<?php
namespace App\Provisioning\Steps\Customer;
use App\Models\ProvisioningRun;
use App\Provisioning\StepResult;
use App\Services\Proxmox\ProxmoxClient;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Str;
class CreateCustomerAdmin extends CustomerStep
{
public function __construct(private ProxmoxClient $pve) {}
public function key(): string
{
return 'create_customer_admin';
}
public function maxDuration(): int
{
return 120;
}
public function execute(ProvisioningRun $run): StepResult
{
// Idempotent: admin already created.
if ($this->hasResource($run, 'nc_admin')) {
return StepResult::advance();
}
$instance = $this->instance($run);
$pve = $this->pve->forHost($instance->host);
$node = (string) $run->context('node');
$vmid = (int) $run->context('vmid');
$username = 'admin';
$password = Str::random(20);
$occ = 'cd /opt/nextcloud && docker compose exec -T';
// Retry-safe: if a prior crashed attempt already created the user, reset
// its password instead of re-running user:add (which Nextcloud rejects).
$exists = (int) ($pve->guestExec($node, $vmid, $occ.' app php occ user:info '.escapeshellarg($username))['exitcode'] ?? 1) === 0;
$action = $exists
? 'user:resetpassword --password-from-env '.escapeshellarg($username)
: 'user:add --password-from-env --group=admin '.escapeshellarg($username);
// Pass the password via env (OC_PASS), never on the argv/command line.
$this->guest($pve, $run, 'OC_PASS='.escapeshellarg($password).' '.$occ.' -e OC_PASS app php occ '.$action);
// Persist only the username (encrypted ref); hand the password to step 15
// encrypted-in-context for delivery, then it is scrubbed. Never plaintext.
$instance->update(['nc_admin_ref' => $username]);
$run->mergeContext(['admin_password' => Crypt::encryptString($password)]);
$this->recordResource($run, $instance->host, 'nc_admin', $username);
return StepResult::advance();
}
}