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
+1 -4
View File
@@ -6,11 +6,9 @@ import AlbumAddUsersModal from '$lib/modals/AlbumAddUsersModal.svelte';
import AlbumOptionsModal from '$lib/modals/AlbumOptionsModal.svelte';
import SharedLinkCreateModal from '$lib/modals/SharedLinkCreateModal.svelte';
import { Route } from '$lib/route';
import { user } from '$lib/stores/user.store';
import { createAlbumAndRedirect } from '$lib/utils/album-utils';
import { downloadArchive } from '$lib/utils/asset-utils';
import { openFileUploadDialog } from '$lib/utils/file-uploader';
import { handleError } from '$lib/utils/handle-error';
import { getFormatter } from '$lib/utils/i18n';
import {
@@ -32,7 +30,6 @@ import {
import { modalManager, toastManager, type ActionItem } from '@immich/ui';
import { mdiLink, mdiPlus, mdiPlusBoxOutline, mdiShareVariantOutline, mdiUpload } from '@mdi/js';
import { type MessageFormatter } from 'svelte-i18n';
import { get } from 'svelte/store';
export const getAlbumsActions = ($t: MessageFormatter) => {
const Create: ActionItem = {
@@ -45,7 +42,7 @@ export const getAlbumsActions = ($t: MessageFormatter) => {
};
export const getAlbumActions = ($t: MessageFormatter, album: AlbumResponseDto) => {
const isOwned = get(user).id === album.ownerId;
const isOwned = authManager.user.id === album.ownerId;
const Share: ActionItem = {
title: $t('share'),
+8 -3
View File
@@ -1,10 +1,11 @@
import { authManager } from '$lib/managers/auth-manager.svelte';
import { getAssetActions, handleDownloadAsset } from '$lib/services/asset.service';
import { user as userStore } from '$lib/stores/user.store';
import { setSharedLink } from '$lib/utils';
import { getFormatter } from '$lib/utils/i18n';
import { getAssetInfo } from '@immich/sdk';
import { toastManager } from '@immich/ui';
import { assetFactory } from '@test-data/factories/asset-factory';
import { preferencesFactory } from '@test-data/factories/preferences-factory';
import { sharedLinkFactory } from '@test-data/factories/shared-link-factory';
import { userAdminFactory } from '@test-data/factories/user-factory';
import { vitest } from 'vitest';
@@ -32,11 +33,15 @@ vitest.mock('$lib/utils', async () => {
describe('AssetService', () => {
describe('getAssetActions', () => {
beforeEach(() => {
authManager.setPreferences(preferencesFactory.build());
});
it('should allow shared link downloads if the user owns the asset and shared link downloads are disabled', () => {
const ownerId = 'owner';
const user = userAdminFactory.build({ id: ownerId });
const asset = assetFactory.build({ ownerId });
userStore.set(user);
authManager.setUser(user);
setSharedLink(sharedLinkFactory.build({ allowDownload: false }));
const assetActions = getAssetActions(() => '', asset);
expect(assetActions.SharedLinkDownload.$if?.()).toStrictEqual(true);
@@ -46,7 +51,7 @@ describe('AssetService', () => {
const ownerId = 'owner';
const user = userAdminFactory.build({ id: 'non-owner' });
const asset = assetFactory.build({ ownerId });
userStore.set(user);
authManager.setUser(user);
setSharedLink(sharedLinkFactory.build({ allowDownload: false }));
const assetActions = getAssetActions(() => '', asset);
expect(assetActions.SharedLinkDownload.$if?.()).toStrictEqual(false);
+10 -10
View File
@@ -6,7 +6,6 @@ import { eventManager } from '$lib/managers/event-manager.svelte';
import AssetAddToAlbumModal from '$lib/modals/AssetAddToAlbumModal.svelte';
import AssetTagModal from '$lib/modals/AssetTagModal.svelte';
import SharedLinkCreateModal from '$lib/modals/SharedLinkCreateModal.svelte';
import { user as authUser, preferences } from '$lib/stores/user.store';
import { getAssetMediaUrl, getSharedLink, sleep } from '$lib/utils';
import { downloadUrl } from '$lib/utils/asset-utils';
import { handleError } from '$lib/utils/handle-error';
@@ -46,7 +45,6 @@ import {
mdiTune,
} from '@mdi/js';
import type { MessageFormatter } from 'svelte-i18n';
import { get } from 'svelte/store';
export const getAssetBulkActions = ($t: MessageFormatter) => {
const ownedAssets = assetMultiSelectManager.ownedAssets;
@@ -95,15 +93,14 @@ export const getAssetBulkActions = ($t: MessageFormatter) => {
export const getAssetActions = ($t: MessageFormatter, asset: AssetResponseDto) => {
const sharedLink = getSharedLink();
const currentAuthUser = get(authUser);
const userPreferences = get(preferences);
const isOwner = !!(currentAuthUser && currentAuthUser.id === asset.ownerId);
const authUser = authManager.authenticated ? authManager.user : undefined;
const isOwner = !!(authUser && authUser.id === asset.ownerId);
const Share: ActionItem = {
title: $t('share'),
icon: mdiShareVariantOutline,
type: $t('assets'),
$if: () => !!(currentAuthUser && !asset.isTrashed && asset.visibility !== AssetVisibility.Locked),
$if: () => !!(authUser && !asset.isTrashed && asset.visibility !== AssetVisibility.Locked),
onAction: () => modalManager.show(SharedLinkCreateModal, { assetIds: [asset.id] }),
};
@@ -112,7 +109,7 @@ export const getAssetActions = ($t: MessageFormatter, asset: AssetResponseDto) =
icon: mdiDownload,
shortcuts: { key: 'd', shift: true },
type: $t('assets'),
$if: () => !!currentAuthUser,
$if: () => !!authUser,
onAction: () => handleDownloadAsset(asset, { edited: true }),
};
@@ -120,7 +117,7 @@ export const getAssetActions = ($t: MessageFormatter, asset: AssetResponseDto) =
title: $t('download_original'),
icon: mdiDownloadBox,
type: $t('assets'),
$if: () => !!currentAuthUser && asset.isEdited,
$if: () => !!authUser && asset.isEdited,
onAction: () => handleDownloadAsset(asset, { edited: false }),
};
@@ -218,7 +215,7 @@ export const getAssetActions = ($t: MessageFormatter, asset: AssetResponseDto) =
title: $t('add_tag'),
icon: mdiTagPlusOutline,
type: $t('assets'),
$if: () => userPreferences.tags.enabled,
$if: () => authManager.authenticated && authManager.preferences.tags.enabled,
onAction: () => modalManager.show(AssetTagModal, { assetIds: [asset.id] }),
shortcuts: { key: 't' },
};
@@ -315,7 +312,10 @@ export const handleDownloadAsset = async (asset: AssetResponseDto, { edited }: {
if (asset.livePhotoVideoId) {
const motionAsset = await getAssetInfo({ ...authManager.params, id: asset.livePhotoVideoId });
if (!isAndroidMotionVideo(motionAsset) || get(preferences)?.download.includeEmbeddedVideos) {
if (
!isAndroidMotionVideo(motionAsset) ||
(authManager.authenticated && authManager.preferences.download.includeEmbeddedVideos)
) {
const motionFilename = motionAsset.originalFileName;
const lastDotIndex = motionFilename.lastIndexOf('.');
const motionDownloadFilename =
+3 -4
View File
@@ -1,11 +1,11 @@
import { goto } from '$app/navigation';
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 PasswordResetSuccessModal from '$lib/modals/PasswordResetSuccessModal.svelte';
import UserDeleteConfirmModal from '$lib/modals/UserDeleteConfirmModal.svelte';
import UserRestoreConfirmModal from '$lib/modals/UserRestoreConfirmModal.svelte';
import { Route } from '$lib/route';
import { user as authUser } from '$lib/stores/user.store';
import type { HeaderButtonActionItem } from '$lib/types';
import { handleError } from '$lib/utils/handle-error';
import { getFormatter } from '$lib/utils/i18n';
@@ -32,7 +32,6 @@ import {
} from '@mdi/js';
import { DateTime } from 'luxon';
import type { MessageFormatter } from 'svelte-i18n';
import { get } from 'svelte/store';
export const getUserAdminsActions = ($t: MessageFormatter) => {
const Create: ActionItem = {
@@ -64,7 +63,7 @@ export const getUserAdminActions = ($t: MessageFormatter, user: UserAdminRespons
title: $t('delete'),
type: $t('command'),
color: 'danger',
$if: () => get(authUser).id !== user.id && !user.deletedAt,
$if: () => authManager.user.id !== user.id && !user.deletedAt,
onAction: () => modalManager.show(UserDeleteConfirmModal, { user }),
shortcuts: { key: 'Backspace' },
shortcutOptions: { ignoreInputFields: true },
@@ -89,7 +88,7 @@ export const getUserAdminActions = ($t: MessageFormatter, user: UserAdminRespons
icon: mdiLockReset,
title: $t('reset_password'),
type: $t('command'),
$if: () => get(authUser).id !== user.id,
$if: () => authManager.user.id !== user.id,
onAction: () => handleResetPasswordUserAdmin(user),
};