All checks were successful
Build MapleDeploy Coolify Image / build (push) Successful in 41s
107 lines
3.8 KiB
PHP
107 lines
3.8 KiB
PHP
<?php
|
|
|
|
namespace App\Console\Commands\Mapledeploy;
|
|
|
|
use App\Enums\Role;
|
|
use App\Models\Team;
|
|
use App\Models\User;
|
|
use Illuminate\Console\Command;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Hash;
|
|
use Illuminate\Support\Facades\Validator;
|
|
use Illuminate\Support\Str;
|
|
|
|
class UserSetPassword extends Command
|
|
{
|
|
protected $signature = 'mapledeploy:user:set-password
|
|
{user_id : Coolify user id}
|
|
{--email= : New user email address}
|
|
{--name= : New user display name}';
|
|
|
|
protected $description = 'Set a Coolify user password for MapleDeploy dashboard access management';
|
|
|
|
public function handle(): int
|
|
{
|
|
$password = rtrim((string) stream_get_contents(STDIN), "\n");
|
|
$updatesOwner = $this->option('email') !== null || $this->option('name') !== null;
|
|
$input = [
|
|
'password' => $password,
|
|
'email' => $this->option('email'),
|
|
'name' => $this->option('name'),
|
|
];
|
|
$rules = ['password' => ['required', 'string', 'min:8']];
|
|
if ($updatesOwner) {
|
|
$rules['email'] = ['required', 'string', 'email', 'max:255'];
|
|
$rules['name'] = ['required', 'string', 'max:255'];
|
|
}
|
|
$validator = Validator::make($input, $rules);
|
|
|
|
if ($validator->fails()) {
|
|
return $this->failWith('INVALID_INPUT');
|
|
}
|
|
|
|
$user = User::find($this->argument('user_id'));
|
|
if (! $user) {
|
|
return $this->failWith('USER_NOT_FOUND');
|
|
}
|
|
$rootTeam = null;
|
|
if ((int) $user->id !== 0) {
|
|
$rootTeam = Team::find(0);
|
|
if (! $rootTeam) {
|
|
return $this->failWith('ROOT_TEAM_MISSING');
|
|
}
|
|
}
|
|
|
|
$changes = [
|
|
'password' => Hash::make($password),
|
|
// MapleDeploy branding: clear the revocation marker when the
|
|
// dashboard intentionally restores this Coolify login.
|
|
'remember_token' => null,
|
|
];
|
|
if ($updatesOwner) {
|
|
$email = Str::lower((string) $input['email']);
|
|
if (User::whereEmail($email)->whereKeyNot($user->id)->exists()) {
|
|
return $this->failWith('EMAIL_EXISTS');
|
|
}
|
|
// MapleDeploy branding: claiming root admin transfers the Coolify
|
|
// account identity so the previous email holder cannot recover it.
|
|
$changes['email'] = $email;
|
|
$changes['name'] = $input['name'];
|
|
}
|
|
|
|
DB::transaction(function () use ($user, $changes, $updatesOwner, $rootTeam) {
|
|
$user->forceFill($changes)->save();
|
|
if ($updatesOwner && ! $user->hasVerifiedEmail()) {
|
|
$user->markEmailAsVerified();
|
|
}
|
|
if ($rootTeam) {
|
|
// MapleDeploy branding: matching an existing Coolify user by
|
|
// email must grant the same root-team admin access as a newly
|
|
// dashboard-created user.
|
|
$user->teams()->syncWithoutDetaching([
|
|
$rootTeam->id => ['role' => Role::ADMIN->value],
|
|
]);
|
|
}
|
|
// MapleDeploy branding: password resets from the dashboard should
|
|
// end browser sessions authenticated with the previous password.
|
|
DB::table('sessions')->where('user_id', $user->id)->delete();
|
|
});
|
|
|
|
$this->line(json_encode([
|
|
'user' => [
|
|
'id' => $user->id,
|
|
'email' => $user->email,
|
|
'name' => $user->name,
|
|
],
|
|
], JSON_THROW_ON_ERROR));
|
|
|
|
return self::SUCCESS;
|
|
}
|
|
|
|
private function failWith(string $code): int
|
|
{
|
|
$this->line(json_encode(['error' => $code], JSON_THROW_ON_ERROR));
|
|
|
|
return self::FAILURE;
|
|
}
|
|
}
|