refactor: auth manager (#27638)

This commit is contained in:
Jason Rasmussen
2026-04-14 08:49:24 -04:00
committed by GitHub
parent daed3f0966
commit 1ba0989e15
77 changed files with 387 additions and 379 deletions
@@ -31,6 +31,7 @@
import { activityManager } from '$lib/managers/activity-manager.svelte';
import { assetMultiSelectManager, AssetMultiSelectManager } from '$lib/managers/asset-multi-select-manager.svelte';
import { assetViewerManager } from '$lib/managers/asset-viewer-manager.svelte';
import { authManager } from '$lib/managers/auth-manager.svelte';
import { eventManager } from '$lib/managers/event-manager.svelte';
import { featureFlagsManager } from '$lib/managers/feature-flags-manager.svelte';
import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte';
@@ -47,7 +48,6 @@
import { getGlobalActions } from '$lib/services/app.service';
import { getAssetBulkActions } from '$lib/services/asset.service';
import { SlideshowNavigation, SlideshowState, slideshowStore } from '$lib/stores/slideshow.store';
import { preferences, user } from '$lib/stores/user.store';
import { handlePromiseError } from '$lib/utils';
import { handleError } from '$lib/utils/handle-error';
import { isAlbumsRoute, navigate, type AssetGridRouteSearchParams } from '$lib/utils/navigation';
@@ -243,7 +243,7 @@
onDestroy(() => activityManager.reset());
let isOwned = $derived($user.id == album.ownerId);
let isOwned = $derived(authManager.user.id == album.ownerId);
let showActivityStatus = $derived(
album.albumUsers.length > 0 &&
@@ -251,8 +251,8 @@
(album.isActivityEnabled || activityManager.commentCount > 0),
);
let isEditor = $derived(
album.albumUsers.find(({ user: { id } }) => id === $user.id)?.role === AlbumUserRole.Editor ||
album.ownerId === $user.id,
album.albumUsers.find(({ user: { id } }) => id === authManager.user.id)?.role === AlbumUserRole.Editor ||
album.ownerId === authManager.user.id,
);
let albumHasViewers = $derived(album.albumUsers.some(({ role }) => role === AlbumUserRole.Viewer));
@@ -485,7 +485,7 @@
/>
{/if}
{#if $preferences.tags.enabled && assetMultiSelectManager.isAllUserOwned}
{#if authManager.preferences.tags.enabled && assetMultiSelectManager.isAllUserOwned}
<TagAction menuItem />
{/if}
@@ -615,7 +615,7 @@
{/if}
{/if}
</div>
{#if album.albumUsers.length > 0 && album && assetViewerManager.isShowActivityPanel && $user && !assetViewerManager.isViewing}
{#if album.albumUsers.length > 0 && album && assetViewerManager.isShowActivityPanel && authManager.authenticated && !assetViewerManager.isViewing}
<div class="flex">
<div
transition:fly={{ duration: 150 }}
@@ -623,12 +623,7 @@
class="z-2 w-90 md:w-115 overflow-y-auto transition-all dark:border-l dark:border-s-immich-dark-gray"
translate="yes"
>
<ActivityViewer
user={$user}
disabled={!album.isActivityEnabled}
albumOwnerId={album.ownerId}
albumId={album.id}
/>
<ActivityViewer disabled={!album.isActivityEnabled} albumOwnerId={album.ownerId} albumId={album.id} />
</div>
</div>
{/if}
@@ -16,9 +16,9 @@
import AssetSelectControlBar from '$lib/components/timeline/AssetSelectControlBar.svelte';
import Timeline from '$lib/components/timeline/Timeline.svelte';
import { assetMultiSelectManager } from '$lib/managers/asset-multi-select-manager.svelte';
import { authManager } from '$lib/managers/auth-manager.svelte';
import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte';
import { getAssetBulkActions } from '$lib/services/asset.service';
import { preferences } from '$lib/stores/user.store';
import { ActionButton, CommandPaletteDefaultProvider } from '@immich/ui';
import { mdiDotsVertical } from '@mdi/js';
import { t } from 'svelte-i18n';
@@ -80,7 +80,7 @@
unarchive={assetMultiSelectManager.isAllArchived}
onArchive={(ids, visibility) => timelineManager.update(ids, (asset) => (asset.visibility = visibility))}
/>
{#if $preferences.tags.enabled}
{#if authManager.preferences.tags.enabled}
<TagAction menuItem />
{/if}
<SetVisibilityAction menuItem onVisibilitySet={handleSetVisibility} />
@@ -21,11 +21,11 @@
import AssetSelectControlBar from '$lib/components/timeline/AssetSelectControlBar.svelte';
import SkipLink from '$lib/elements/SkipLink.svelte';
import { assetMultiSelectManager } from '$lib/managers/asset-multi-select-manager.svelte';
import { authManager } from '$lib/managers/auth-manager.svelte';
import type { Viewport } from '$lib/managers/timeline-manager/types';
import { Route } from '$lib/route';
import { getAssetBulkActions } from '$lib/services/asset.service';
import { foldersStore } from '$lib/stores/folders.svelte';
import { preferences } from '$lib/stores/user.store';
import { toTimelineAsset } from '$lib/utils/timeline-util';
import { joinPaths } from '$lib/utils/tree-utils';
import { ActionButton, CommandPaletteDefaultProvider, IconButton, Text } from '@immich/ui';
@@ -149,7 +149,7 @@
<ChangeLocation menuItem />
<ArchiveAction menuItem unarchive={assetMultiSelectManager.isAllArchived} onArchive={triggerAssetUpdate} />
<SetVisibilityAction menuItem onVisibilitySet={handleSetVisibility} />
{#if $preferences.tags.enabled && assetMultiSelectManager.isAllUserOwned}
{#if authManager.preferences.tags.enabled && assetMultiSelectManager.isAllUserOwned}
<TagAction menuItem />
{/if}
<DeleteAssets menuItem onAssetDelete={triggerAssetUpdate} onUndoDelete={triggerAssetUpdate} />
@@ -27,6 +27,7 @@
import Timeline from '$lib/components/timeline/Timeline.svelte';
import { PersonPageViewMode, QueryParameter, SessionStorageKey } from '$lib/constants';
import { assetMultiSelectManager } from '$lib/managers/asset-multi-select-manager.svelte';
import { authManager } from '$lib/managers/auth-manager.svelte';
import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte';
import type { TimelineAsset } from '$lib/managers/timeline-manager/types';
import PersonMergeSuggestionModal from '$lib/modals/PersonMergeSuggestionModal.svelte';
@@ -34,7 +35,6 @@
import { getAssetBulkActions } from '$lib/services/asset.service';
import { getPersonActions } from '$lib/services/person.service';
import { locale } from '$lib/stores/preferences.store';
import { preferences } from '$lib/stores/user.store';
import { websocketEvents } from '$lib/stores/websocket';
import { getPeopleThumbnailUrl } from '$lib/utils';
import { handleError } from '$lib/utils/handle-error';
@@ -483,7 +483,7 @@
unarchive={assetMultiSelectManager.isAllArchived}
onArchive={(ids, visibility) => timelineManager.update(ids, (asset) => (asset.visibility = visibility))}
/>
{#if $preferences.tags.enabled && assetMultiSelectManager.isAllUserOwned}
{#if authManager.preferences.tags.enabled && assetMultiSelectManager.isAllUserOwned}
<TagAction menuItem />
{/if}
<SetVisibilityAction menuItem onVisibilitySet={handleSetVisibility} />
@@ -21,11 +21,11 @@
import { AssetAction } from '$lib/constants';
import { assetMultiSelectManager } from '$lib/managers/asset-multi-select-manager.svelte';
import { assetViewerManager } from '$lib/managers/asset-viewer-manager.svelte';
import { authManager } from '$lib/managers/auth-manager.svelte';
import { memoryManager } from '$lib/managers/memory-manager.svelte';
import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte';
import { Route } from '$lib/route';
import { getAssetBulkActions } from '$lib/services/asset.service';
import { preferences } from '$lib/stores/user.store';
import { getAssetMediaUrl, memoryLaneTitle } from '$lib/utils';
import {
updateStackedAssetInTimeline,
@@ -102,7 +102,7 @@
onEscape={handleEscape}
withStacked
>
{#if $preferences.memories.enabled}
{#if authManager.preferences.memories.enabled}
<ImageCarousel {items} />
{/if}
{#snippet empty()}
@@ -150,7 +150,7 @@
menuItem
onArchive={(ids, visibility) => timelineManager.update(ids, (asset) => (asset.visibility = visibility))}
/>
{#if $preferences.tags.enabled}
{#if authManager.preferences.tags.enabled}
<TagAction menuItem />
{/if}
<DeleteAssets
@@ -20,12 +20,12 @@
import AssetSelectControlBar from '$lib/components/timeline/AssetSelectControlBar.svelte';
import { QueryParameter } from '$lib/constants';
import { assetMultiSelectManager } from '$lib/managers/asset-multi-select-manager.svelte';
import { authManager } from '$lib/managers/auth-manager.svelte';
import { featureFlagsManager } from '$lib/managers/feature-flags-manager.svelte';
import type { Viewport } from '$lib/managers/timeline-manager/types';
import { Route } from '$lib/route';
import { getAssetBulkActions } from '$lib/services/asset.service';
import { lang, locale } from '$lib/stores/preferences.store';
import { preferences } from '$lib/stores/user.store';
import { handlePromiseError } from '$lib/utils';
import { parseUtcDate } from '$lib/utils/date-time';
import { handleError } from '$lib/utils/handle-error';
@@ -353,7 +353,7 @@
<ChangeLocation menuItem />
<ArchiveAction menuItem unarchive={assetMultiSelectManager.isAllArchived} />
<SetVisibilityAction menuItem onVisibilitySet={handleSetVisibility} />
{#if $preferences.tags.enabled}
{#if authManager.preferences.tags.enabled}
<TagAction menuItem />
{/if}
<DeleteAssets menuItem {onAssetDelete} onUndoDelete={onSearchQueryUpdate} />
@@ -23,11 +23,11 @@
import { AssetAction } from '$lib/constants';
import SkipLink from '$lib/elements/SkipLink.svelte';
import { assetMultiSelectManager } from '$lib/managers/asset-multi-select-manager.svelte';
import { authManager } from '$lib/managers/auth-manager.svelte';
import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte';
import { Route } from '$lib/route';
import { getAssetBulkActions } from '$lib/services/asset.service';
import { getTagActions } from '$lib/services/tag.service';
import { preferences } from '$lib/stores/user.store';
import { joinPaths, TreeNode } from '$lib/utils/tree-utils';
import { getAllTags, type TagResponseDto } from '@immich/sdk';
import { ActionButton, CommandPaletteDefaultProvider, Text } from '@immich/ui';
@@ -132,7 +132,7 @@
menuItem
onArchive={(ids, visibility) => timelineManager.update(ids, (asset) => (asset.visibility = visibility))}
/>
{#if $preferences.tags.enabled}
{#if authManager.preferences.tags.enabled}
<TagAction menuItem />
{/if}
<DeleteAssets
+3 -3
View File
@@ -8,6 +8,7 @@
import NavigationLoadingBar from '$lib/components/shared-components/navigation-loading-bar.svelte';
import UploadPanel from '$lib/components/shared-components/upload-panel.svelte';
import VersionAnnouncement from '$lib/components/VersionAnnouncement.svelte';
import { authManager } from '$lib/managers/auth-manager.svelte';
import { eventManager } from '$lib/managers/event-manager.svelte';
import { serverConfigManager } from '$lib/managers/server-config-manager.svelte';
import { themeManager } from '$lib/managers/theme-manager.svelte';
@@ -15,7 +16,6 @@
import { Route } from '$lib/route';
import { locale } from '$lib/stores/preferences.store';
import { sidebarStore } from '$lib/stores/sidebar.svelte';
import { user } from '$lib/stores/user.store';
import { closeWebsocketConnection, openWebsocketConnection, websocketStore } from '$lib/stores/websocket';
import { copyToClipboard } from '$lib/utils';
import { maintenanceShouldRedirect } from '$lib/utils/maintenance';
@@ -112,7 +112,7 @@
const { serverRestarting } = websocketStore;
$effect.pre(() => {
if ($user || $serverRestarting || page.url.pathname.startsWith(Route.maintenanceMode())) {
if (authManager.authenticated || $serverRestarting || page.url.pathname.startsWith(Route.maintenanceMode())) {
openWebsocketConnection();
} else {
closeWebsocketConnection();
@@ -182,7 +182,7 @@
icon: mdiServer,
onAction: () => goto(Route.systemStatistics()),
},
].map((route) => ({ ...route, type: $t('page'), $if: () => $user?.isAdmin }));
].map((route) => ({ ...route, type: $t('page'), $if: () => authManager.user.isAdmin }));
const commands = $derived([...userCommands, ...adminCommands]);
</script>
+3 -3
View File
@@ -1,9 +1,9 @@
import { authManager } from '$lib/managers/auth-manager.svelte';
import { serverConfigManager } from '$lib/managers/server-config-manager.svelte';
import { Route } from '$lib/route';
import { getFormatter } from '$lib/utils/i18n';
import { init } from '$lib/utils/server';
import { redirect } from '@sveltejs/kit';
import { loadUser } from '../lib/utils/auth';
import type { PageLoad } from './$types';
export const ssr = false;
@@ -17,8 +17,8 @@ export const load = (async ({ fetch }) => {
redirect(307, Route.maintenanceMode());
}
const authenticated = await loadUser();
if (authenticated) {
await authManager.load();
if (authManager.authenticated) {
redirect(307, Route.photos());
}
@@ -1,8 +1,8 @@
<script lang="ts">
import { goto } from '$app/navigation';
import { authManager } from '$lib/managers/auth-manager.svelte';
import { Route } from '$lib/route';
import { handleCreateLibrary } from '$lib/services/library.service';
import { user } from '$lib/stores/user.store';
import { Field, FormModal, HelperText, Select } from '@immich/ui';
import { mdiFolderSync } from '@mdi/js';
import { t } from 'svelte-i18n';
@@ -14,7 +14,7 @@
const { data }: Props = $props();
let ownerId: string = $state($user.id);
let ownerId: string = $state(authManager.user.id);
const users = $state(data.allUsers);
const onClose = async () => {
@@ -1,8 +1,8 @@
<script lang="ts">
import { goto } from '$app/navigation';
import { authManager } from '$lib/managers/auth-manager.svelte';
import { Route } from '$lib/route';
import { handleUpdateUserAdmin } from '$lib/services/user-admin.service';
import { user as authUser } from '$lib/stores/user.store';
import { userInteraction } from '$lib/stores/user.svelte';
import { ByteUnit, convertFromBytes, convertToBytes } from '$lib/utils/byte-units';
import { Field, FormModal, Input, Link, NumberInput, Switch, Text } from '@immich/ui';
@@ -82,7 +82,7 @@
</Link>
</Text>
{#if user.id !== $authUser.id}
{#if user.id !== authManager.user.id}
<Field label={$t('admin.admin_user')}>
<Switch bind:checked={isAdmin} class="mt-4" />
</Field>
@@ -1,7 +1,6 @@
<script lang="ts">
import AuthPageLayout from '$lib/components/layouts/AuthPageLayout.svelte';
import { authManager } from '$lib/managers/auth-manager.svelte';
import { user } from '$lib/stores/user.store';
import { updateMyUser } from '@immich/sdk';
import { Alert, Button, Field, HelperText, PasswordInput, Stack, Text } from '@immich/ui';
import { t } from 'svelte-i18n';
@@ -32,7 +31,7 @@
<form onsubmit={onSubmit} class="flex flex-col gap-4">
<Alert color="primary" size="small" class="mb-2">
<Stack gap={4}>
<Text>{$t('hi_user', { values: { name: $user.name, email: $user.email } })}</Text>
<Text>{$t('hi_user', { values: { name: authManager.user.name, email: authManager.user.email } })}</Text>
<Text>{$t('change_password_description')}</Text>
</Stack>
</Alert>
+2 -3
View File
@@ -1,14 +1,13 @@
import { authManager } from '$lib/managers/auth-manager.svelte';
import { Route } from '$lib/route';
import { user } from '$lib/stores/user.store';
import { authenticate } from '$lib/utils/auth';
import { getFormatter } from '$lib/utils/i18n';
import { redirect } from '@sveltejs/kit';
import { get } from 'svelte/store';
import type { PageLoad } from './$types';
export const load = (async ({ url }) => {
await authenticate(url);
if (!get(user).shouldChangePassword) {
if (!authManager.user.shouldChangePassword) {
redirect(307, Route.photos());
}
+3 -3
View File
@@ -10,10 +10,10 @@
import OnboardingStorageTemplate from '$lib/components/onboarding-page/onboarding-storage-template.svelte';
import OnboardingTheme from '$lib/components/onboarding-page/onboarding-theme.svelte';
import OnboardingUserPrivacy from '$lib/components/onboarding-page/onboarding-user-privacy.svelte';
import { authManager } from '$lib/managers/auth-manager.svelte';
import { serverConfigManager } from '$lib/managers/server-config-manager.svelte';
import { systemConfigManager } from '$lib/managers/system-config-manager.svelte';
import { Route } from '$lib/route';
import { user } from '$lib/stores/user.store';
import { OnboardingRole } from '$lib/types';
import { setUserOnboarding, updateAdminOnboarding } from '@immich/sdk';
import {
@@ -101,7 +101,7 @@
return temporaryIndex === -1 ? 0 : temporaryIndex;
});
let userRole = $derived(
$user.isAdmin && !serverConfigManager.value.isOnboarded ? OnboardingRole.SERVER : OnboardingRole.USER,
authManager.user.isAdmin && !serverConfigManager.value.isOnboarded ? OnboardingRole.SERVER : OnboardingRole.USER,
);
let onboardingStepCount = $derived(onboardingSteps.filter((step) => shouldRunStep(step.role, userRole)).length);
@@ -128,7 +128,7 @@
const handleNextClicked = async () => {
if (nextStepIndex == -1) {
if ($user.isAdmin) {
if (authManager.user.isAdmin) {
await updateAdminOnboarding({ adminOnboardingUpdateDto: { isOnboarded: true } });
await serverConfigManager.loadServerConfig();
}