feat(auth): notify MapleDeploy on first-user registration
After the first user registers, clears the setup token and dispatches NotifySetupCompleteJob to POST the token to MapleDeploy's callback URL. Adds setup_callback_url column to instance_settings.
This commit is contained in:
parent
cff8339b0f
commit
b9174f8d09
3 changed files with 95 additions and 0 deletions
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace App\Actions\Fortify;
|
namespace App\Actions\Fortify;
|
||||||
|
|
||||||
|
use App\Jobs\NotifySetupCompleteJob;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Support\Facades\Hash;
|
use Illuminate\Support\Facades\Hash;
|
||||||
use Illuminate\Support\Facades\Validator;
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
|
@ -56,7 +57,18 @@ public function create(array $input): User
|
||||||
// Disable registration after first user is created
|
// Disable registration after first user is created
|
||||||
$settings = instanceSettings();
|
$settings = instanceSettings();
|
||||||
$settings->is_registration_enabled = false;
|
$settings->is_registration_enabled = false;
|
||||||
|
|
||||||
|
// MapleDeploy: notify control plane that setup is complete
|
||||||
|
// Capture token before clearing so the job can authenticate with it
|
||||||
|
$callbackUrl = $settings->setup_callback_url;
|
||||||
|
$token = $settings->setup_token;
|
||||||
|
$settings->setup_token = null;
|
||||||
|
$settings->setup_callback_url = null;
|
||||||
$settings->save();
|
$settings->save();
|
||||||
|
|
||||||
|
if ($callbackUrl && $token) {
|
||||||
|
NotifySetupCompleteJob::dispatch($token, $callbackUrl);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
$user = User::create([
|
$user = User::create([
|
||||||
'name' => $input['name'],
|
'name' => $input['name'],
|
||||||
|
|
|
||||||
55
app/Jobs/NotifySetupCompleteJob.php
Normal file
55
app/Jobs/NotifySetupCompleteJob.php
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Jobs;
|
||||||
|
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldBeEncrypted;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use Illuminate\Support\Facades\Http;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify MapleDeploy that the first user has registered on this Coolify instance.
|
||||||
|
*
|
||||||
|
* Sends the setup token as a Bearer token so MapleDeploy can verify authenticity
|
||||||
|
* and clear its stored copy. The token acts as a one-time shared secret.
|
||||||
|
*/
|
||||||
|
class NotifySetupCompleteJob implements ShouldBeEncrypted, ShouldQueue
|
||||||
|
{
|
||||||
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
|
|
||||||
|
public $tries = 5;
|
||||||
|
|
||||||
|
public array $backoff = [10, 30, 60, 120, 300];
|
||||||
|
|
||||||
|
public int $maxExceptions = 5;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
public string $setupToken,
|
||||||
|
public string $callbackUrl
|
||||||
|
) {
|
||||||
|
$this->onQueue('high');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handle(): void
|
||||||
|
{
|
||||||
|
$response = Http::withToken($this->setupToken)
|
||||||
|
->timeout(15)
|
||||||
|
->post($this->callbackUrl);
|
||||||
|
|
||||||
|
if (! $response->successful()) {
|
||||||
|
Log::warning('Setup-complete callback failed', [
|
||||||
|
'status' => $response->status(),
|
||||||
|
'url' => $this->callbackUrl,
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Throw so the job retries
|
||||||
|
throw new \RuntimeException(
|
||||||
|
"Setup-complete callback returned HTTP {$response->status()}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('instance_settings', function (Blueprint $table) {
|
||||||
|
$table->string('setup_callback_url')->nullable();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('instance_settings', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('setup_callback_url');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
Loading…
Reference in a new issue