Merge pull request 'fix: user settings' (#38) from fix/user-settings into main
All checks were successful
Renovate / renovate (push) Successful in 1m23s

Reviewed-on: #38
This commit was merged in pull request #38.
This commit is contained in:
2026-03-05 01:35:34 +00:00
4 changed files with 43 additions and 16 deletions

View File

@@ -60,7 +60,7 @@ class InitController extends ControllerAbstract
'permissions' => $this->userIdentity->identity()->getPermissions(), 'permissions' => $this->userIdentity->identity()->getPermissions(),
], ],
'profile' => $this->userService->getEditableFields($this->userIdentity->identifier()), 'profile' => $this->userService->getEditableFields($this->userIdentity->identifier()),
'settings' => $this->userService->fetchSettings(), 'settings' => $this->userService->fetchSettings([], true),
]; ];
return new JsonResponse($configuration); return new JsonResponse($configuration);

View File

@@ -2,6 +2,7 @@
namespace KTXC\Controllers; namespace KTXC\Controllers;
use KTXC\Http\Request\Request;
use KTXC\Http\Response\JsonResponse; use KTXC\Http\Response\JsonResponse;
use KTXC\Service\UserAccountsService; use KTXC\Service\UserAccountsService;
use KTXC\SessionIdentity; use KTXC\SessionIdentity;
@@ -18,7 +19,7 @@ class UserSettingsController extends ControllerAbstract
) {} ) {}
/** /**
* Retrieve user settings * Retrieve user settings, with optional filtering
* If no specific settings are requested, all settings are returned * If no specific settings are requested, all settings are returned
* *
* @return JsonResponse Settings data as key-value pairs * @return JsonResponse Settings data as key-value pairs
@@ -29,10 +30,9 @@ class UserSettingsController extends ControllerAbstract
methods: ['GET'], methods: ['GET'],
permissions: ['user.settings.read'] permissions: ['user.settings.read']
)] )]
public function read(): JsonResponse public function read(bool $flatten = false): JsonResponse
{ {
// Fetch all settings (no filter) $settings = $this->userService->fetchSettings(flatten: $flatten);
$settings = $this->userService->fetchSettings();
return new JsonResponse($settings, JsonResponse::HTTP_OK); return new JsonResponse($settings, JsonResponse::HTTP_OK);
} }
@@ -55,17 +55,17 @@ class UserSettingsController extends ControllerAbstract
*/ */
#[AuthenticatedRoute( #[AuthenticatedRoute(
'/user/settings', '/user/settings',
name: 'user.settings.update', name: 'user.settings.write',
methods: ['PUT', 'PATCH'], methods: ['POST', 'PUT', 'PATCH'],
permissions: ['user.settings.update'] permissions: ['user.settings.write']
)] )]
public function update(array $data): JsonResponse public function write(array $data): JsonResponse
{ {
$this->userService->storeSettings($data); $this->userService->storeSettings($data);
// Return updated settings // Return updated settings
$updatedSettings = $this->userService->fetchSettings(array_keys($data)); $settings = $this->userService->fetchSettings(array_keys($data));
return new JsonResponse($updatedSettings, JsonResponse::HTTP_OK); return new JsonResponse($settings, JsonResponse::HTTP_OK);
} }
} }

View File

@@ -116,9 +116,9 @@ class UserAccountsService
// Settings Operations // Settings Operations
// ========================================================================= // =========================================================================
public function fetchSettings(array $settings = []): array | null public function fetchSettings(array $settings = [], bool $flatten = false): array | null
{ {
return $this->userStore->fetchSettings($this->tenantIdentity->identifier(), $this->userIdentity->identifier(), $settings); return $this->userStore->fetchSettings($this->tenantIdentity->identifier(), $this->userIdentity->identifier(), $settings, $flatten);
} }
public function storeSettings(array $settings): bool public function storeSettings(array $settings): bool

View File

@@ -249,7 +249,7 @@ class UserAccountsStore
// Settings Operations // Settings Operations
// ========================================================================= // =========================================================================
public function fetchSettings(string $tenant, string $uid, array $settings = []): ?array public function fetchSettings(string $tenant, string $uid, array $settings = [], bool $flatten = false): ?array
{ {
// Only fetch the settings field from the database // Only fetch the settings field from the database
$user = $this->store->selectCollection('user_accounts')->findOne( $user = $this->store->selectCollection('user_accounts')->findOne(
@@ -264,12 +264,39 @@ class UserAccountsStore
$userSettings = $user['settings'] ?? []; $userSettings = $user['settings'] ?? [];
if (empty($settings)) { if (empty($settings)) {
return $userSettings; return $flatten ? $this->flattenSettings($userSettings) : $userSettings;
} }
// Specific keys are always returned in dot-notation (already flat)
$result = []; $result = [];
foreach ($settings as $key) { foreach ($settings as $key) {
$result[$key] = $userSettings[$key] ?? null; $parts = explode('.', $key);
$value = $userSettings;
foreach ($parts as $part) {
if (!is_array($value) || !array_key_exists($part, $value)) {
$value = null;
break;
}
$value = $value[$part];
}
$result[$key] = $value;
}
return $result;
}
/**
* Recursively flatten a nested settings array into dot-notation keys.
*/
private function flattenSettings(array $settings, string $prefix = ''): array
{
$result = [];
foreach ($settings as $key => $value) {
$fullKey = $prefix !== '' ? "{$prefix}.{$key}" : (string) $key;
if (is_array($value)) {
$result = array_merge($result, $this->flattenSettings($value, $fullKey));
} else {
$result[$fullKey] = $value;
}
} }
return $result; return $result;
} }