Files
mood-tracking/src/Domain/UserRepository.php
T
2026-04-11 19:13:40 +02:00

103 lines
2.6 KiB
PHP

<?php
declare(strict_types=1);
final class UserRepository
{
private string $path;
public function __construct()
{
$this->path = storage_path('system/users.json');
}
public function hasAnyUsers(): bool
{
return count($this->all()) > 0;
}
public function all(): array
{
$data = decode_json_file($this->path, ['users' => []]);
return array_values(array_filter($data['users'] ?? [], 'is_array'));
}
public function find(string $username): ?array
{
$needle = normalize_username($username);
foreach ($this->all() as $user) {
if (($user['username'] ?? '') === $needle) {
return $user;
}
}
return null;
}
public function verify(string $username, string $password): ?array
{
$user = $this->find($username);
if ($user === null) {
return null;
}
if (!password_verify($password, (string) ($user['password_hash'] ?? ''))) {
return null;
}
return $user;
}
public function create(string $username, string $password, bool $isAdmin = false): array
{
$normalized = normalize_username($username);
if ($normalized === '' || $this->find($normalized) !== null) {
throw new RuntimeException('Benutzername existiert bereits oder ist ungültig.');
}
$users = $this->all();
$users[] = [
'username' => $normalized,
'password_hash' => password_hash($password, PASSWORD_DEFAULT),
'is_admin' => $isAdmin,
'created_at' => date(DATE_ATOM),
];
$this->write(['users' => $users]);
return $this->find($normalized) ?? [];
}
public function changePassword(string $username, string $password): void
{
$normalized = normalize_username($username);
$users = $this->all();
foreach ($users as &$user) {
if (($user['username'] ?? '') === $normalized) {
$user['password_hash'] = password_hash($password, PASSWORD_DEFAULT);
$user['updated_at'] = date(DATE_ATOM);
}
}
unset($user);
$this->write(['users' => $users]);
}
private function write(array $payload): void
{
if (!is_dir(dirname($this->path))) {
mkdir(dirname($this->path), 0775, true);
}
file_put_contents(
$this->path,
json_encode($payload, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)
);
}
}