Files
ADconsle/app/Http/Controllers/Admin/ConfigController.php
T
kzbkowskiandClaude Sonnet 5 1126d96271
CI / PHP 8.2 (push) Failing after 2m46s
CI / PHP 8.3 (push) Failing after 59s
CI / PHP 8.4 (push) Failing after 1m7s
ADconsole v1.0.0
First public release.

- docs: document the audit log, user offboarding, CSV export and the
  "require a reason for destructive actions" setting across README, docs/
  and CLAUDE/AGENTS.md; note retention for panel_audit
- docs: fill the publishing placeholders (repo URL, security contact,
  issue-template links) and add a semantic-versioning policy
- move agent/contributor context into CLAUDE/ (AGENTS.md + a README);
  root CLAUDE.md is now a thin @-import pointer
- add a favicon (shield-lock, matching the login screen) to the login
  page and the app layout
- CHANGELOG: promote [Unreleased] to [1.0.0]; keep the earlier internal
  build as [0.1.0]

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UfuvfwexztdS7LDpGuKsuK
2026-09-08 23:14:39 +02:00

144 lines
6.9 KiB
PHP

<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Services\AuditLogger;
use App\Services\PanelSettingsService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
class ConfigController extends Controller
{
public function __construct(protected AuditLogger $audit) {}
public function index(PanelSettingsService $settings)
{
return view('admin.config.index', [
'settings' => $settings->all(),
'attributes' => $settings->attributes(),
'attributeCategories' => $settings->categories(),
'attributeTypeLabels' => PanelSettingsService::ATTRIBUTE_TYPE_LABELS,
'editableAttributeTypes' => PanelSettingsService::EDITABLE_ATTRIBUTE_TYPES,
'ldapDefaults' => [
'user_ou' => config('ldap.defaults.user_ou'),
'computer_ou' => config('ldap.defaults.computer_ou'),
'groups_ou' => config('ldap.defaults.groups_ou'),
'domain_label' => config('ldap.defaults.domain_label'),
],
'ldapConnection' => [
'hosts' => config('ldap.connections.default.hosts'),
'base_dn' => config('ldap.connections.default.base_dn'),
'encrypted' => (bool) config('ldap.connections.default.use_tls')
|| (bool) config('ldap.connections.default.use_starttls'),
'username' => config('ldap.connections.default.username'),
],
]);
}
public function update(Request $request, PanelSettingsService $settings): RedirectResponse
{
$data = $request->validate([
'reset_password.must_change_password' => ['nullable', 'boolean'],
'reset_password.unlock_account' => ['nullable', 'boolean'],
'password_policy.max_age_days' => ['required', 'integer', 'min:0', 'max:3650'],
'password_policy.generator_length' => ['nullable', 'integer', 'min:8', 'max:128'],
'password_policy.generator_symbols' => ['nullable', 'boolean'],
'encryption.key' => ['nullable', 'string', 'max:2048'],
'audit.require_reason' => ['nullable', 'boolean'],
]);
$current = $settings->all();
$current['reset_password']['must_change_password'] = (bool) ($data['reset_password']['must_change_password'] ?? false);
$current['reset_password']['unlock_account'] = (bool) ($data['reset_password']['unlock_account'] ?? false);
$current['password_policy']['max_age_days'] = (int) $data['password_policy']['max_age_days'];
$current['password_policy']['generator_length'] = (int) ($data['password_policy']['generator_length'] ?? 16);
$current['password_policy']['generator_symbols'] = (bool) ($data['password_policy']['generator_symbols'] ?? false);
$current['encryption']['key'] = trim((string) ($data['encryption']['key'] ?? ''));
$current['audit']['require_reason'] = (bool) ($data['audit']['require_reason'] ?? false);
$settings->save($current);
$this->audit->log('config.settings', [
'context' => [
'max_age_days' => $current['password_policy']['max_age_days'],
'require_reason' => $current['audit']['require_reason'],
'encryption_key_set' => $current['encryption']['key'] !== '',
],
]);
return back()->with('status', __('config.flash.saved'));
}
/**
* Zapisuje graficznie skonfigurowaną listę atrybutów AD (zakładka "Atrybuty"):
* dodanie / edycja / usunięcie, widoczność jako kolumna listy użytkowników
* oraz przypisanie do kategorii w oknie podglądu użytkownika.
*/
public function updateAttributes(Request $request, PanelSettingsService $settings): RedirectResponse
{
$validCategories = array_keys($settings->categories());
$data = $request->validate([
'attributes' => ['array'],
'attributes.*.key' => ['nullable', 'string', 'max:64', 'regex:/^[A-Za-z0-9_-]*$/'],
'attributes.*.label' => ['nullable', 'string', 'max:128'],
'attributes.*.ldap' => ['nullable', 'string', 'max:128', 'regex:/^[A-Za-z0-9-]*$/'],
'attributes.*.category' => ['nullable', 'string'],
'attributes.*.type' => ['nullable', 'string', 'in:'.implode(',', PanelSettingsService::ATTRIBUTE_TYPES)],
'attributes.*.column' => ['nullable', 'boolean'],
'attributes.*.regex' => ['nullable', 'string', 'max:191', function (string $attribute, mixed $value, \Closure $fail) {
if (is_string($value) && $value !== '' && @preg_match($value, '') === false) {
$fail(__('config.validation.regex_invalid'));
}
}],
'attributes.*.required' => ['nullable', 'boolean'],
'attributes.*.help' => ['nullable', 'string', 'max:255'],
], [
'attributes.*.key.regex' => __('config.validation.key_regex'),
'attributes.*.ldap.regex' => __('config.validation.ldap_regex'),
]);
$computedKeys = PanelSettingsService::COMPUTED_ATTRIBUTE_KEYS;
$rows = collect($data['attributes'] ?? [])
->map(function (array $row) use ($validCategories, $computedKeys) {
$key = trim((string) ($row['key'] ?? ''));
$category = $row['category'] ?? 'general';
$isComputed = in_array($key, $computedKeys, true);
return [
'key' => $key,
'label' => trim((string) ($row['label'] ?? '')),
// Kolumny wyliczane nie mają atrybutu AD - podstawiamy klucz,
// żeby przeszły przez filtr; PanelSettingsService i tak to wymusi.
'ldap' => $isComputed ? $key : trim((string) ($row['ldap'] ?? '')),
'category' => in_array($category, $validCategories, true) ? $category : 'general',
// Typ (tekst / liczba / data / tekst szyfrowany ...) - dla
// pozycji wbudowanych i tak wymusi go PanelSettingsService.
'type' => (string) ($row['type'] ?? 'text'),
// Reguły walidacji pola profilu - PanelSettingsService czyści
// je dla pozycji nieedytowalnych.
'regex' => trim((string) ($row['regex'] ?? '')),
'required' => (bool) ($row['required'] ?? false),
'help' => trim((string) ($row['help'] ?? '')),
'column' => (bool) ($row['column'] ?? false),
];
})
->filter(fn (array $row) => $row['key'] !== '' && $row['ldap'] !== '')
->values()
->all();
$settings->saveAttributes($rows);
$this->audit->log('config.attributes', [
'context' => ['count' => count($rows)],
]);
return back()
->with('status', __('config.flash.attributes_saved'))
->withFragment('attributes');
}
}