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

62 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 App\Support\NextcloudOcc;
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);
// 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, NextcloudOcc::command('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);
// The password travels as OC_PASS rather than as an argument, so it never
// shows up in the guest's process list — see NextcloudOcc::command().
$this->guest($pve, $run, NextcloudOcc::command($action, ['OC_PASS' => $password]));
// 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();
}
}