clusev/app/Livewire/Modals/CreateUser.php

105 lines
2.8 KiB
PHP

<?php
namespace App\Livewire\Modals;
use App\Models\AuditEvent;
use App\Models\User;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;
use LivewireUI\Modal\ModalComponent;
/**
* Form modal: add a new administrator account. Every account is a full admin
* (no roles). We generate a strong one-time password, store it hashed, and flag
* the account `must_change_password` so the new admin must rotate it on first
* sign-in. The clear-text temp password is revealed ONCE in the modal and never
* persisted or logged.
*/
class CreateUser extends ModalComponent
{
public string $name = '';
public string $email = '';
/** Clear-text temp password, held in component state only to reveal it once. */
public ?string $tempPassword = null;
/** Name of the account just created, used in the reveal copy. */
public string $createdName = '';
public static function modalMaxWidth(): string
{
return 'lg';
}
/**
* @return array<string, array<int, mixed>>
*/
protected function rules(): array
{
return [
'name' => ['required', 'string', 'max:120'],
'email' => ['required', 'string', 'email', 'max:255', Rule::unique('users', 'email')],
];
}
/**
* @return array<string, string>
*/
protected function validationAttributes(): array
{
return [
'name' => __('accounts.name_label'),
'email' => __('accounts.email_label'),
];
}
public function save(): void
{
$data = $this->validate();
// Re-check uniqueness server-side regardless of the live validator state.
$email = mb_strtolower(trim($data['email']));
if (User::where('email', $email)->exists()) {
$this->addError('email', __('validation.unique', ['attribute' => __('accounts.email_label')]));
return;
}
$temp = Str::password(16);
$user = User::create([
'name' => trim($data['name']),
'email' => $email,
'password' => Hash::make($temp),
'must_change_password' => true,
]);
AuditEvent::create([
'user_id' => Auth::id(),
'actor' => Auth::user()?->name ?? 'system',
'action' => 'user.create',
'target' => $user->email,
'ip' => request()->ip(),
]);
// Reveal the temp password ONCE — swaps the form for the reveal panel.
$this->createdName = $user->name;
$this->tempPassword = $temp;
}
/** "Fertig": reload the list and close. */
public function finish(): void
{
$this->dispatch('usersChanged');
$this->closeModal();
}
public function render()
{
return view('livewire.modals.create-user');
}
}