/
DATKAI
/
ITCUP
Обзор
Документация
Войти
/
DATKAI
/
ITCUP
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
main
app/Filament/Pages/AdUserCreate.php
234 строки
9 KB
ITCUP Admin
feat(ad): создание пользователя в AD с группами и паролем
22 апр 2026, 11:01
22 апр 2026, 11:01
4cb5abf
Код
Авторство
О чём код?
<?php namespace App\Filament\Pages; use App\Services\LdapService; use BackedEnum; use Filament\Actions\Action; use Filament\Forms\Components\Select; use Filament\Forms\Components\TextInput; use Filament\Forms\Components\Toggle; use Filament\Forms\Concerns\InteractsWithForms; use Filament\Forms\Contracts\HasForms; use Filament\Notifications\Notification; use Filament\Pages\Page; use Filament\Schemas\Components\Section; use Filament\Schemas\Schema; use Filament\Support\Icons\Heroicon; class AdUserCreate extends Page implements HasForms { use InteractsWithForms; protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedUserPlus; protected static ?string $navigationLabel = 'Создать пользователя AD'; protected static string|\UnitEnum|null $navigationGroup = 'Настройки'; protected static ?int $navigationSort = 13; protected static ?string $title = 'Создание пользователя в Active Directory'; protected string $view = 'filament.pages.ad-user-create'; public ?array $data = []; public function mount(): void { $this->form->fill([ 'enabled' => true, 'must_change_password' => true, ]); } public function form(Schema $schema): Schema { return $schema->components([ Section::make('ФИО и основные данные') ->columns(3) ->columnSpanFull() ->schema([ TextInput::make('last_name') ->label('Фамилия') ->required() ->live(debounce: 500) ->afterStateUpdated(fn ($state, $set, $get) => $this->autofillNames($set, $get)), TextInput::make('given_name') ->label('Имя') ->required() ->live(debounce: 500) ->afterStateUpdated(fn ($state, $set, $get) => $this->autofillNames($set, $get)), TextInput::make('middle_name') ->label('Отчество'), TextInput::make('display_name') ->label('Полное имя (CN)') ->required() ->columnSpan(2) ->helperText('Автозаполняется из Фамилия+Имя+Отчество, можно редактировать'), TextInput::make('sam') ->label('sAMAccountName') ->required() ->maxLength(20) ->regex('/^[a-zA-Z0-9._\-]+$/') ->helperText('Логин для входа (до 20 символов, латиница)'), ]), Section::make('Учётная запись') ->columns(2) ->columnSpanFull() ->schema([ TextInput::make('upn') ->label('UPN (user@domain)') ->email() ->columnSpanFull() ->placeholder('ivanov@sibprofil3.com'), Select::make('ou_dn') ->label('OU (куда создать)') ->required() ->options(fn () => app(LdapService::class)->ouOptions(true)) ->searchable() ->native(false) ->columnSpanFull(), TextInput::make('password') ->label('Пароль') ->password() ->revealable() ->minLength(8) ->helperText('Требует LDAPS (порт 636) или StartTLS. Если пусто — аккаунт создан отключённым.'), TextInput::make('password_confirmation') ->label('Повтор пароля') ->password() ->revealable() ->same('password'), Toggle::make('enabled') ->label('Аккаунт активен') ->default(true) ->helperText('Применимо если установлен пароль'), Toggle::make('must_change_password') ->label('Смена пароля при входе') ->default(true), ]), Section::make('Дополнительные атрибуты') ->columns(2) ->columnSpanFull() ->collapsible() ->schema([ TextInput::make('email')->label('Email')->email(), TextInput::make('phone')->label('Телефон')->tel(), TextInput::make('title')->label('Должность'), TextInput::make('department')->label('Отдел'), TextInput::make('company')->label('Компания')->columnSpanFull(), ]), Section::make('Группы AD') ->description('Выберите группы, в которые будет добавлен пользователь') ->columnSpanFull() ->schema([ Select::make('group_dns') ->label('Группы') ->multiple() ->options(fn () => app(LdapService::class)->groupOptions()) ->searchable() ->preload() ->helperText('Поиск по имени. Domain Users добавится автоматически.'), ]), ])->statePath('data'); } protected function autofillNames($set, $get): void { $ln = trim((string) $get('last_name')); $gn = trim((string) $get('given_name')); $mn = trim((string) $get('middle_name')); if (empty($get('display_name'))) { $parts = array_filter([$ln, $gn, $mn]); if ($parts) { $set('display_name', implode(' ', $parts)); } } // Транслитерация sam из ФИО (если ещё не задан) if (empty($get('sam')) && $ln && $gn) { $set('sam', $this->translit(mb_strtolower(trim("{$ln}.{$gn}")))); } } protected function translit(string $s): string { $map = [ 'а'=>'a','б'=>'b','в'=>'v','г'=>'g','д'=>'d','е'=>'e','ё'=>'e','ж'=>'zh', 'з'=>'z','и'=>'i','й'=>'y','к'=>'k','л'=>'l','м'=>'m','н'=>'n','о'=>'o', 'п'=>'p','р'=>'r','с'=>'s','т'=>'t','у'=>'u','ф'=>'f','х'=>'h','ц'=>'ts', 'ч'=>'ch','ш'=>'sh','щ'=>'sch','ъ'=>'','ы'=>'y','ь'=>'','э'=>'e','ю'=>'yu','я'=>'ya', ]; $s = strtr($s, $map); $s = preg_replace('/[^a-z0-9._\-]/', '', $s); return substr($s, 0, 20); } public function create(): void { $data = $this->form->getState(); // Группы DN, добавим автоматически Domain Users если известна база $groupDns = $data['group_dns'] ?? []; $res = app(LdapService::class)->createAdUser([ 'sam' => $data['sam'], 'upn' => $data['upn'] ?? null, 'display_name' => $data['display_name'], 'given_name' => $data['given_name'] ?? null, 'last_name' => $data['last_name'] ?? null, 'middle_name' => $data['middle_name'] ?? null, 'email' => $data['email'] ?? null, 'phone' => $data['phone'] ?? null, 'title' => $data['title'] ?? null, 'department' => $data['department'] ?? null, 'company' => $data['company'] ?? null, 'ou_dn' => $data['ou_dn'], 'password' => $data['password'] ?? null, 'enabled' => $data['enabled'] ?? true, 'must_change_password' => $data['must_change_password'] ?? false, 'group_dns' => $groupDns, ]); if ($res['ok']) { $body = $res['message']; if (!empty($res['warnings'])) { $body .= "\n\n⚠ " . implode("\n⚠ ", $res['warnings']); } Notification::make() ->title('Пользователь создан в AD') ->body($body) ->success() ->duration(15000) ->send(); // Очистим форму для следующего ввода $this->form->fill([ 'enabled' => true, 'must_change_password' => true, ]); } else { Notification::make() ->title('Ошибка создания') ->body($res['message']) ->danger() ->duration(15000) ->send(); } } protected function getFormActions(): array { return [ Action::make('create') ->label('Создать пользователя') ->icon('heroicon-o-user-plus') ->color('success') ->submit('create'), ]; } }