feat(server,web): remove external path nonsense and make libraries admin-only (#7237)

* remove external path

* open-api

* make sql

* move library settings to admin panel

* Add documentation

* show external libraries only

* fix library list

* make user library settings look good

* fix test

* fix tests

* fix tests

* can pick user for library

* fix tests

* fix e2e

* chore: make sql

* Use unauth exception

* delete user library list

* cleanup

* fix e2e

* fix await lint

* chore: remove unused code

* chore: cleanup

* revert docs

* fix: is admin stuff

* table alignment

---------

Co-authored-by: Jason Rasmussen <jrasm91@gmail.com>
Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
This commit is contained in:
Jonathan Jogenfors
2024-02-29 19:35:37 +01:00
committed by GitHub
parent 369acc7bea
commit efa6efd200
63 changed files with 783 additions and 1111 deletions
@@ -30,8 +30,6 @@ describe(`Library watcher (e2e)`, () => {
await restoreTempFolder();
await api.authApi.adminSignUp(server);
admin = await api.authApi.adminLogin(server);
await api.userApi.setExternalPath(server, admin.accessToken, admin.userId, '/');
});
afterEach(async () => {
@@ -205,8 +203,6 @@ describe(`Library watcher (e2e)`, () => {
],
});
await api.userApi.setExternalPath(server, admin.accessToken, admin.userId, '/');
await fs.mkdir(`${IMMICH_TEST_ASSET_TEMP_PATH}/dir1`, { recursive: true });
await fs.mkdir(`${IMMICH_TEST_ASSET_TEMP_PATH}/dir2`, { recursive: true });
await fs.mkdir(`${IMMICH_TEST_ASSET_TEMP_PATH}/dir3`, { recursive: true });
+1 -109
View File
@@ -40,8 +40,6 @@ describe(`${LibraryController.name} (e2e)`, () => {
type: LibraryType.EXTERNAL,
importPaths: [`${IMMICH_TEST_ASSET_PATH}/albums/nature`],
});
await api.userApi.setExternalPath(server, admin.accessToken, admin.userId, '/');
await api.libraryApi.scanLibrary(server, admin.accessToken, library.id);
const assets = await api.assetApi.getAllAssets(server, admin.accessToken);
@@ -79,8 +77,6 @@ describe(`${LibraryController.name} (e2e)`, () => {
type: LibraryType.EXTERNAL,
importPaths: [`${IMMICH_TEST_ASSET_PATH}/albums/nature`],
});
await api.userApi.setExternalPath(server, admin.accessToken, admin.userId, '/');
await api.libraryApi.scanLibrary(server, admin.accessToken, library.id);
const assets = await api.assetApi.getAllAssets(server, admin.accessToken);
@@ -118,16 +114,12 @@ describe(`${LibraryController.name} (e2e)`, () => {
});
it('should scan external library with exclusion pattern', async () => {
await api.userApi.setExternalPath(server, admin.accessToken, admin.userId, '/not/a/real/path');
const library = await api.libraryApi.create(server, admin.accessToken, {
type: LibraryType.EXTERNAL,
importPaths: [`${IMMICH_TEST_ASSET_PATH}/albums/nature`],
exclusionPatterns: ['**/el_corcal*'],
});
await api.userApi.setExternalPath(server, admin.accessToken, admin.userId, '/');
await api.libraryApi.scanLibrary(server, admin.accessToken, library.id);
const assets = await api.assetApi.getAllAssets(server, admin.accessToken);
@@ -163,7 +155,6 @@ describe(`${LibraryController.name} (e2e)`, () => {
type: LibraryType.EXTERNAL,
importPaths: [`${IMMICH_TEST_ASSET_TEMP_PATH}`],
});
await api.userApi.setExternalPath(server, admin.accessToken, admin.userId, '/');
await api.libraryApi.scanLibrary(server, admin.accessToken, library.id);
@@ -190,39 +181,11 @@ describe(`${LibraryController.name} (e2e)`, () => {
);
});
it('should offline files outside of changed external path', async () => {
const library = await api.libraryApi.create(server, admin.accessToken, {
type: LibraryType.EXTERNAL,
importPaths: [`${IMMICH_TEST_ASSET_PATH}/albums/nature`],
});
await api.userApi.setExternalPath(server, admin.accessToken, admin.userId, '/');
await api.libraryApi.scanLibrary(server, admin.accessToken, library.id);
await api.userApi.setExternalPath(server, admin.accessToken, admin.userId, '/some/other/path');
await api.libraryApi.scanLibrary(server, admin.accessToken, library.id);
const assets = await api.assetApi.getAllAssets(server, admin.accessToken);
expect(assets).toEqual(
expect.arrayContaining([
expect.objectContaining({
isOffline: true,
originalFileName: 'el_torcal_rocks',
}),
expect.objectContaining({
isOffline: true,
originalFileName: 'tanners_ridge',
}),
]),
);
});
it('should scan new files', async () => {
const library = await api.libraryApi.create(server, admin.accessToken, {
type: LibraryType.EXTERNAL,
importPaths: [`${IMMICH_TEST_ASSET_TEMP_PATH}`],
});
await api.userApi.setExternalPath(server, admin.accessToken, admin.userId, '/');
await fs.promises.cp(
`${IMMICH_TEST_ASSET_PATH}/albums/nature/silver_fir.jpg`,
@@ -258,7 +221,6 @@ describe(`${LibraryController.name} (e2e)`, () => {
type: LibraryType.EXTERNAL,
importPaths: [`${IMMICH_TEST_ASSET_TEMP_PATH}`],
});
await api.userApi.setExternalPath(server, admin.accessToken, admin.userId, '/');
await fs.promises.cp(
`${IMMICH_TEST_ASSET_PATH}/albums/nature/el_torcal_rocks.jpg`,
@@ -305,7 +267,6 @@ describe(`${LibraryController.name} (e2e)`, () => {
type: LibraryType.EXTERNAL,
importPaths: [`${IMMICH_TEST_ASSET_TEMP_PATH}`],
});
await api.userApi.setExternalPath(server, admin.accessToken, admin.userId, '/');
await fs.promises.cp(
`${IMMICH_TEST_ASSET_PATH}/albums/nature/el_torcal_rocks.jpg`,
@@ -345,7 +306,6 @@ describe(`${LibraryController.name} (e2e)`, () => {
type: LibraryType.EXTERNAL,
importPaths: [`${IMMICH_TEST_ASSET_TEMP_PATH}`],
});
await api.userApi.setExternalPath(server, admin.accessToken, admin.userId, '/');
await fs.promises.cp(
`${IMMICH_TEST_ASSET_PATH}/albums/nature/el_torcal_rocks.jpg`,
@@ -387,72 +347,6 @@ describe(`${LibraryController.name} (e2e)`, () => {
});
});
describe('External path', () => {
let library: LibraryResponseDto;
beforeEach(async () => {
library = await api.libraryApi.create(server, admin.accessToken, {
type: LibraryType.EXTERNAL,
importPaths: [`${IMMICH_TEST_ASSET_PATH}/albums/nature`],
});
});
it('should not scan assets for user without external path', async () => {
await api.libraryApi.scanLibrary(server, admin.accessToken, library.id);
const assets = await api.assetApi.getAllAssets(server, admin.accessToken);
expect(assets).toEqual([]);
});
it("should not import assets outside of user's external path", async () => {
await api.userApi.setExternalPath(server, admin.accessToken, admin.userId, '/not/a/real/path');
await api.libraryApi.scanLibrary(server, admin.accessToken, library.id);
const assets = await api.assetApi.getAllAssets(server, admin.accessToken);
expect(assets).toEqual([]);
});
it.each([`${IMMICH_TEST_ASSET_PATH}/albums/nature`, `${IMMICH_TEST_ASSET_PATH}/albums/nature/`])(
'should scan external library with external path %s',
async (externalPath: string) => {
await api.userApi.setExternalPath(server, admin.accessToken, admin.userId, externalPath);
await api.libraryApi.scanLibrary(server, admin.accessToken, library.id);
const assets = await api.assetApi.getAllAssets(server, admin.accessToken);
expect(assets).toEqual(
expect.arrayContaining([
expect.objectContaining({
type: AssetType.IMAGE,
originalFileName: 'el_torcal_rocks',
libraryId: library.id,
resized: true,
exifInfo: expect.objectContaining({
exifImageWidth: 512,
exifImageHeight: 341,
latitude: null,
longitude: null,
}),
}),
expect.objectContaining({
type: AssetType.IMAGE,
originalFileName: 'silver_fir',
libraryId: library.id,
resized: true,
exifInfo: expect.objectContaining({
exifImageWidth: 511,
exifImageHeight: 323,
latitude: null,
longitude: null,
}),
}),
]),
);
},
);
});
it('should not scan an upload library', async () => {
const library = await api.libraryApi.create(server, admin.accessToken, {
type: LibraryType.UPLOAD,
@@ -484,7 +378,6 @@ describe(`${LibraryController.name} (e2e)`, () => {
type: LibraryType.EXTERNAL,
importPaths: [`${IMMICH_TEST_ASSET_TEMP_PATH}`],
});
await api.userApi.setExternalPath(server, admin.accessToken, admin.userId, '/');
await api.libraryApi.scanLibrary(server, admin.accessToken, library.id);
@@ -506,12 +399,11 @@ describe(`${LibraryController.name} (e2e)`, () => {
expect(assets).toEqual([]);
});
it('should not remvove online files', async () => {
it('should not remove online files', async () => {
const library = await api.libraryApi.create(server, admin.accessToken, {
type: LibraryType.EXTERNAL,
importPaths: [`${IMMICH_TEST_ASSET_PATH}/albums/nature`],
});
await api.userApi.setExternalPath(server, admin.accessToken, admin.userId, '/');
await api.libraryApi.scanLibrary(server, admin.accessToken, library.id);