adasdas
This commit is contained in:
@@ -20,7 +20,10 @@ if (isset($_SESSION['desktop_auth']) && is_array($_SESSION['desktop_auth'])) {
|
|||||||
|
|
||||||
if (!($accountCheck['allowed'] ?? false)) {
|
if (!($accountCheck['allowed'] ?? false)) {
|
||||||
unset($_SESSION['desktop_auth']);
|
unset($_SESSION['desktop_auth']);
|
||||||
header('Location: /auth/inactive/?message=' . urlencode((string) ($accountCheck['message'] ?? 'Dieses Konto ist noch nicht freigeschaltet.')), true, 302);
|
$target = (string) ($accountCheck['state'] ?? '') === 'pending'
|
||||||
|
? '/auth/pending/?username=' . urlencode((string) ($currentAuthUser['username'] ?? ''))
|
||||||
|
: '/auth/inactive/?message=' . urlencode((string) ($accountCheck['message'] ?? 'Dieses Konto ist noch nicht freigeschaltet.'));
|
||||||
|
header('Location: ' . $target, true, 302);
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,10 @@ if ($auth->isAuthenticated()) {
|
|||||||
|
|
||||||
if (!($accountCheck['allowed'] ?? false)) {
|
if (!($accountCheck['allowed'] ?? false)) {
|
||||||
$auth->logout();
|
$auth->logout();
|
||||||
header('Location: /auth/inactive/?message=' . urlencode((string) ($accountCheck['message'] ?? 'Dieses Konto ist noch nicht freigeschaltet.')), true, 302);
|
$target = (string) ($accountCheck['state'] ?? '') === 'pending'
|
||||||
|
? '/auth/pending/?username=' . urlencode((string) ($currentUser['username'] ?? ''))
|
||||||
|
: '/auth/inactive/?message=' . urlencode((string) ($accountCheck['message'] ?? 'Dieses Konto ist noch nicht freigeschaltet.'));
|
||||||
|
header('Location: ' . $target, true, 302);
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,9 +57,11 @@ if ($state === '' || $expectedState === '' || !hash_equals($expectedState, $stat
|
|||||||
|
|
||||||
if (!($accountCheck['allowed'] ?? false)) {
|
if (!($accountCheck['allowed'] ?? false)) {
|
||||||
$auth->logout();
|
$auth->logout();
|
||||||
http_response_code(403);
|
$target = (string) ($accountCheck['state'] ?? '') === 'pending'
|
||||||
$title = 'Zugriff gesperrt';
|
? '/auth/pending/?username=' . urlencode($username)
|
||||||
$message = (string) ($accountCheck['message'] ?? 'Dieses Konto ist noch nicht freigeschaltet.');
|
: '/auth/inactive/?message=' . urlencode((string) ($accountCheck['message'] ?? 'Dieses Konto ist noch nicht freigeschaltet.'));
|
||||||
|
header('Location: ' . $target, true, 302);
|
||||||
|
exit;
|
||||||
} else {
|
} else {
|
||||||
$auth->establishSession($tokenPayload, $userPayload);
|
$auth->establishSession($tokenPayload, $userPayload);
|
||||||
header('Location: ' . $redirectTarget, true, 302);
|
header('Location: ' . $redirectTarget, true, 302);
|
||||||
|
|||||||
72
public/auth/pending/index.php
Normal file
72
public/auth/pending/index.php
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
require_once dirname(__DIR__, 3) . '/src/App/bootstrap.php';
|
||||||
|
|
||||||
|
use App\ConfigLoader;
|
||||||
|
use App\RegistrationService;
|
||||||
|
|
||||||
|
$projectRoot = dirname(__DIR__, 3);
|
||||||
|
$registration = new RegistrationService($projectRoot, ConfigLoader::load($projectRoot, 'registration'));
|
||||||
|
$username = strtolower(trim((string) ($_GET['username'] ?? '')));
|
||||||
|
$request = $registration->findLatestByUsername($username);
|
||||||
|
$status = (string) ($request['status'] ?? 'pending_approval');
|
||||||
|
|
||||||
|
$statusMap = [
|
||||||
|
'pending_approval' => [
|
||||||
|
'title' => 'Freigabe ausstehend',
|
||||||
|
'copy' => 'Dein Konto wurde angelegt und wartet aktuell auf die manuelle Freigabe.',
|
||||||
|
'label' => 'Wartet auf Freigabe',
|
||||||
|
],
|
||||||
|
'provisioning_failed' => [
|
||||||
|
'title' => 'Bearbeitung erforderlich',
|
||||||
|
'copy' => 'Dein Konto konnte technisch noch nicht vollständig vorbereitet werden. Die Anfrage liegt bereits vor und wird geprüft.',
|
||||||
|
'label' => 'Technische Prüfung läuft',
|
||||||
|
],
|
||||||
|
'approved_active' => [
|
||||||
|
'title' => 'Freigeschaltet',
|
||||||
|
'copy' => 'Dein Konto wurde bereits freigeschaltet. Bitte melde dich erneut an.',
|
||||||
|
'label' => 'Freigeschaltet',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
$view = $statusMap[$status] ?? [
|
||||||
|
'title' => 'Freigabestatus',
|
||||||
|
'copy' => 'Der Status deiner Freigabe wird aktuell verarbeitet.',
|
||||||
|
'label' => 'In Bearbeitung',
|
||||||
|
];
|
||||||
|
?><!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title><?= htmlspecialchars($view['title'], ENT_QUOTES) ?></title>
|
||||||
|
<link rel="stylesheet" href="/assets/auth/login.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<main class="login-shell">
|
||||||
|
<section class="login-panel">
|
||||||
|
<div class="login-panel-top">
|
||||||
|
<p class="login-kicker">Kusche.Berlin</p>
|
||||||
|
<h1><?= htmlspecialchars($view['title'], ENT_QUOTES) ?></h1>
|
||||||
|
<p class="login-copy"><?= htmlspecialchars($view['copy'], ENT_QUOTES) ?></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="login-notice login-notice-info">
|
||||||
|
<strong>Aktueller Stand</strong>
|
||||||
|
<p>Status: <?= htmlspecialchars($view['label'], ENT_QUOTES) ?></p>
|
||||||
|
<?php if (is_array($request)): ?>
|
||||||
|
<p>Benutzername: <?= htmlspecialchars((string) ($request['username'] ?? ''), ENT_QUOTES) ?></p>
|
||||||
|
<p>E-Mail: <?= htmlspecialchars((string) ($request['email'] ?? ''), ENT_QUOTES) ?></p>
|
||||||
|
<p class="login-meta-inline">Vorgangs-ID: <?= htmlspecialchars((string) ($request['id'] ?? ''), ENT_QUOTES) ?></p>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="login-actions">
|
||||||
|
<a class="login-button login-button-primary" href="/auth/keycloak">Zum Login</a>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -23,7 +23,10 @@ if ($auth->isAuthenticated()) {
|
|||||||
|
|
||||||
if (!($accountCheck['allowed'] ?? false)) {
|
if (!($accountCheck['allowed'] ?? false)) {
|
||||||
$auth->logout();
|
$auth->logout();
|
||||||
header('Location: /auth/inactive/?message=' . urlencode((string) ($accountCheck['message'] ?? 'Dieses Konto ist noch nicht freigeschaltet.')), true, 302);
|
$target = (string) ($accountCheck['state'] ?? '') === 'pending'
|
||||||
|
? '/auth/pending/?username=' . urlencode((string) ($currentUser['username'] ?? ''))
|
||||||
|
: '/auth/inactive/?message=' . urlencode((string) ($accountCheck['message'] ?? 'Dieses Konto ist noch nicht freigeschaltet.'));
|
||||||
|
header('Location: ' . $target, true, 302);
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,28 +38,62 @@ final class AccountGate
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
$user = $this->ldap->getUserByUsername($username, ['uid', 'shadowExpire']);
|
$user = $this->ldap->getUserByUsername($username, ['uid', 'shadowExpire', 'memberOf']);
|
||||||
|
|
||||||
if (!is_array($user)) {
|
if (!is_array($user)) {
|
||||||
return [
|
return [
|
||||||
'allowed' => false,
|
'allowed' => false,
|
||||||
|
'state' => 'blocked',
|
||||||
'message' => 'Dieses Konto ist nicht freigeschaltet.',
|
'message' => 'Dieses Konto ist nicht freigeschaltet.',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
$shadowExpire = (string) ($user['shadowexpire'] ?? $user['shadowExpire'] ?? '');
|
$shadowExpire = (string) ($user['shadowexpire'] ?? $user['shadowExpire'] ?? '');
|
||||||
$activeShadowExpire = (string) ($this->config['ldap']['active_shadow_expire'] ?? -1);
|
$activeShadowExpire = (string) ($this->config['ldap']['active_shadow_expire'] ?? -1);
|
||||||
|
$pendingGroupDn = strtolower(trim((string) ($this->config['ldap']['pending_group_dn'] ?? '')));
|
||||||
|
$memberOf = $this->normalizeMemberOf($user['memberof'] ?? $user['memberOf'] ?? []);
|
||||||
|
$isPending = $pendingGroupDn !== '' && in_array($pendingGroupDn, $memberOf, true);
|
||||||
|
|
||||||
if ($shadowExpire !== $activeShadowExpire) {
|
if ($isPending && $shadowExpire !== $activeShadowExpire) {
|
||||||
return [
|
return [
|
||||||
'allowed' => false,
|
'allowed' => false,
|
||||||
|
'state' => 'pending',
|
||||||
'message' => 'Dieses Konto ist noch nicht freigeschaltet.',
|
'message' => 'Dieses Konto ist noch nicht freigeschaltet.',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($shadowExpire !== '' && $shadowExpire !== $activeShadowExpire) {
|
||||||
|
return [
|
||||||
|
'allowed' => false,
|
||||||
|
'state' => 'blocked',
|
||||||
|
'message' => 'Dieses Konto ist derzeit deaktiviert.',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'allowed' => true,
|
'allowed' => true,
|
||||||
|
'state' => 'active',
|
||||||
'message' => 'Konto ist aktiv.',
|
'message' => 'Konto ist aktiv.',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mixed $value
|
||||||
|
* @return array<int, string>
|
||||||
|
*/
|
||||||
|
private function normalizeMemberOf(mixed $value): array
|
||||||
|
{
|
||||||
|
if (is_string($value)) {
|
||||||
|
$value = [$value];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_array($value)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_values(array_filter(array_map(
|
||||||
|
static fn (mixed $item): string => strtolower(trim((string) $item)),
|
||||||
|
$value
|
||||||
|
)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,6 +51,14 @@ final class RegistrationService
|
|||||||
return $this->store->find($id);
|
return $this->store->find($id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, mixed>|null
|
||||||
|
*/
|
||||||
|
public function findLatestByUsername(string $username): ?array
|
||||||
|
{
|
||||||
|
return $this->store->findLatestByUsername($username);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array<string, string> $input
|
* @param array<string, string> $input
|
||||||
* @return array{success: bool, errors?: array<int, string>, request?: array<string, mixed>}
|
* @return array{success: bool, errors?: array<int, string>, request?: array<string, mixed>}
|
||||||
|
|||||||
@@ -42,6 +42,37 @@ final class RegistrationStore
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, mixed>|null
|
||||||
|
*/
|
||||||
|
public function findLatestByUsername(string $username): ?array
|
||||||
|
{
|
||||||
|
$username = strtolower(trim($username));
|
||||||
|
|
||||||
|
if ($username === '') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$matches = array_values(array_filter(
|
||||||
|
$this->read(),
|
||||||
|
static fn (array $item): bool => strtolower((string) ($item['username'] ?? '')) === $username
|
||||||
|
));
|
||||||
|
|
||||||
|
if ($matches === []) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
usort(
|
||||||
|
$matches,
|
||||||
|
static fn (array $left, array $right): int => strcmp(
|
||||||
|
(string) ($right['created_at'] ?? ''),
|
||||||
|
(string) ($left['created_at'] ?? '')
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return $matches[0];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array<string, mixed>|null
|
* @return array<string, mixed>|null
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user