Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f7285191bd | |||
| c9a079201a | |||
| be4a783845 | |||
| c30cd3b378 | |||
| 0d3cc28f45 | |||
| f004487be0 | |||
| 21231d53a5 | |||
| a99862120d | |||
| 776023b149 | |||
| 7d4187962a | |||
| a93534fc3c | |||
| cef84f6ced | |||
| a2180a467d | |||
| 1e3dceea4d | |||
| fd4514711f | |||
| 2dd7c13b88 | |||
| 40931b5668 | |||
| 25549b87c9 | |||
| 7ec62f12b5 | |||
| caf76f0713 | |||
| 6778653825 | |||
| c858b43717 | |||
| 6eb1b82541 | |||
| 71b6d8b569 | |||
| 3abfe3c99e | |||
| 171b6bb0a6 | |||
| 78c7ff855d | |||
| 57be9182d4 |
@@ -37,15 +37,15 @@ jobs:
|
|||||||
|
|
||||||
- uses: actions/setup-java@v4
|
- uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
distribution: "zulu"
|
distribution: 'zulu'
|
||||||
java-version: "11.0.21+9"
|
java-version: '17'
|
||||||
cache: "gradle"
|
cache: 'gradle'
|
||||||
|
|
||||||
- name: Setup Flutter SDK
|
- name: Setup Flutter SDK
|
||||||
uses: subosito/flutter-action@v2
|
uses: subosito/flutter-action@v2
|
||||||
with:
|
with:
|
||||||
channel: "stable"
|
channel: 'stable'
|
||||||
flutter-version: "3.19.3"
|
flutter-version: '3.19.3'
|
||||||
cache: true
|
cache: true
|
||||||
|
|
||||||
- name: Create the Keystore
|
- name: Create the Keystore
|
||||||
|
|||||||
@@ -208,7 +208,7 @@ jobs:
|
|||||||
uses: subosito/flutter-action@v2
|
uses: subosito/flutter-action@v2
|
||||||
with:
|
with:
|
||||||
channel: 'stable'
|
channel: 'stable'
|
||||||
flutter-version: '3.16.9'
|
flutter-version: '3.19.3'
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
working-directory: ./mobile
|
working-directory: ./mobile
|
||||||
run: flutter test -j 1
|
run: flutter test -j 1
|
||||||
|
|||||||
Generated
+1
-1
@@ -47,7 +47,7 @@
|
|||||||
},
|
},
|
||||||
"../open-api/typescript-sdk": {
|
"../open-api/typescript-sdk": {
|
||||||
"name": "@immich/sdk",
|
"name": "@immich/sdk",
|
||||||
"version": "1.102.0",
|
"version": "1.102.3",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "GNU Affero General Public License version 3",
|
"license": "GNU Affero General Public License version 3",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
+8
-5
@@ -117,7 +117,7 @@ For example, say you have existing transcodes with the policy "Videos higher tha
|
|||||||
|
|
||||||
No. Our design principle is that the original assets should always be untouched.
|
No. Our design principle is that the original assets should always be untouched.
|
||||||
|
|
||||||
### How can I move all data (photos, persons, albums) from one user to another?
|
### How can I move all data (photos, persons, albums, libraries) from one user to another?
|
||||||
|
|
||||||
This is not officially supported but can be accomplished with some database updates. You can do this on the command line (in the PostgreSQL container using the `psql` command), or you can add, for example, an [Adminer](https://www.adminer.org/) container to the `docker-compose.yml` file so that you can use a web interface.
|
This is not officially supported but can be accomplished with some database updates. You can do this on the command line (in the PostgreSQL container using the `psql` command), or you can add, for example, an [Adminer](https://www.adminer.org/) container to the `docker-compose.yml` file so that you can use a web interface.
|
||||||
|
|
||||||
@@ -128,18 +128,21 @@ This is not officially supported but can be accomplished with some database upda
|
|||||||
|
|
||||||
2. Find the ID of both the 'source' and the 'destination' user (it's the id column in the `users` table)
|
2. Find the ID of both the 'source' and the 'destination' user (it's the id column in the `users` table)
|
||||||
|
|
||||||
3. Three tables need to be updated:
|
3. Four tables need to be updated:
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
// Reassign albums
|
-- reassign albums
|
||||||
UPDATE albums SET "ownerId" = '<destinationId>' WHERE "ownerId" = '<sourceId>';
|
UPDATE albums SET "ownerId" = '<destinationId>' WHERE "ownerId" = '<sourceId>';
|
||||||
|
|
||||||
// Reassign people
|
-- reassign people
|
||||||
UPDATE person SET "ownerId" = '<destinationId>' WHERE "ownerId" = '<sourceId>';
|
UPDATE person SET "ownerId" = '<destinationId>' WHERE "ownerId" = '<sourceId>';
|
||||||
|
|
||||||
// reassign assets
|
-- reassign assets
|
||||||
UPDATE assets SET "ownerId" = '<destinationId>' WHERE "ownerId" = '<sourceId>'
|
UPDATE assets SET "ownerId" = '<destinationId>' WHERE "ownerId" = '<sourceId>'
|
||||||
AND CHECKSUM NOT IN (SELECT CHECKSUM FROM assets WHERE "ownerId" = '<destinationId>');
|
AND CHECKSUM NOT IN (SELECT CHECKSUM FROM assets WHERE "ownerId" = '<destinationId>');
|
||||||
|
|
||||||
|
-- reassign external libraries
|
||||||
|
UPDATE libraries SET "ownerId" = '<destinationId>' WHERE "ownerId" = '<sourceId>';
|
||||||
```
|
```
|
||||||
|
|
||||||
4. There might be left-over assets in the 'source' user's library if they are skipped by the last query because of duplicate checksums. These are probably duplicates anyway, and can probably be removed.
|
4. There might be left-over assets in the 'source' user's library if they are skipped by the last query because of duplicate checksums. These are probably duplicates anyway, and can probably be removed.
|
||||||
|
|||||||
Generated
+3
-3
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "immich-e2e",
|
"name": "immich-e2e",
|
||||||
"version": "1.102.0",
|
"version": "1.102.3",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "immich-e2e",
|
"name": "immich-e2e",
|
||||||
"version": "1.102.0",
|
"version": "1.102.3",
|
||||||
"license": "GNU Affero General Public License version 3",
|
"license": "GNU Affero General Public License version 3",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@immich/cli": "file:../cli",
|
"@immich/cli": "file:../cli",
|
||||||
@@ -81,7 +81,7 @@
|
|||||||
},
|
},
|
||||||
"../open-api/typescript-sdk": {
|
"../open-api/typescript-sdk": {
|
||||||
"name": "@immich/sdk",
|
"name": "@immich/sdk",
|
||||||
"version": "1.102.0",
|
"version": "1.102.3",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "GNU Affero General Public License version 3",
|
"license": "GNU Affero General Public License version 3",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "immich-e2e",
|
"name": "immich-e2e",
|
||||||
"version": "1.102.0",
|
"version": "1.102.3",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|||||||
@@ -572,6 +572,22 @@ describe('/asset', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const tests = [
|
const tests = [
|
||||||
|
{
|
||||||
|
input: 'formats/avif/8bit-sRGB.avif',
|
||||||
|
expected: {
|
||||||
|
type: AssetTypeEnum.Image,
|
||||||
|
originalFileName: '8bit-sRGB.avif',
|
||||||
|
resized: true,
|
||||||
|
exifInfo: {
|
||||||
|
description: '',
|
||||||
|
exifImageHeight: 1080,
|
||||||
|
exifImageWidth: 1617,
|
||||||
|
fileSizeInByte: 862_424,
|
||||||
|
latitude: null,
|
||||||
|
longitude: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
input: 'formats/jpg/el_torcal_rocks.jpg',
|
input: 'formats/jpg/el_torcal_rocks.jpg',
|
||||||
expected: {
|
expected: {
|
||||||
@@ -596,6 +612,22 @@ describe('/asset', () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
input: 'formats/jxl/8bit-sRGB.jxl',
|
||||||
|
expected: {
|
||||||
|
type: AssetTypeEnum.Image,
|
||||||
|
originalFileName: '8bit-sRGB.jxl',
|
||||||
|
resized: true,
|
||||||
|
exifInfo: {
|
||||||
|
description: '',
|
||||||
|
exifImageHeight: 1080,
|
||||||
|
exifImageWidth: 1440,
|
||||||
|
fileSizeInByte: 1_780_777,
|
||||||
|
latitude: null,
|
||||||
|
longitude: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
input: 'formats/heic/IMG_2682.heic',
|
input: 'formats/heic/IMG_2682.heic',
|
||||||
expected: {
|
expected: {
|
||||||
@@ -681,6 +713,80 @@ describe('/asset', () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
input: 'formats/raw/Panasonic/DMC-GH4/4_3.rw2',
|
||||||
|
expected: {
|
||||||
|
type: AssetTypeEnum.Image,
|
||||||
|
originalFileName: '4_3.rw2',
|
||||||
|
resized: true,
|
||||||
|
fileCreatedAt: '2018-05-10T08:42:37.842Z',
|
||||||
|
exifInfo: {
|
||||||
|
make: 'Panasonic',
|
||||||
|
model: 'DMC-GH4',
|
||||||
|
exifImageHeight: 3456,
|
||||||
|
exifImageWidth: 4608,
|
||||||
|
exposureTime: '1/100',
|
||||||
|
fNumber: 3.2,
|
||||||
|
focalLength: 35,
|
||||||
|
iso: 400,
|
||||||
|
fileSizeInByte: 19_587_072,
|
||||||
|
dateTimeOriginal: '2018-05-10T08:42:37.842Z',
|
||||||
|
latitude: null,
|
||||||
|
longitude: null,
|
||||||
|
orientation: '1',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: 'formats/raw/Sony/ILCE-6300/12bit-compressed-(3_2).arw',
|
||||||
|
expected: {
|
||||||
|
type: AssetTypeEnum.Image,
|
||||||
|
originalFileName: '12bit-compressed-(3_2).arw',
|
||||||
|
resized: true,
|
||||||
|
fileCreatedAt: '2016-09-27T10:51:44.000Z',
|
||||||
|
exifInfo: {
|
||||||
|
make: 'SONY',
|
||||||
|
model: 'ILCE-6300',
|
||||||
|
exifImageHeight: 4024,
|
||||||
|
exifImageWidth: 6048,
|
||||||
|
exposureTime: '1/320',
|
||||||
|
fNumber: 8,
|
||||||
|
focalLength: 97,
|
||||||
|
iso: 100,
|
||||||
|
lensModel: 'E PZ 18-105mm F4 G OSS',
|
||||||
|
fileSizeInByte: 25_001_984,
|
||||||
|
dateTimeOriginal: '2016-09-27T10:51:44.000Z',
|
||||||
|
latitude: null,
|
||||||
|
longitude: null,
|
||||||
|
orientation: '1',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: 'formats/raw/Sony/ILCE-7M2/14bit-uncompressed-(3_2).arw',
|
||||||
|
expected: {
|
||||||
|
type: AssetTypeEnum.Image,
|
||||||
|
originalFileName: '14bit-uncompressed-(3_2).arw',
|
||||||
|
resized: true,
|
||||||
|
fileCreatedAt: '2016-01-08T15:08:01.000Z',
|
||||||
|
exifInfo: {
|
||||||
|
make: 'SONY',
|
||||||
|
model: 'ILCE-7M2',
|
||||||
|
exifImageHeight: 4024,
|
||||||
|
exifImageWidth: 6048,
|
||||||
|
exposureTime: '1.3',
|
||||||
|
fNumber: 22,
|
||||||
|
focalLength: 25,
|
||||||
|
iso: 100,
|
||||||
|
lensModel: 'E 25mm F2',
|
||||||
|
fileSizeInByte: 49_512_448,
|
||||||
|
dateTimeOriginal: '2016-01-08T15:08:01.000Z',
|
||||||
|
latitude: null,
|
||||||
|
longitude: null,
|
||||||
|
orientation: '1',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
for (const { input, expected } of tests) {
|
for (const { input, expected } of tests) {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import {
|
|||||||
} from '@immich/sdk';
|
} from '@immich/sdk';
|
||||||
import { cpSync, existsSync } from 'node:fs';
|
import { cpSync, existsSync } from 'node:fs';
|
||||||
import { Socket } from 'socket.io-client';
|
import { Socket } from 'socket.io-client';
|
||||||
import { userDto, uuidDto } from 'src/fixtures';
|
import { createUserDto, uuidDto } from 'src/fixtures';
|
||||||
import { errorDto } from 'src/responses';
|
import { errorDto } from 'src/responses';
|
||||||
import { app, asBearerAuth, testAssetDir, testAssetDirInternal, utils } from 'src/utils';
|
import { app, asBearerAuth, testAssetDir, testAssetDirInternal, utils } from 'src/utils';
|
||||||
import request from 'supertest';
|
import request from 'supertest';
|
||||||
@@ -18,7 +18,7 @@ import { afterAll, beforeAll, beforeEach, describe, expect, it } from 'vitest';
|
|||||||
const scan = async (accessToken: string, id: string, dto: ScanLibraryDto = {}) =>
|
const scan = async (accessToken: string, id: string, dto: ScanLibraryDto = {}) =>
|
||||||
scanLibrary({ id, scanLibraryDto: dto }, { headers: asBearerAuth(accessToken) });
|
scanLibrary({ id, scanLibraryDto: dto }, { headers: asBearerAuth(accessToken) });
|
||||||
|
|
||||||
describe('/library', () => {
|
describe.skip('/library', () => {
|
||||||
let admin: LoginResponseDto;
|
let admin: LoginResponseDto;
|
||||||
let user: LoginResponseDto;
|
let user: LoginResponseDto;
|
||||||
let library: LibraryResponseDto;
|
let library: LibraryResponseDto;
|
||||||
@@ -28,7 +28,7 @@ describe('/library', () => {
|
|||||||
await utils.resetDatabase();
|
await utils.resetDatabase();
|
||||||
admin = await utils.adminSetup();
|
admin = await utils.adminSetup();
|
||||||
await utils.resetAdminConfig(admin.accessToken);
|
await utils.resetAdminConfig(admin.accessToken);
|
||||||
user = await utils.userSetup(admin.accessToken, userDto.user1);
|
user = await utils.userSetup(admin.accessToken, createUserDto.user1);
|
||||||
library = await utils.createLibrary(admin.accessToken, { ownerId: admin.userId, type: LibraryType.External });
|
library = await utils.createLibrary(admin.accessToken, { ownerId: admin.userId, type: LibraryType.External });
|
||||||
websocket = await utils.connectWebsocket(admin.accessToken);
|
websocket = await utils.connectWebsocket(admin.accessToken);
|
||||||
utils.createImageFile(`${testAssetDir}/temp/directoryA/assetA.png`);
|
utils.createImageFile(`${testAssetDir}/temp/directoryA/assetA.png`);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { LoginResponseDto, getServerConfig } from '@immich/sdk';
|
import { LoginResponseDto } from '@immich/sdk';
|
||||||
import { createUserDto } from 'src/fixtures';
|
import { createUserDto } from 'src/fixtures';
|
||||||
import { errorDto } from 'src/responses';
|
import { errorDto } from 'src/responses';
|
||||||
import { app, utils } from 'src/utils';
|
import { app, utils } from 'src/utils';
|
||||||
@@ -162,19 +162,4 @@ describe('/server-info', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('POST /server-info/admin-onboarding', () => {
|
|
||||||
it('should set admin onboarding', async () => {
|
|
||||||
const config = await getServerConfig({});
|
|
||||||
expect(config.isOnboarded).toBe(false);
|
|
||||||
|
|
||||||
const { status } = await request(app)
|
|
||||||
.post('/server-info/admin-onboarding')
|
|
||||||
.set('Authorization', `Bearer ${admin.accessToken}`);
|
|
||||||
expect(status).toBe(204);
|
|
||||||
|
|
||||||
const newConfig = await getServerConfig({});
|
|
||||||
expect(newConfig.isOnboarded).toBe(true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
import { LoginResponseDto, getServerConfig } from '@immich/sdk';
|
||||||
|
import { createUserDto } from 'src/fixtures';
|
||||||
|
import { errorDto } from 'src/responses';
|
||||||
|
import { app, utils } from 'src/utils';
|
||||||
|
import request from 'supertest';
|
||||||
|
import { beforeAll, describe, expect, it } from 'vitest';
|
||||||
|
|
||||||
|
describe('/server-info', () => {
|
||||||
|
let admin: LoginResponseDto;
|
||||||
|
let nonAdmin: LoginResponseDto;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
await utils.resetDatabase();
|
||||||
|
admin = await utils.adminSetup({ onboarding: false });
|
||||||
|
nonAdmin = await utils.userSetup(admin.accessToken, createUserDto.user1);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('POST /system-metadata/admin-onboarding', () => {
|
||||||
|
it('should require authentication', async () => {
|
||||||
|
const { status, body } = await request(app).post('/system-metadata/admin-onboarding').send({ isOnboarded: true });
|
||||||
|
expect(status).toBe(401);
|
||||||
|
expect(body).toEqual(errorDto.unauthorized);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should only work for admins', async () => {
|
||||||
|
const { status, body } = await request(app)
|
||||||
|
.post('/system-metadata/admin-onboarding')
|
||||||
|
.set('Authorization', `Bearer ${nonAdmin.accessToken}`)
|
||||||
|
.send({ isOnboarded: true });
|
||||||
|
expect(status).toBe(403);
|
||||||
|
expect(body).toEqual(errorDto.forbidden);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set admin onboarding', async () => {
|
||||||
|
const config = await getServerConfig({});
|
||||||
|
expect(config.isOnboarded).toBe(false);
|
||||||
|
|
||||||
|
const { status } = await request(app)
|
||||||
|
.post('/system-metadata/admin-onboarding')
|
||||||
|
.set('Authorization', `Bearer ${admin.accessToken}`)
|
||||||
|
.send({ isOnboarded: true });
|
||||||
|
expect(status).toBe(204);
|
||||||
|
|
||||||
|
const newConfig = await getServerConfig({});
|
||||||
|
expect(newConfig.isOnboarded).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('GET /system-metadata/reverse-geocoding-state', () => {
|
||||||
|
it('should require authentication', async () => {
|
||||||
|
const { status, body } = await request(app).get('/system-metadata/reverse-geocoding-state');
|
||||||
|
expect(status).toBe(401);
|
||||||
|
expect(body).toEqual(errorDto.unauthorized);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should only work for admins', async () => {
|
||||||
|
const { status, body } = await request(app)
|
||||||
|
.get('/system-metadata/reverse-geocoding-state')
|
||||||
|
.set('Authorization', `Bearer ${nonAdmin.accessToken}`);
|
||||||
|
expect(status).toBe(403);
|
||||||
|
expect(body).toEqual(errorDto.forbidden);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should get the reverse geocoding state', async () => {
|
||||||
|
const { status, body } = await request(app)
|
||||||
|
.get('/system-metadata/reverse-geocoding-state')
|
||||||
|
.set('Authorization', `Bearer ${admin.accessToken}`);
|
||||||
|
|
||||||
|
expect(status).toBe(200);
|
||||||
|
expect(body).toEqual({
|
||||||
|
lastUpdate: expect.any(String),
|
||||||
|
lastImportFileName: 'cities500.txt',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -135,7 +135,7 @@ describe('/user', () => {
|
|||||||
expect(body).toEqual(errorDto.unauthorized);
|
expect(body).toEqual(errorDto.unauthorized);
|
||||||
});
|
});
|
||||||
|
|
||||||
for (const key of Object.keys(createUserDto.user1)) {
|
for (const key of ['email', 'password', 'name', 'permissionPreset']) {
|
||||||
it(`should not allow null ${key}`, async () => {
|
it(`should not allow null ${key}`, async () => {
|
||||||
const { status, body } = await request(app)
|
const { status, body } = await request(app)
|
||||||
.post(`/user`)
|
.post(`/user`)
|
||||||
@@ -146,6 +146,17 @@ describe('/user', () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
it(`should require permissions when using the custom preset `, async () => {
|
||||||
|
const { status, body } = await request(app)
|
||||||
|
.post(`/user`)
|
||||||
|
.set('Authorization', `Bearer ${admin.accessToken}`)
|
||||||
|
.send({ ...createUserDto.user1, permissionPreset: 'custom' });
|
||||||
|
expect(status).toBe(400);
|
||||||
|
expect(body).toEqual(
|
||||||
|
errorDto.badRequest([expect.stringContaining('each value in permissions must be one of the following')]),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should ignore `isAdmin`', async () => {
|
it('should ignore `isAdmin`', async () => {
|
||||||
const { status, body } = await request(app)
|
const { status, body } = await request(app)
|
||||||
.post(`/user`)
|
.post(`/user`)
|
||||||
@@ -154,6 +165,7 @@ describe('/user', () => {
|
|||||||
email: 'user5@immich.cloud',
|
email: 'user5@immich.cloud',
|
||||||
password: 'password123',
|
password: 'password123',
|
||||||
name: 'Immich',
|
name: 'Immich',
|
||||||
|
permissionPreset: 'user',
|
||||||
})
|
})
|
||||||
.set('Authorization', `Bearer ${admin.accessToken}`);
|
.set('Authorization', `Bearer ${admin.accessToken}`);
|
||||||
expect(body).toMatchObject({
|
expect(body).toMatchObject({
|
||||||
@@ -172,6 +184,7 @@ describe('/user', () => {
|
|||||||
password: 'Password123',
|
password: 'Password123',
|
||||||
name: 'No Memories',
|
name: 'No Memories',
|
||||||
memoriesEnabled: false,
|
memoriesEnabled: false,
|
||||||
|
permissionPreset: 'user',
|
||||||
})
|
})
|
||||||
.set('Authorization', `Bearer ${admin.accessToken}`);
|
.set('Authorization', `Bearer ${admin.accessToken}`);
|
||||||
expect(body).toMatchObject({
|
expect(body).toMatchObject({
|
||||||
|
|||||||
+7
-1
@@ -1,4 +1,4 @@
|
|||||||
import { UserAvatarColor } from '@immich/sdk';
|
import { PermissionPreset, UserAvatarColor } from '@immich/sdk';
|
||||||
|
|
||||||
export const uuidDto = {
|
export const uuidDto = {
|
||||||
invalid: 'invalid-uuid',
|
invalid: 'invalid-uuid',
|
||||||
@@ -26,33 +26,39 @@ export const createUserDto = {
|
|||||||
email: `${key}@immich.cloud`,
|
email: `${key}@immich.cloud`,
|
||||||
name: `Generated User ${key}`,
|
name: `Generated User ${key}`,
|
||||||
password: `password-${key}`,
|
password: `password-${key}`,
|
||||||
|
permissionPreset: PermissionPreset.User,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
user1: {
|
user1: {
|
||||||
email: 'user1@immich.cloud',
|
email: 'user1@immich.cloud',
|
||||||
name: 'User 1',
|
name: 'User 1',
|
||||||
password: 'password1',
|
password: 'password1',
|
||||||
|
permissionPreset: PermissionPreset.User,
|
||||||
},
|
},
|
||||||
user2: {
|
user2: {
|
||||||
email: 'user2@immich.cloud',
|
email: 'user2@immich.cloud',
|
||||||
name: 'User 2',
|
name: 'User 2',
|
||||||
password: 'password12',
|
password: 'password12',
|
||||||
|
permissionPreset: PermissionPreset.User,
|
||||||
},
|
},
|
||||||
user3: {
|
user3: {
|
||||||
email: 'user3@immich.cloud',
|
email: 'user3@immich.cloud',
|
||||||
name: 'User 3',
|
name: 'User 3',
|
||||||
|
permissionPreset: PermissionPreset.User,
|
||||||
password: 'password123',
|
password: 'password123',
|
||||||
},
|
},
|
||||||
user4: {
|
user4: {
|
||||||
email: 'user4@immich.cloud',
|
email: 'user4@immich.cloud',
|
||||||
name: 'User 4',
|
name: 'User 4',
|
||||||
password: 'password123',
|
password: 'password123',
|
||||||
|
permissionPreset: PermissionPreset.User,
|
||||||
},
|
},
|
||||||
userQuota: {
|
userQuota: {
|
||||||
email: 'user-quota@immich.cloud',
|
email: 'user-quota@immich.cloud',
|
||||||
name: 'User Quota',
|
name: 'User Quota',
|
||||||
password: 'password-quota',
|
password: 'password-quota',
|
||||||
quotaSizeInBytes: 512,
|
quotaSizeInBytes: 512,
|
||||||
|
permissionPreset: PermissionPreset.User,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -77,6 +77,91 @@ export const signupResponseDto = {
|
|||||||
quotaUsageInBytes: 0,
|
quotaUsageInBytes: 0,
|
||||||
quotaSizeInBytes: null,
|
quotaSizeInBytes: null,
|
||||||
status: 'active',
|
status: 'active',
|
||||||
|
permissions: [
|
||||||
|
'activity.create',
|
||||||
|
'activity.read',
|
||||||
|
'activity.update',
|
||||||
|
'activity.delete',
|
||||||
|
'album.create',
|
||||||
|
'album.read',
|
||||||
|
'album.update',
|
||||||
|
'album.delete',
|
||||||
|
'asset.create',
|
||||||
|
'asset.read',
|
||||||
|
'asset.update',
|
||||||
|
'asset.delete',
|
||||||
|
'apiKey.create',
|
||||||
|
'apiKey.read',
|
||||||
|
'apiKey.update',
|
||||||
|
'apiKey.delete',
|
||||||
|
'authDevice.create',
|
||||||
|
'authDevice.read',
|
||||||
|
'authDevice.update',
|
||||||
|
'authDevice.delete',
|
||||||
|
'face.create',
|
||||||
|
'face.read',
|
||||||
|
'face.update',
|
||||||
|
'face.delete',
|
||||||
|
'library.create',
|
||||||
|
'library.read',
|
||||||
|
'library.update',
|
||||||
|
'library.delete',
|
||||||
|
'memory.create',
|
||||||
|
'memory.read',
|
||||||
|
'memory.update',
|
||||||
|
'memory.delete',
|
||||||
|
'memory.addAsset',
|
||||||
|
'memory.removeAsset',
|
||||||
|
'partner.create',
|
||||||
|
'partner.read',
|
||||||
|
'partner.update',
|
||||||
|
'partner.delete',
|
||||||
|
'person.create',
|
||||||
|
'person.read',
|
||||||
|
'person.update',
|
||||||
|
'person.delete',
|
||||||
|
'report.create',
|
||||||
|
'report.read',
|
||||||
|
'report.update',
|
||||||
|
'report.delete',
|
||||||
|
'sharedLink.create',
|
||||||
|
'sharedLink.read',
|
||||||
|
'sharedLink.update',
|
||||||
|
'sharedLink.delete',
|
||||||
|
'systemConfig.read',
|
||||||
|
'systemConfig.update',
|
||||||
|
'systemConfig.delete',
|
||||||
|
'stack.create',
|
||||||
|
'stack.read',
|
||||||
|
'stack.update',
|
||||||
|
'stack.delete',
|
||||||
|
'tag.create',
|
||||||
|
'tag.read',
|
||||||
|
'tag.update',
|
||||||
|
'tag.delete',
|
||||||
|
'user.create',
|
||||||
|
'user.read',
|
||||||
|
'user.update',
|
||||||
|
'user.delete',
|
||||||
|
'auth.changePassword',
|
||||||
|
'auth.oauth',
|
||||||
|
'album.addAsset',
|
||||||
|
'album.removeAsset',
|
||||||
|
'album.addUser',
|
||||||
|
'album.removeUser',
|
||||||
|
'asset.viewThumb',
|
||||||
|
'asset.viewPreview',
|
||||||
|
'asset.viewOriginal',
|
||||||
|
'asset.upload',
|
||||||
|
'asset.download',
|
||||||
|
'job.read',
|
||||||
|
'job.run',
|
||||||
|
'map.read',
|
||||||
|
'user.readSimple',
|
||||||
|
'user.changePassword',
|
||||||
|
'server.read',
|
||||||
|
'server.setup',
|
||||||
|
],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+5
-2
@@ -24,8 +24,8 @@ import {
|
|||||||
getConfigDefaults,
|
getConfigDefaults,
|
||||||
login,
|
login,
|
||||||
searchMetadata,
|
searchMetadata,
|
||||||
setAdminOnboarding,
|
|
||||||
signUpAdmin,
|
signUpAdmin,
|
||||||
|
updateAdminOnboarding,
|
||||||
updateConfig,
|
updateConfig,
|
||||||
validate,
|
validate,
|
||||||
} from '@immich/sdk';
|
} from '@immich/sdk';
|
||||||
@@ -264,7 +264,10 @@ export const utils = {
|
|||||||
await signUpAdmin({ signUpDto: signupDto.admin });
|
await signUpAdmin({ signUpDto: signupDto.admin });
|
||||||
const response = await login({ loginCredentialDto: loginDto.admin });
|
const response = await login({ loginCredentialDto: loginDto.admin });
|
||||||
if (options.onboarding) {
|
if (options.onboarding) {
|
||||||
await setAdminOnboarding({ headers: asBearerAuth(response.accessToken) });
|
await updateAdminOnboarding(
|
||||||
|
{ adminOnboardingUpdateDto: { isOnboarded: true } },
|
||||||
|
{ headers: asBearerAuth(response.accessToken) },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return response;
|
return response;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "machine-learning"
|
name = "machine-learning"
|
||||||
version = "1.102.0"
|
version = "1.102.3"
|
||||||
description = ""
|
description = ""
|
||||||
authors = ["Hau Tran <alex.tran1502@gmail.com>"]
|
authors = ["Hau Tran <alex.tran1502@gmail.com>"]
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
|
plugins {
|
||||||
|
id "com.android.application"
|
||||||
|
id "kotlin-android"
|
||||||
|
id "dev.flutter.flutter-gradle-plugin"
|
||||||
|
id "kotlin-kapt"
|
||||||
|
}
|
||||||
|
|
||||||
def localProperties = new Properties()
|
def localProperties = new Properties()
|
||||||
def localPropertiesFile = rootProject.file('local.properties')
|
def localPropertiesFile = rootProject.file('local.properties')
|
||||||
if (localPropertiesFile.exists()) {
|
if (localPropertiesFile.exists()) {
|
||||||
localPropertiesFile.withReader('UTF-8') { reader ->
|
localPropertiesFile.withInputStream { localProperties.load(it) }
|
||||||
localProperties.load(reader)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def flutterRoot = localProperties.getProperty('flutter.sdk')
|
|
||||||
if (flutterRoot == null) {
|
|
||||||
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
|
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
|
||||||
@@ -21,18 +21,12 @@ if (flutterVersionName == null) {
|
|||||||
flutterVersionName = '1.0'
|
flutterVersionName = '1.0'
|
||||||
}
|
}
|
||||||
|
|
||||||
apply plugin: 'com.android.application'
|
|
||||||
apply plugin: 'kotlin-android'
|
|
||||||
apply plugin: 'kotlin-kapt'
|
|
||||||
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
|
||||||
|
|
||||||
def keystoreProperties = new Properties()
|
def keystoreProperties = new Properties()
|
||||||
def keystorePropertiesFile = rootProject.file('key.properties')
|
def keystorePropertiesFile = rootProject.file('key.properties')
|
||||||
if (keystorePropertiesFile.exists()) {
|
if (keystorePropertiesFile.exists()) {
|
||||||
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
|
keystorePropertiesFile.withInputStream { keystoreProperties.load(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 34
|
compileSdkVersion 34
|
||||||
|
|
||||||
@@ -50,7 +44,6 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
|
||||||
applicationId "app.alextran.immich"
|
applicationId "app.alextran.immich"
|
||||||
minSdkVersion 26
|
minSdkVersion 26
|
||||||
targetSdkVersion 33
|
targetSdkVersion 33
|
||||||
@@ -88,6 +81,13 @@ flutter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
def kotlin_version = '1.9.23'
|
||||||
|
def kotlin_coroutines_version = '1.8.0'
|
||||||
|
def work_version = '2.9.0'
|
||||||
|
def concurrent_version = '1.1.0'
|
||||||
|
def guava_version = '33.1.0-android'
|
||||||
|
def glide_version = '4.16.0'
|
||||||
|
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"
|
||||||
implementation "androidx.work:work-runtime-ktx:$work_version"
|
implementation "androidx.work:work-runtime-ktx:$work_version"
|
||||||
|
|||||||
@@ -276,7 +276,7 @@ class BackupWorker(ctx: Context, params: WorkerParameters) : ListenableWorker(ct
|
|||||||
private const val NOTIFICATION_CHANNEL_ERROR_ID = "immich/backgroundServiceError"
|
private const val NOTIFICATION_CHANNEL_ERROR_ID = "immich/backgroundServiceError"
|
||||||
private const val NOTIFICATION_DEFAULT_TITLE = "Immich"
|
private const val NOTIFICATION_DEFAULT_TITLE = "Immich"
|
||||||
private const val NOTIFICATION_ID = 1
|
private const val NOTIFICATION_ID = 1
|
||||||
private const val NOTIFICATION_ERROR_ID = 2
|
private const val NOTIFICATION_ERROR_ID = 2
|
||||||
private const val NOTIFICATION_DETAIL_ID = 3
|
private const val NOTIFICATION_DETAIL_ID = 3
|
||||||
private const val ONE_MINUTE = 60000L
|
private const val ONE_MINUTE = 60000L
|
||||||
|
|
||||||
@@ -304,7 +304,7 @@ class BackupWorker(ctx: Context, params: WorkerParameters) : ListenableWorker(ct
|
|||||||
val workInfoList = workInfoFuture.get(1000, TimeUnit.MILLISECONDS)
|
val workInfoList = workInfoFuture.get(1000, TimeUnit.MILLISECONDS)
|
||||||
if (workInfoList != null) {
|
if (workInfoList != null) {
|
||||||
for (workInfo in workInfoList) {
|
for (workInfo in workInfoList) {
|
||||||
if (workInfo.getState() == WorkInfo.State.ENQUEUED) {
|
if (workInfo.state == WorkInfo.State.ENQUEUED) {
|
||||||
val workRequest = buildWorkRequest(requireWifi, requireCharging)
|
val workRequest = buildWorkRequest(requireWifi, requireCharging)
|
||||||
wm.enqueueUniqueWork(TASK_NAME_BACKUP, ExistingWorkPolicy.REPLACE, workRequest)
|
wm.enqueueUniqueWork(TASK_NAME_BACKUP, ExistingWorkPolicy.REPLACE, workRequest)
|
||||||
Log.d(TAG, "updateBackupWorker updated BackupWorker constraints")
|
Log.d(TAG, "updateBackupWorker updated BackupWorker constraints")
|
||||||
@@ -346,7 +346,7 @@ class BackupWorker(ctx: Context, params: WorkerParameters) : ListenableWorker(ct
|
|||||||
.setRequiresBatteryNotLow(true)
|
.setRequiresBatteryNotLow(true)
|
||||||
.setRequiresCharging(requireCharging)
|
.setRequiresCharging(requireCharging)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
val work = OneTimeWorkRequest.Builder(BackupWorker::class.java)
|
val work = OneTimeWorkRequest.Builder(BackupWorker::class.java)
|
||||||
.setConstraints(constraints)
|
.setConstraints(constraints)
|
||||||
.setBackoffCriteria(BackoffPolicy.EXPONENTIAL, ONE_MINUTE, TimeUnit.MILLISECONDS)
|
.setBackoffCriteria(BackoffPolicy.EXPONENTIAL, ONE_MINUTE, TimeUnit.MILLISECONDS)
|
||||||
@@ -359,4 +359,4 @@ class BackupWorker(ctx: Context, params: WorkerParameters) : ListenableWorker(ct
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private const val TAG = "BackupWorker"
|
private const val TAG = "BackupWorker"
|
||||||
|
|||||||
@@ -1,21 +1,3 @@
|
|||||||
buildscript {
|
|
||||||
ext.kotlin_version = '1.8.20'
|
|
||||||
ext.kotlin_coroutines_version = '1.7.1'
|
|
||||||
ext.work_version = '2.7.1'
|
|
||||||
ext.concurrent_version = '1.1.0'
|
|
||||||
ext.guava_version = '33.0.0-android'
|
|
||||||
ext.glide_version = '4.14.2'
|
|
||||||
repositories {
|
|
||||||
google()
|
|
||||||
mavenCentral()
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
classpath 'com.android.tools.build:gradle:7.4.2'
|
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
@@ -34,3 +16,7 @@ subprojects {
|
|||||||
tasks.register("clean", Delete) {
|
tasks.register("clean", Delete) {
|
||||||
delete rootProject.buildDir
|
delete rootProject.buildDir
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tasks.named('wrapper') {
|
||||||
|
distributionType = Wrapper.DistributionType.ALL
|
||||||
|
}
|
||||||
@@ -35,8 +35,8 @@ platform :android do
|
|||||||
task: 'bundle',
|
task: 'bundle',
|
||||||
build_type: 'Release',
|
build_type: 'Release',
|
||||||
properties: {
|
properties: {
|
||||||
"android.injected.version.code" => 132,
|
"android.injected.version.code" => 136,
|
||||||
"android.injected.version.name" => "1.102.0",
|
"android.injected.version.name" => "1.102.3",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
upload_to_play_store(skip_upload_apk: true, skip_upload_images: true, skip_upload_screenshots: true, aab: '../build/app/outputs/bundle/release/app-release.aab')
|
upload_to_play_store(skip_upload_apk: true, skip_upload_images: true, skip_upload_screenshots: true, aab: '../build/app/outputs/bundle/release/app-release.aab')
|
||||||
|
|||||||
@@ -5,17 +5,17 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000219">
|
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000261">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="1: bundleRelease" time="67.515419">
|
<testcase classname="fastlane.lanes" name="1: bundleRelease" time="32.48099">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="2: upload_to_play_store" time="35.431743">
|
<testcase classname="fastlane.lanes" name="2: upload_to_play_store" time="30.236974">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|||||||
+3
-2
@@ -1,6 +1,7 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.3-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.4-all.zip
|
||||||
distributionSha256Sum=6001aba9b2204d26fa25a5800bb9382cf3ee01ccb78fe77317b2872336eb2f80
|
distributionSha256Sum=fe696c020f241a5f69c30f763c5a7f38eec54b490db19cd2b0962dda420d7d12
|
||||||
@@ -1,11 +1,26 @@
|
|||||||
include ':app'
|
pluginManagement {
|
||||||
|
def flutterSdkPath = {
|
||||||
|
def properties = new Properties()
|
||||||
|
file("local.properties").withInputStream { properties.load(it) }
|
||||||
|
def flutterSdkPath = properties.getProperty("flutter.sdk")
|
||||||
|
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
|
||||||
|
return flutterSdkPath
|
||||||
|
}()
|
||||||
|
|
||||||
def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
|
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
|
||||||
def properties = new Properties()
|
|
||||||
|
|
||||||
assert localPropertiesFile.exists()
|
repositories {
|
||||||
localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
|
google()
|
||||||
|
mavenCentral()
|
||||||
|
gradlePluginPortal()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def flutterSdkPath = properties.getProperty("flutter.sdk")
|
plugins {
|
||||||
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
|
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
|
||||||
apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
|
id "com.android.application" version "7.4.2" apply false
|
||||||
|
id "org.jetbrains.kotlin.android" version "1.9.23" apply false
|
||||||
|
id "org.jetbrains.kotlin.kapt" version "1.9.23" apply false
|
||||||
|
}
|
||||||
|
|
||||||
|
include ":app"
|
||||||
|
|||||||
@@ -296,6 +296,7 @@
|
|||||||
"motion_photos_page_title": "Motion Photos",
|
"motion_photos_page_title": "Motion Photos",
|
||||||
"multiselect_grid_edit_date_time_err_read_only": "Cannot edit date of read only asset(s), skipping",
|
"multiselect_grid_edit_date_time_err_read_only": "Cannot edit date of read only asset(s), skipping",
|
||||||
"multiselect_grid_edit_gps_err_read_only": "Cannot edit location of read only asset(s), skipping",
|
"multiselect_grid_edit_gps_err_read_only": "Cannot edit location of read only asset(s), skipping",
|
||||||
|
"no_assets_to_show" : "No assets to show",
|
||||||
"notification_permission_dialog_cancel": "Cancel",
|
"notification_permission_dialog_cancel": "Cancel",
|
||||||
"notification_permission_dialog_content": "To enable notifications, go to Settings and select allow.",
|
"notification_permission_dialog_content": "To enable notifications, go to Settings and select allow.",
|
||||||
"notification_permission_dialog_settings": "Settings",
|
"notification_permission_dialog_settings": "Settings",
|
||||||
|
|||||||
@@ -296,6 +296,7 @@
|
|||||||
"motion_photos_page_title": "Photos avec mouvement",
|
"motion_photos_page_title": "Photos avec mouvement",
|
||||||
"multiselect_grid_edit_date_time_err_read_only": "Impossible de modifier la date d'un élément d'actif en lecture seule.",
|
"multiselect_grid_edit_date_time_err_read_only": "Impossible de modifier la date d'un élément d'actif en lecture seule.",
|
||||||
"multiselect_grid_edit_gps_err_read_only": "Impossible de modifier l'emplacement d'un élément en lecture seule.",
|
"multiselect_grid_edit_gps_err_read_only": "Impossible de modifier l'emplacement d'un élément en lecture seule.",
|
||||||
|
"no_assets_to_show" : "Aucun élément à afficher",
|
||||||
"notification_permission_dialog_cancel": "Annuler",
|
"notification_permission_dialog_cancel": "Annuler",
|
||||||
"notification_permission_dialog_content": "Pour activer les notifications, allez dans Paramètres et sélectionnez Autoriser.",
|
"notification_permission_dialog_content": "Pour activer les notifications, allez dans Paramètres et sélectionnez Autoriser.",
|
||||||
"notification_permission_dialog_settings": "Paramètres",
|
"notification_permission_dialog_settings": "Paramètres",
|
||||||
@@ -509,5 +510,7 @@
|
|||||||
"version_announcement_overlay_title": "Nouvelle version serveur disponible \uD83C\uDF89",
|
"version_announcement_overlay_title": "Nouvelle version serveur disponible \uD83C\uDF89",
|
||||||
"viewer_remove_from_stack": "Retirer de la pile",
|
"viewer_remove_from_stack": "Retirer de la pile",
|
||||||
"viewer_stack_use_as_main_asset": "Utiliser comme élément principal",
|
"viewer_stack_use_as_main_asset": "Utiliser comme élément principal",
|
||||||
"viewer_unstack": "Désempiler"
|
"viewer_unstack": "Désempiler",
|
||||||
|
"haptic_feedback_title": "Retour haptique",
|
||||||
|
"haptic_feedback_switch": "Activer le retour haptique"
|
||||||
}
|
}
|
||||||
@@ -383,7 +383,7 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = Runner/RunnerProfile.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/RunnerProfile.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 147;
|
CURRENT_PROJECT_VERSION = 150;
|
||||||
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
@@ -525,7 +525,7 @@
|
|||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 147;
|
CURRENT_PROJECT_VERSION = 150;
|
||||||
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
@@ -553,7 +553,7 @@
|
|||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 147;
|
CURRENT_PROJECT_VERSION = 150;
|
||||||
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
|||||||
@@ -58,11 +58,11 @@
|
|||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>1.101.0</string>
|
<string>1.102.2</string>
|
||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>147</string>
|
<string>150</string>
|
||||||
<key>FLTEnableImpeller</key>
|
<key>FLTEnableImpeller</key>
|
||||||
<true />
|
<true />
|
||||||
<key>ITSAppUsesNonExemptEncryption</key>
|
<key>ITSAppUsesNonExemptEncryption</key>
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ platform :ios do
|
|||||||
desc "iOS Beta"
|
desc "iOS Beta"
|
||||||
lane :beta do
|
lane :beta do
|
||||||
increment_version_number(
|
increment_version_number(
|
||||||
version_number: "1.102.0"
|
version_number: "1.102.3"
|
||||||
)
|
)
|
||||||
increment_build_number(
|
increment_build_number(
|
||||||
build_number: latest_testflight_build_number + 1,
|
build_number: latest_testflight_build_number + 1,
|
||||||
|
|||||||
@@ -5,32 +5,32 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000242">
|
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000231">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="1: increment_version_number" time="0.761829">
|
<testcase classname="fastlane.lanes" name="1: increment_version_number" time="0.155919">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="2: latest_testflight_build_number" time="4.47461">
|
<testcase classname="fastlane.lanes" name="2: latest_testflight_build_number" time="4.252784">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="3: increment_build_number" time="0.179512">
|
<testcase classname="fastlane.lanes" name="3: increment_build_number" time="0.210502">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="4: build_app" time="165.636347">
|
<testcase classname="fastlane.lanes" name="4: build_app" time="175.813647">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="5: upload_to_testflight" time="77.651963">
|
<testcase classname="fastlane.lanes" name="5: upload_to_testflight" time="73.512517">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ class MultiselectGrid extends HookConsumerWidget {
|
|||||||
const Center(child: ImmichLoadingIndicator());
|
const Center(child: ImmichLoadingIndicator());
|
||||||
|
|
||||||
Widget buildEmptyIndicator() =>
|
Widget buildEmptyIndicator() =>
|
||||||
emptyIndicator ?? const Center(child: Text("No assets to show"));
|
emptyIndicator ?? Center(child: const Text("no_assets_to_show").tr());
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ class SplashScreenPage extends HookConsumerWidget {
|
|||||||
void performLoggingIn() async {
|
void performLoggingIn() async {
|
||||||
bool isSuccess = false;
|
bool isSuccess = false;
|
||||||
bool deviceIsOffline = false;
|
bool deviceIsOffline = false;
|
||||||
|
|
||||||
if (accessToken != null && serverUrl != null) {
|
if (accessToken != null && serverUrl != null) {
|
||||||
try {
|
try {
|
||||||
// Resolve API server endpoint from user provided serverUrl
|
// Resolve API server endpoint from user provided serverUrl
|
||||||
@@ -51,11 +50,15 @@ class SplashScreenPage extends HookConsumerWidget {
|
|||||||
offlineLogin: deviceIsOffline,
|
offlineLogin: deviceIsOffline,
|
||||||
);
|
);
|
||||||
} catch (error, stackTrace) {
|
} catch (error, stackTrace) {
|
||||||
|
ref.read(authenticationProvider.notifier).logout();
|
||||||
|
|
||||||
log.severe(
|
log.severe(
|
||||||
'Cannot set success login info',
|
'Cannot set success login info',
|
||||||
error,
|
error,
|
||||||
stackTrace,
|
stackTrace,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
context.pushRoute(const LoginRoute());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,11 +76,6 @@ class SplashScreenPage extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
context.replaceRoute(const TabControllerRoute());
|
context.replaceRoute(const TabControllerRoute());
|
||||||
} else {
|
} else {
|
||||||
log.severe(
|
|
||||||
'Unable to login through offline or online methods - logging out completely',
|
|
||||||
);
|
|
||||||
|
|
||||||
ref.read(authenticationProvider.notifier).logout();
|
|
||||||
// User was unable to login through either offline or online methods
|
// User was unable to login through either offline or online methods
|
||||||
context.replaceRoute(const LoginRoute());
|
context.replaceRoute(const LoginRoute());
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+12
@@ -13,6 +13,7 @@ doc/ActivityCreateDto.md
|
|||||||
doc/ActivityResponseDto.md
|
doc/ActivityResponseDto.md
|
||||||
doc/ActivityStatisticsResponseDto.md
|
doc/ActivityStatisticsResponseDto.md
|
||||||
doc/AddUsersDto.md
|
doc/AddUsersDto.md
|
||||||
|
doc/AdminOnboardingUpdateDto.md
|
||||||
doc/AlbumApi.md
|
doc/AlbumApi.md
|
||||||
doc/AlbumCountResponseDto.md
|
doc/AlbumCountResponseDto.md
|
||||||
doc/AlbumResponseDto.md
|
doc/AlbumResponseDto.md
|
||||||
@@ -69,6 +70,7 @@ doc/FaceApi.md
|
|||||||
doc/FaceDto.md
|
doc/FaceDto.md
|
||||||
doc/FileChecksumDto.md
|
doc/FileChecksumDto.md
|
||||||
doc/FileChecksumResponseDto.md
|
doc/FileChecksumResponseDto.md
|
||||||
|
doc/FileReportApi.md
|
||||||
doc/FileReportDto.md
|
doc/FileReportDto.md
|
||||||
doc/FileReportFixDto.md
|
doc/FileReportFixDto.md
|
||||||
doc/FileReportItemDto.md
|
doc/FileReportItemDto.md
|
||||||
@@ -122,6 +124,7 @@ doc/QueueStatusDto.md
|
|||||||
doc/ReactionLevel.md
|
doc/ReactionLevel.md
|
||||||
doc/ReactionType.md
|
doc/ReactionType.md
|
||||||
doc/RecognitionConfig.md
|
doc/RecognitionConfig.md
|
||||||
|
doc/ReverseGeocodingStateResponseDto.md
|
||||||
doc/ScanLibraryDto.md
|
doc/ScanLibraryDto.md
|
||||||
doc/SearchAlbumResponseDto.md
|
doc/SearchAlbumResponseDto.md
|
||||||
doc/SearchApi.md
|
doc/SearchApi.md
|
||||||
@@ -173,6 +176,7 @@ doc/SystemConfigTemplateStorageOptionDto.md
|
|||||||
doc/SystemConfigThemeDto.md
|
doc/SystemConfigThemeDto.md
|
||||||
doc/SystemConfigTrashDto.md
|
doc/SystemConfigTrashDto.md
|
||||||
doc/SystemConfigUserDto.md
|
doc/SystemConfigUserDto.md
|
||||||
|
doc/SystemMetadataApi.md
|
||||||
doc/TagApi.md
|
doc/TagApi.md
|
||||||
doc/TagResponseDto.md
|
doc/TagResponseDto.md
|
||||||
doc/TagTypeEnum.md
|
doc/TagTypeEnum.md
|
||||||
@@ -212,6 +216,7 @@ lib/api/audit_api.dart
|
|||||||
lib/api/authentication_api.dart
|
lib/api/authentication_api.dart
|
||||||
lib/api/download_api.dart
|
lib/api/download_api.dart
|
||||||
lib/api/face_api.dart
|
lib/api/face_api.dart
|
||||||
|
lib/api/file_report_api.dart
|
||||||
lib/api/job_api.dart
|
lib/api/job_api.dart
|
||||||
lib/api/library_api.dart
|
lib/api/library_api.dart
|
||||||
lib/api/memory_api.dart
|
lib/api/memory_api.dart
|
||||||
@@ -224,6 +229,7 @@ lib/api/sessions_api.dart
|
|||||||
lib/api/shared_link_api.dart
|
lib/api/shared_link_api.dart
|
||||||
lib/api/sync_api.dart
|
lib/api/sync_api.dart
|
||||||
lib/api/system_config_api.dart
|
lib/api/system_config_api.dart
|
||||||
|
lib/api/system_metadata_api.dart
|
||||||
lib/api/tag_api.dart
|
lib/api/tag_api.dart
|
||||||
lib/api/timeline_api.dart
|
lib/api/timeline_api.dart
|
||||||
lib/api/trash_api.dart
|
lib/api/trash_api.dart
|
||||||
@@ -240,6 +246,7 @@ lib/model/activity_create_dto.dart
|
|||||||
lib/model/activity_response_dto.dart
|
lib/model/activity_response_dto.dart
|
||||||
lib/model/activity_statistics_response_dto.dart
|
lib/model/activity_statistics_response_dto.dart
|
||||||
lib/model/add_users_dto.dart
|
lib/model/add_users_dto.dart
|
||||||
|
lib/model/admin_onboarding_update_dto.dart
|
||||||
lib/model/album_count_response_dto.dart
|
lib/model/album_count_response_dto.dart
|
||||||
lib/model/album_response_dto.dart
|
lib/model/album_response_dto.dart
|
||||||
lib/model/all_job_status_response_dto.dart
|
lib/model/all_job_status_response_dto.dart
|
||||||
@@ -341,6 +348,7 @@ lib/model/queue_status_dto.dart
|
|||||||
lib/model/reaction_level.dart
|
lib/model/reaction_level.dart
|
||||||
lib/model/reaction_type.dart
|
lib/model/reaction_type.dart
|
||||||
lib/model/recognition_config.dart
|
lib/model/recognition_config.dart
|
||||||
|
lib/model/reverse_geocoding_state_response_dto.dart
|
||||||
lib/model/scan_library_dto.dart
|
lib/model/scan_library_dto.dart
|
||||||
lib/model/search_album_response_dto.dart
|
lib/model/search_album_response_dto.dart
|
||||||
lib/model/search_asset_response_dto.dart
|
lib/model/search_asset_response_dto.dart
|
||||||
@@ -417,6 +425,7 @@ test/activity_create_dto_test.dart
|
|||||||
test/activity_response_dto_test.dart
|
test/activity_response_dto_test.dart
|
||||||
test/activity_statistics_response_dto_test.dart
|
test/activity_statistics_response_dto_test.dart
|
||||||
test/add_users_dto_test.dart
|
test/add_users_dto_test.dart
|
||||||
|
test/admin_onboarding_update_dto_test.dart
|
||||||
test/album_api_test.dart
|
test/album_api_test.dart
|
||||||
test/album_count_response_dto_test.dart
|
test/album_count_response_dto_test.dart
|
||||||
test/album_response_dto_test.dart
|
test/album_response_dto_test.dart
|
||||||
@@ -478,6 +487,7 @@ test/face_api_test.dart
|
|||||||
test/face_dto_test.dart
|
test/face_dto_test.dart
|
||||||
test/file_checksum_dto_test.dart
|
test/file_checksum_dto_test.dart
|
||||||
test/file_checksum_response_dto_test.dart
|
test/file_checksum_response_dto_test.dart
|
||||||
|
test/file_report_api_test.dart
|
||||||
test/file_report_dto_test.dart
|
test/file_report_dto_test.dart
|
||||||
test/file_report_fix_dto_test.dart
|
test/file_report_fix_dto_test.dart
|
||||||
test/file_report_item_dto_test.dart
|
test/file_report_item_dto_test.dart
|
||||||
@@ -531,6 +541,7 @@ test/queue_status_dto_test.dart
|
|||||||
test/reaction_level_test.dart
|
test/reaction_level_test.dart
|
||||||
test/reaction_type_test.dart
|
test/reaction_type_test.dart
|
||||||
test/recognition_config_test.dart
|
test/recognition_config_test.dart
|
||||||
|
test/reverse_geocoding_state_response_dto_test.dart
|
||||||
test/scan_library_dto_test.dart
|
test/scan_library_dto_test.dart
|
||||||
test/search_album_response_dto_test.dart
|
test/search_album_response_dto_test.dart
|
||||||
test/search_api_test.dart
|
test/search_api_test.dart
|
||||||
@@ -582,6 +593,7 @@ test/system_config_template_storage_option_dto_test.dart
|
|||||||
test/system_config_theme_dto_test.dart
|
test/system_config_theme_dto_test.dart
|
||||||
test/system_config_trash_dto_test.dart
|
test/system_config_trash_dto_test.dart
|
||||||
test/system_config_user_dto_test.dart
|
test/system_config_user_dto_test.dart
|
||||||
|
test/system_metadata_api_test.dart
|
||||||
test/tag_api_test.dart
|
test/tag_api_test.dart
|
||||||
test/tag_response_dto_test.dart
|
test/tag_response_dto_test.dart
|
||||||
test/tag_type_enum_test.dart
|
test/tag_type_enum_test.dart
|
||||||
|
|||||||
Generated
+9
-5
@@ -3,7 +3,7 @@ Immich API
|
|||||||
|
|
||||||
This Dart package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
|
This Dart package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
|
||||||
|
|
||||||
- API version: 1.102.0
|
- API version: 1.102.3
|
||||||
- Build package: org.openapitools.codegen.languages.DartClientCodegen
|
- Build package: org.openapitools.codegen.languages.DartClientCodegen
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
@@ -112,10 +112,7 @@ Class | Method | HTTP request | Description
|
|||||||
*AssetApi* | [**updateAssets**](doc//AssetApi.md#updateassets) | **PUT** /asset |
|
*AssetApi* | [**updateAssets**](doc//AssetApi.md#updateassets) | **PUT** /asset |
|
||||||
*AssetApi* | [**updateStackParent**](doc//AssetApi.md#updatestackparent) | **PUT** /asset/stack/parent |
|
*AssetApi* | [**updateStackParent**](doc//AssetApi.md#updatestackparent) | **PUT** /asset/stack/parent |
|
||||||
*AssetApi* | [**uploadFile**](doc//AssetApi.md#uploadfile) | **POST** /asset/upload |
|
*AssetApi* | [**uploadFile**](doc//AssetApi.md#uploadfile) | **POST** /asset/upload |
|
||||||
*AuditApi* | [**fixAuditFiles**](doc//AuditApi.md#fixauditfiles) | **POST** /audit/file-report/fix |
|
|
||||||
*AuditApi* | [**getAuditDeletes**](doc//AuditApi.md#getauditdeletes) | **GET** /audit/deletes |
|
*AuditApi* | [**getAuditDeletes**](doc//AuditApi.md#getauditdeletes) | **GET** /audit/deletes |
|
||||||
*AuditApi* | [**getAuditFiles**](doc//AuditApi.md#getauditfiles) | **GET** /audit/file-report |
|
|
||||||
*AuditApi* | [**getFileChecksums**](doc//AuditApi.md#getfilechecksums) | **POST** /audit/file-report/checksum |
|
|
||||||
*AuthenticationApi* | [**changePassword**](doc//AuthenticationApi.md#changepassword) | **POST** /auth/change-password |
|
*AuthenticationApi* | [**changePassword**](doc//AuthenticationApi.md#changepassword) | **POST** /auth/change-password |
|
||||||
*AuthenticationApi* | [**login**](doc//AuthenticationApi.md#login) | **POST** /auth/login |
|
*AuthenticationApi* | [**login**](doc//AuthenticationApi.md#login) | **POST** /auth/login |
|
||||||
*AuthenticationApi* | [**logout**](doc//AuthenticationApi.md#logout) | **POST** /auth/logout |
|
*AuthenticationApi* | [**logout**](doc//AuthenticationApi.md#logout) | **POST** /auth/logout |
|
||||||
@@ -126,6 +123,9 @@ Class | Method | HTTP request | Description
|
|||||||
*DownloadApi* | [**getDownloadInfo**](doc//DownloadApi.md#getdownloadinfo) | **POST** /download/info |
|
*DownloadApi* | [**getDownloadInfo**](doc//DownloadApi.md#getdownloadinfo) | **POST** /download/info |
|
||||||
*FaceApi* | [**getFaces**](doc//FaceApi.md#getfaces) | **GET** /face |
|
*FaceApi* | [**getFaces**](doc//FaceApi.md#getfaces) | **GET** /face |
|
||||||
*FaceApi* | [**reassignFacesById**](doc//FaceApi.md#reassignfacesbyid) | **PUT** /face/{id} |
|
*FaceApi* | [**reassignFacesById**](doc//FaceApi.md#reassignfacesbyid) | **PUT** /face/{id} |
|
||||||
|
*FileReportApi* | [**fixAuditFiles**](doc//FileReportApi.md#fixauditfiles) | **POST** /report/fix |
|
||||||
|
*FileReportApi* | [**getAuditFiles**](doc//FileReportApi.md#getauditfiles) | **GET** /report |
|
||||||
|
*FileReportApi* | [**getFileChecksums**](doc//FileReportApi.md#getfilechecksums) | **POST** /report/checksum |
|
||||||
*JobApi* | [**getAllJobsStatus**](doc//JobApi.md#getalljobsstatus) | **GET** /jobs |
|
*JobApi* | [**getAllJobsStatus**](doc//JobApi.md#getalljobsstatus) | **GET** /jobs |
|
||||||
*JobApi* | [**sendJobCommand**](doc//JobApi.md#sendjobcommand) | **PUT** /jobs/{id} |
|
*JobApi* | [**sendJobCommand**](doc//JobApi.md#sendjobcommand) | **PUT** /jobs/{id} |
|
||||||
*LibraryApi* | [**createLibrary**](doc//LibraryApi.md#createlibrary) | **POST** /library |
|
*LibraryApi* | [**createLibrary**](doc//LibraryApi.md#createlibrary) | **POST** /library |
|
||||||
@@ -179,7 +179,6 @@ Class | Method | HTTP request | Description
|
|||||||
*ServerInfoApi* | [**getSupportedMediaTypes**](doc//ServerInfoApi.md#getsupportedmediatypes) | **GET** /server-info/media-types |
|
*ServerInfoApi* | [**getSupportedMediaTypes**](doc//ServerInfoApi.md#getsupportedmediatypes) | **GET** /server-info/media-types |
|
||||||
*ServerInfoApi* | [**getTheme**](doc//ServerInfoApi.md#gettheme) | **GET** /server-info/theme |
|
*ServerInfoApi* | [**getTheme**](doc//ServerInfoApi.md#gettheme) | **GET** /server-info/theme |
|
||||||
*ServerInfoApi* | [**pingServer**](doc//ServerInfoApi.md#pingserver) | **GET** /server-info/ping |
|
*ServerInfoApi* | [**pingServer**](doc//ServerInfoApi.md#pingserver) | **GET** /server-info/ping |
|
||||||
*ServerInfoApi* | [**setAdminOnboarding**](doc//ServerInfoApi.md#setadminonboarding) | **POST** /server-info/admin-onboarding |
|
|
||||||
*SessionsApi* | [**deleteAllSessions**](doc//SessionsApi.md#deleteallsessions) | **DELETE** /sessions |
|
*SessionsApi* | [**deleteAllSessions**](doc//SessionsApi.md#deleteallsessions) | **DELETE** /sessions |
|
||||||
*SessionsApi* | [**deleteSession**](doc//SessionsApi.md#deletesession) | **DELETE** /sessions/{id} |
|
*SessionsApi* | [**deleteSession**](doc//SessionsApi.md#deletesession) | **DELETE** /sessions/{id} |
|
||||||
*SessionsApi* | [**getSessions**](doc//SessionsApi.md#getsessions) | **GET** /sessions |
|
*SessionsApi* | [**getSessions**](doc//SessionsApi.md#getsessions) | **GET** /sessions |
|
||||||
@@ -198,6 +197,9 @@ Class | Method | HTTP request | Description
|
|||||||
*SystemConfigApi* | [**getMapStyle**](doc//SystemConfigApi.md#getmapstyle) | **GET** /system-config/map/style.json |
|
*SystemConfigApi* | [**getMapStyle**](doc//SystemConfigApi.md#getmapstyle) | **GET** /system-config/map/style.json |
|
||||||
*SystemConfigApi* | [**getStorageTemplateOptions**](doc//SystemConfigApi.md#getstoragetemplateoptions) | **GET** /system-config/storage-template-options |
|
*SystemConfigApi* | [**getStorageTemplateOptions**](doc//SystemConfigApi.md#getstoragetemplateoptions) | **GET** /system-config/storage-template-options |
|
||||||
*SystemConfigApi* | [**updateConfig**](doc//SystemConfigApi.md#updateconfig) | **PUT** /system-config |
|
*SystemConfigApi* | [**updateConfig**](doc//SystemConfigApi.md#updateconfig) | **PUT** /system-config |
|
||||||
|
*SystemMetadataApi* | [**getAdminOnboarding**](doc//SystemMetadataApi.md#getadminonboarding) | **GET** /system-metadata/admin-onboarding |
|
||||||
|
*SystemMetadataApi* | [**getReverseGeocodingState**](doc//SystemMetadataApi.md#getreversegeocodingstate) | **GET** /system-metadata/reverse-geocoding-state |
|
||||||
|
*SystemMetadataApi* | [**updateAdminOnboarding**](doc//SystemMetadataApi.md#updateadminonboarding) | **POST** /system-metadata/admin-onboarding |
|
||||||
*TagApi* | [**createTag**](doc//TagApi.md#createtag) | **POST** /tag |
|
*TagApi* | [**createTag**](doc//TagApi.md#createtag) | **POST** /tag |
|
||||||
*TagApi* | [**deleteTag**](doc//TagApi.md#deletetag) | **DELETE** /tag/{id} |
|
*TagApi* | [**deleteTag**](doc//TagApi.md#deletetag) | **DELETE** /tag/{id} |
|
||||||
*TagApi* | [**getAllTags**](doc//TagApi.md#getalltags) | **GET** /tag |
|
*TagApi* | [**getAllTags**](doc//TagApi.md#getalltags) | **GET** /tag |
|
||||||
@@ -233,6 +235,7 @@ Class | Method | HTTP request | Description
|
|||||||
- [ActivityResponseDto](doc//ActivityResponseDto.md)
|
- [ActivityResponseDto](doc//ActivityResponseDto.md)
|
||||||
- [ActivityStatisticsResponseDto](doc//ActivityStatisticsResponseDto.md)
|
- [ActivityStatisticsResponseDto](doc//ActivityStatisticsResponseDto.md)
|
||||||
- [AddUsersDto](doc//AddUsersDto.md)
|
- [AddUsersDto](doc//AddUsersDto.md)
|
||||||
|
- [AdminOnboardingUpdateDto](doc//AdminOnboardingUpdateDto.md)
|
||||||
- [AlbumCountResponseDto](doc//AlbumCountResponseDto.md)
|
- [AlbumCountResponseDto](doc//AlbumCountResponseDto.md)
|
||||||
- [AlbumResponseDto](doc//AlbumResponseDto.md)
|
- [AlbumResponseDto](doc//AlbumResponseDto.md)
|
||||||
- [AllJobStatusResponseDto](doc//AllJobStatusResponseDto.md)
|
- [AllJobStatusResponseDto](doc//AllJobStatusResponseDto.md)
|
||||||
@@ -330,6 +333,7 @@ Class | Method | HTTP request | Description
|
|||||||
- [ReactionLevel](doc//ReactionLevel.md)
|
- [ReactionLevel](doc//ReactionLevel.md)
|
||||||
- [ReactionType](doc//ReactionType.md)
|
- [ReactionType](doc//ReactionType.md)
|
||||||
- [RecognitionConfig](doc//RecognitionConfig.md)
|
- [RecognitionConfig](doc//RecognitionConfig.md)
|
||||||
|
- [ReverseGeocodingStateResponseDto](doc//ReverseGeocodingStateResponseDto.md)
|
||||||
- [ScanLibraryDto](doc//ScanLibraryDto.md)
|
- [ScanLibraryDto](doc//ScanLibraryDto.md)
|
||||||
- [SearchAlbumResponseDto](doc//SearchAlbumResponseDto.md)
|
- [SearchAlbumResponseDto](doc//SearchAlbumResponseDto.md)
|
||||||
- [SearchAssetResponseDto](doc//SearchAssetResponseDto.md)
|
- [SearchAssetResponseDto](doc//SearchAssetResponseDto.md)
|
||||||
|
|||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
# openapi.model.AdminOnboardingUpdateDto
|
||||||
|
|
||||||
|
## Load the model package
|
||||||
|
```dart
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
```
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**isOnboarded** | **bool** | |
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
||||||
Generated
-163
@@ -9,66 +9,9 @@ All URIs are relative to */api*
|
|||||||
|
|
||||||
Method | HTTP request | Description
|
Method | HTTP request | Description
|
||||||
------------- | ------------- | -------------
|
------------- | ------------- | -------------
|
||||||
[**fixAuditFiles**](AuditApi.md#fixauditfiles) | **POST** /audit/file-report/fix |
|
|
||||||
[**getAuditDeletes**](AuditApi.md#getauditdeletes) | **GET** /audit/deletes |
|
[**getAuditDeletes**](AuditApi.md#getauditdeletes) | **GET** /audit/deletes |
|
||||||
[**getAuditFiles**](AuditApi.md#getauditfiles) | **GET** /audit/file-report |
|
|
||||||
[**getFileChecksums**](AuditApi.md#getfilechecksums) | **POST** /audit/file-report/checksum |
|
|
||||||
|
|
||||||
|
|
||||||
# **fixAuditFiles**
|
|
||||||
> fixAuditFiles(fileReportFixDto)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Example
|
|
||||||
```dart
|
|
||||||
import 'package:openapi/api.dart';
|
|
||||||
// TODO Configure API key authorization: cookie
|
|
||||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
|
|
||||||
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
|
||||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
|
|
||||||
// TODO Configure API key authorization: api_key
|
|
||||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
|
|
||||||
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
|
||||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
|
|
||||||
// TODO Configure HTTP Bearer authorization: bearer
|
|
||||||
// Case 1. Use String Token
|
|
||||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
|
|
||||||
// Case 2. Use Function which generate token.
|
|
||||||
// String yourTokenGeneratorFunction() { ... }
|
|
||||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
|
|
||||||
|
|
||||||
final api_instance = AuditApi();
|
|
||||||
final fileReportFixDto = FileReportFixDto(); // FileReportFixDto |
|
|
||||||
|
|
||||||
try {
|
|
||||||
api_instance.fixAuditFiles(fileReportFixDto);
|
|
||||||
} catch (e) {
|
|
||||||
print('Exception when calling AuditApi->fixAuditFiles: $e\n');
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Parameters
|
|
||||||
|
|
||||||
Name | Type | Description | Notes
|
|
||||||
------------- | ------------- | ------------- | -------------
|
|
||||||
**fileReportFixDto** | [**FileReportFixDto**](FileReportFixDto.md)| |
|
|
||||||
|
|
||||||
### Return type
|
|
||||||
|
|
||||||
void (empty response body)
|
|
||||||
|
|
||||||
### Authorization
|
|
||||||
|
|
||||||
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
|
|
||||||
|
|
||||||
### HTTP request headers
|
|
||||||
|
|
||||||
- **Content-Type**: application/json
|
|
||||||
- **Accept**: Not defined
|
|
||||||
|
|
||||||
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
|
||||||
|
|
||||||
# **getAuditDeletes**
|
# **getAuditDeletes**
|
||||||
> AuditDeletesResponseDto getAuditDeletes(after, entityType, userId)
|
> AuditDeletesResponseDto getAuditDeletes(after, entityType, userId)
|
||||||
|
|
||||||
@@ -128,109 +71,3 @@ Name | Type | Description | Notes
|
|||||||
|
|
||||||
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
# **getAuditFiles**
|
|
||||||
> FileReportDto getAuditFiles()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Example
|
|
||||||
```dart
|
|
||||||
import 'package:openapi/api.dart';
|
|
||||||
// TODO Configure API key authorization: cookie
|
|
||||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
|
|
||||||
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
|
||||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
|
|
||||||
// TODO Configure API key authorization: api_key
|
|
||||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
|
|
||||||
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
|
||||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
|
|
||||||
// TODO Configure HTTP Bearer authorization: bearer
|
|
||||||
// Case 1. Use String Token
|
|
||||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
|
|
||||||
// Case 2. Use Function which generate token.
|
|
||||||
// String yourTokenGeneratorFunction() { ... }
|
|
||||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
|
|
||||||
|
|
||||||
final api_instance = AuditApi();
|
|
||||||
|
|
||||||
try {
|
|
||||||
final result = api_instance.getAuditFiles();
|
|
||||||
print(result);
|
|
||||||
} catch (e) {
|
|
||||||
print('Exception when calling AuditApi->getAuditFiles: $e\n');
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Parameters
|
|
||||||
This endpoint does not need any parameter.
|
|
||||||
|
|
||||||
### Return type
|
|
||||||
|
|
||||||
[**FileReportDto**](FileReportDto.md)
|
|
||||||
|
|
||||||
### Authorization
|
|
||||||
|
|
||||||
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
|
|
||||||
|
|
||||||
### HTTP request headers
|
|
||||||
|
|
||||||
- **Content-Type**: Not defined
|
|
||||||
- **Accept**: application/json
|
|
||||||
|
|
||||||
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
|
||||||
|
|
||||||
# **getFileChecksums**
|
|
||||||
> List<FileChecksumResponseDto> getFileChecksums(fileChecksumDto)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Example
|
|
||||||
```dart
|
|
||||||
import 'package:openapi/api.dart';
|
|
||||||
// TODO Configure API key authorization: cookie
|
|
||||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
|
|
||||||
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
|
||||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
|
|
||||||
// TODO Configure API key authorization: api_key
|
|
||||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
|
|
||||||
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
|
||||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
|
|
||||||
// TODO Configure HTTP Bearer authorization: bearer
|
|
||||||
// Case 1. Use String Token
|
|
||||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
|
|
||||||
// Case 2. Use Function which generate token.
|
|
||||||
// String yourTokenGeneratorFunction() { ... }
|
|
||||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
|
|
||||||
|
|
||||||
final api_instance = AuditApi();
|
|
||||||
final fileChecksumDto = FileChecksumDto(); // FileChecksumDto |
|
|
||||||
|
|
||||||
try {
|
|
||||||
final result = api_instance.getFileChecksums(fileChecksumDto);
|
|
||||||
print(result);
|
|
||||||
} catch (e) {
|
|
||||||
print('Exception when calling AuditApi->getFileChecksums: $e\n');
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Parameters
|
|
||||||
|
|
||||||
Name | Type | Description | Notes
|
|
||||||
------------- | ------------- | ------------- | -------------
|
|
||||||
**fileChecksumDto** | [**FileChecksumDto**](FileChecksumDto.md)| |
|
|
||||||
|
|
||||||
### Return type
|
|
||||||
|
|
||||||
[**List<FileChecksumResponseDto>**](FileChecksumResponseDto.md)
|
|
||||||
|
|
||||||
### Authorization
|
|
||||||
|
|
||||||
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
|
|
||||||
|
|
||||||
### HTTP request headers
|
|
||||||
|
|
||||||
- **Content-Type**: application/json
|
|
||||||
- **Accept**: application/json
|
|
||||||
|
|
||||||
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
|
||||||
|
|
||||||
|
|||||||
Generated
+176
@@ -0,0 +1,176 @@
|
|||||||
|
# openapi.api.FileReportApi
|
||||||
|
|
||||||
|
## Load the API package
|
||||||
|
```dart
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
```
|
||||||
|
|
||||||
|
All URIs are relative to */api*
|
||||||
|
|
||||||
|
Method | HTTP request | Description
|
||||||
|
------------- | ------------- | -------------
|
||||||
|
[**fixAuditFiles**](FileReportApi.md#fixauditfiles) | **POST** /report/fix |
|
||||||
|
[**getAuditFiles**](FileReportApi.md#getauditfiles) | **GET** /report |
|
||||||
|
[**getFileChecksums**](FileReportApi.md#getfilechecksums) | **POST** /report/checksum |
|
||||||
|
|
||||||
|
|
||||||
|
# **fixAuditFiles**
|
||||||
|
> fixAuditFiles(fileReportFixDto)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Example
|
||||||
|
```dart
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
// TODO Configure API key authorization: cookie
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
|
||||||
|
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
|
||||||
|
// TODO Configure API key authorization: api_key
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
|
||||||
|
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
|
||||||
|
// TODO Configure HTTP Bearer authorization: bearer
|
||||||
|
// Case 1. Use String Token
|
||||||
|
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
|
||||||
|
// Case 2. Use Function which generate token.
|
||||||
|
// String yourTokenGeneratorFunction() { ... }
|
||||||
|
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
|
||||||
|
|
||||||
|
final api_instance = FileReportApi();
|
||||||
|
final fileReportFixDto = FileReportFixDto(); // FileReportFixDto |
|
||||||
|
|
||||||
|
try {
|
||||||
|
api_instance.fixAuditFiles(fileReportFixDto);
|
||||||
|
} catch (e) {
|
||||||
|
print('Exception when calling FileReportApi->fixAuditFiles: $e\n');
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------- | ------------- | ------------- | -------------
|
||||||
|
**fileReportFixDto** | [**FileReportFixDto**](FileReportFixDto.md)| |
|
||||||
|
|
||||||
|
### Return type
|
||||||
|
|
||||||
|
void (empty response body)
|
||||||
|
|
||||||
|
### Authorization
|
||||||
|
|
||||||
|
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
|
||||||
|
|
||||||
|
### HTTP request headers
|
||||||
|
|
||||||
|
- **Content-Type**: application/json
|
||||||
|
- **Accept**: Not defined
|
||||||
|
|
||||||
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
# **getAuditFiles**
|
||||||
|
> FileReportDto getAuditFiles()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Example
|
||||||
|
```dart
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
// TODO Configure API key authorization: cookie
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
|
||||||
|
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
|
||||||
|
// TODO Configure API key authorization: api_key
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
|
||||||
|
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
|
||||||
|
// TODO Configure HTTP Bearer authorization: bearer
|
||||||
|
// Case 1. Use String Token
|
||||||
|
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
|
||||||
|
// Case 2. Use Function which generate token.
|
||||||
|
// String yourTokenGeneratorFunction() { ... }
|
||||||
|
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
|
||||||
|
|
||||||
|
final api_instance = FileReportApi();
|
||||||
|
|
||||||
|
try {
|
||||||
|
final result = api_instance.getAuditFiles();
|
||||||
|
print(result);
|
||||||
|
} catch (e) {
|
||||||
|
print('Exception when calling FileReportApi->getAuditFiles: $e\n');
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
This endpoint does not need any parameter.
|
||||||
|
|
||||||
|
### Return type
|
||||||
|
|
||||||
|
[**FileReportDto**](FileReportDto.md)
|
||||||
|
|
||||||
|
### Authorization
|
||||||
|
|
||||||
|
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
|
||||||
|
|
||||||
|
### HTTP request headers
|
||||||
|
|
||||||
|
- **Content-Type**: Not defined
|
||||||
|
- **Accept**: application/json
|
||||||
|
|
||||||
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
# **getFileChecksums**
|
||||||
|
> List<FileChecksumResponseDto> getFileChecksums(fileChecksumDto)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Example
|
||||||
|
```dart
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
// TODO Configure API key authorization: cookie
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
|
||||||
|
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
|
||||||
|
// TODO Configure API key authorization: api_key
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
|
||||||
|
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
|
||||||
|
// TODO Configure HTTP Bearer authorization: bearer
|
||||||
|
// Case 1. Use String Token
|
||||||
|
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
|
||||||
|
// Case 2. Use Function which generate token.
|
||||||
|
// String yourTokenGeneratorFunction() { ... }
|
||||||
|
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
|
||||||
|
|
||||||
|
final api_instance = FileReportApi();
|
||||||
|
final fileChecksumDto = FileChecksumDto(); // FileChecksumDto |
|
||||||
|
|
||||||
|
try {
|
||||||
|
final result = api_instance.getFileChecksums(fileChecksumDto);
|
||||||
|
print(result);
|
||||||
|
} catch (e) {
|
||||||
|
print('Exception when calling FileReportApi->getFileChecksums: $e\n');
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------- | ------------- | ------------- | -------------
|
||||||
|
**fileChecksumDto** | [**FileChecksumDto**](FileChecksumDto.md)| |
|
||||||
|
|
||||||
|
### Return type
|
||||||
|
|
||||||
|
[**List<FileChecksumResponseDto>**](FileChecksumResponseDto.md)
|
||||||
|
|
||||||
|
### Authorization
|
||||||
|
|
||||||
|
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
|
||||||
|
|
||||||
|
### HTTP request headers
|
||||||
|
|
||||||
|
- **Content-Type**: application/json
|
||||||
|
- **Accept**: application/json
|
||||||
|
|
||||||
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
# openapi.model.ReverseGeocodingStateResponseDto
|
||||||
|
|
||||||
|
## Load the model package
|
||||||
|
```dart
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
```
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**lastImportFileName** | **String** | |
|
||||||
|
**lastUpdate** | **String** | |
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
||||||
Generated
-51
@@ -17,7 +17,6 @@ Method | HTTP request | Description
|
|||||||
[**getSupportedMediaTypes**](ServerInfoApi.md#getsupportedmediatypes) | **GET** /server-info/media-types |
|
[**getSupportedMediaTypes**](ServerInfoApi.md#getsupportedmediatypes) | **GET** /server-info/media-types |
|
||||||
[**getTheme**](ServerInfoApi.md#gettheme) | **GET** /server-info/theme |
|
[**getTheme**](ServerInfoApi.md#gettheme) | **GET** /server-info/theme |
|
||||||
[**pingServer**](ServerInfoApi.md#pingserver) | **GET** /server-info/ping |
|
[**pingServer**](ServerInfoApi.md#pingserver) | **GET** /server-info/ping |
|
||||||
[**setAdminOnboarding**](ServerInfoApi.md#setadminonboarding) | **POST** /server-info/admin-onboarding |
|
|
||||||
|
|
||||||
|
|
||||||
# **getServerConfig**
|
# **getServerConfig**
|
||||||
@@ -344,53 +343,3 @@ No authorization required
|
|||||||
|
|
||||||
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
# **setAdminOnboarding**
|
|
||||||
> setAdminOnboarding()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Example
|
|
||||||
```dart
|
|
||||||
import 'package:openapi/api.dart';
|
|
||||||
// TODO Configure API key authorization: cookie
|
|
||||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
|
|
||||||
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
|
||||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
|
|
||||||
// TODO Configure API key authorization: api_key
|
|
||||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
|
|
||||||
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
|
||||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
|
|
||||||
// TODO Configure HTTP Bearer authorization: bearer
|
|
||||||
// Case 1. Use String Token
|
|
||||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
|
|
||||||
// Case 2. Use Function which generate token.
|
|
||||||
// String yourTokenGeneratorFunction() { ... }
|
|
||||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
|
|
||||||
|
|
||||||
final api_instance = ServerInfoApi();
|
|
||||||
|
|
||||||
try {
|
|
||||||
api_instance.setAdminOnboarding();
|
|
||||||
} catch (e) {
|
|
||||||
print('Exception when calling ServerInfoApi->setAdminOnboarding: $e\n');
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Parameters
|
|
||||||
This endpoint does not need any parameter.
|
|
||||||
|
|
||||||
### Return type
|
|
||||||
|
|
||||||
void (empty response body)
|
|
||||||
|
|
||||||
### Authorization
|
|
||||||
|
|
||||||
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
|
|
||||||
|
|
||||||
### HTTP request headers
|
|
||||||
|
|
||||||
- **Content-Type**: Not defined
|
|
||||||
- **Accept**: Not defined
|
|
||||||
|
|
||||||
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
|
||||||
|
|
||||||
|
|||||||
Generated
+172
@@ -0,0 +1,172 @@
|
|||||||
|
# openapi.api.SystemMetadataApi
|
||||||
|
|
||||||
|
## Load the API package
|
||||||
|
```dart
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
```
|
||||||
|
|
||||||
|
All URIs are relative to */api*
|
||||||
|
|
||||||
|
Method | HTTP request | Description
|
||||||
|
------------- | ------------- | -------------
|
||||||
|
[**getAdminOnboarding**](SystemMetadataApi.md#getadminonboarding) | **GET** /system-metadata/admin-onboarding |
|
||||||
|
[**getReverseGeocodingState**](SystemMetadataApi.md#getreversegeocodingstate) | **GET** /system-metadata/reverse-geocoding-state |
|
||||||
|
[**updateAdminOnboarding**](SystemMetadataApi.md#updateadminonboarding) | **POST** /system-metadata/admin-onboarding |
|
||||||
|
|
||||||
|
|
||||||
|
# **getAdminOnboarding**
|
||||||
|
> AdminOnboardingUpdateDto getAdminOnboarding()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Example
|
||||||
|
```dart
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
// TODO Configure API key authorization: cookie
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
|
||||||
|
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
|
||||||
|
// TODO Configure API key authorization: api_key
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
|
||||||
|
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
|
||||||
|
// TODO Configure HTTP Bearer authorization: bearer
|
||||||
|
// Case 1. Use String Token
|
||||||
|
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
|
||||||
|
// Case 2. Use Function which generate token.
|
||||||
|
// String yourTokenGeneratorFunction() { ... }
|
||||||
|
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
|
||||||
|
|
||||||
|
final api_instance = SystemMetadataApi();
|
||||||
|
|
||||||
|
try {
|
||||||
|
final result = api_instance.getAdminOnboarding();
|
||||||
|
print(result);
|
||||||
|
} catch (e) {
|
||||||
|
print('Exception when calling SystemMetadataApi->getAdminOnboarding: $e\n');
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
This endpoint does not need any parameter.
|
||||||
|
|
||||||
|
### Return type
|
||||||
|
|
||||||
|
[**AdminOnboardingUpdateDto**](AdminOnboardingUpdateDto.md)
|
||||||
|
|
||||||
|
### Authorization
|
||||||
|
|
||||||
|
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
|
||||||
|
|
||||||
|
### HTTP request headers
|
||||||
|
|
||||||
|
- **Content-Type**: Not defined
|
||||||
|
- **Accept**: application/json
|
||||||
|
|
||||||
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
# **getReverseGeocodingState**
|
||||||
|
> ReverseGeocodingStateResponseDto getReverseGeocodingState()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Example
|
||||||
|
```dart
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
// TODO Configure API key authorization: cookie
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
|
||||||
|
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
|
||||||
|
// TODO Configure API key authorization: api_key
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
|
||||||
|
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
|
||||||
|
// TODO Configure HTTP Bearer authorization: bearer
|
||||||
|
// Case 1. Use String Token
|
||||||
|
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
|
||||||
|
// Case 2. Use Function which generate token.
|
||||||
|
// String yourTokenGeneratorFunction() { ... }
|
||||||
|
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
|
||||||
|
|
||||||
|
final api_instance = SystemMetadataApi();
|
||||||
|
|
||||||
|
try {
|
||||||
|
final result = api_instance.getReverseGeocodingState();
|
||||||
|
print(result);
|
||||||
|
} catch (e) {
|
||||||
|
print('Exception when calling SystemMetadataApi->getReverseGeocodingState: $e\n');
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
This endpoint does not need any parameter.
|
||||||
|
|
||||||
|
### Return type
|
||||||
|
|
||||||
|
[**ReverseGeocodingStateResponseDto**](ReverseGeocodingStateResponseDto.md)
|
||||||
|
|
||||||
|
### Authorization
|
||||||
|
|
||||||
|
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
|
||||||
|
|
||||||
|
### HTTP request headers
|
||||||
|
|
||||||
|
- **Content-Type**: Not defined
|
||||||
|
- **Accept**: application/json
|
||||||
|
|
||||||
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
# **updateAdminOnboarding**
|
||||||
|
> updateAdminOnboarding(adminOnboardingUpdateDto)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Example
|
||||||
|
```dart
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
// TODO Configure API key authorization: cookie
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
|
||||||
|
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
|
||||||
|
// TODO Configure API key authorization: api_key
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
|
||||||
|
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
|
||||||
|
// TODO Configure HTTP Bearer authorization: bearer
|
||||||
|
// Case 1. Use String Token
|
||||||
|
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
|
||||||
|
// Case 2. Use Function which generate token.
|
||||||
|
// String yourTokenGeneratorFunction() { ... }
|
||||||
|
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
|
||||||
|
|
||||||
|
final api_instance = SystemMetadataApi();
|
||||||
|
final adminOnboardingUpdateDto = AdminOnboardingUpdateDto(); // AdminOnboardingUpdateDto |
|
||||||
|
|
||||||
|
try {
|
||||||
|
api_instance.updateAdminOnboarding(adminOnboardingUpdateDto);
|
||||||
|
} catch (e) {
|
||||||
|
print('Exception when calling SystemMetadataApi->updateAdminOnboarding: $e\n');
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------- | ------------- | ------------- | -------------
|
||||||
|
**adminOnboardingUpdateDto** | [**AdminOnboardingUpdateDto**](AdminOnboardingUpdateDto.md)| |
|
||||||
|
|
||||||
|
### Return type
|
||||||
|
|
||||||
|
void (empty response body)
|
||||||
|
|
||||||
|
### Authorization
|
||||||
|
|
||||||
|
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
|
||||||
|
|
||||||
|
### HTTP request headers
|
||||||
|
|
||||||
|
- **Content-Type**: application/json
|
||||||
|
- **Accept**: Not defined
|
||||||
|
|
||||||
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
Generated
+4
@@ -37,6 +37,7 @@ part 'api/audit_api.dart';
|
|||||||
part 'api/authentication_api.dart';
|
part 'api/authentication_api.dart';
|
||||||
part 'api/download_api.dart';
|
part 'api/download_api.dart';
|
||||||
part 'api/face_api.dart';
|
part 'api/face_api.dart';
|
||||||
|
part 'api/file_report_api.dart';
|
||||||
part 'api/job_api.dart';
|
part 'api/job_api.dart';
|
||||||
part 'api/library_api.dart';
|
part 'api/library_api.dart';
|
||||||
part 'api/memory_api.dart';
|
part 'api/memory_api.dart';
|
||||||
@@ -49,6 +50,7 @@ part 'api/sessions_api.dart';
|
|||||||
part 'api/shared_link_api.dart';
|
part 'api/shared_link_api.dart';
|
||||||
part 'api/sync_api.dart';
|
part 'api/sync_api.dart';
|
||||||
part 'api/system_config_api.dart';
|
part 'api/system_config_api.dart';
|
||||||
|
part 'api/system_metadata_api.dart';
|
||||||
part 'api/tag_api.dart';
|
part 'api/tag_api.dart';
|
||||||
part 'api/timeline_api.dart';
|
part 'api/timeline_api.dart';
|
||||||
part 'api/trash_api.dart';
|
part 'api/trash_api.dart';
|
||||||
@@ -62,6 +64,7 @@ part 'model/activity_create_dto.dart';
|
|||||||
part 'model/activity_response_dto.dart';
|
part 'model/activity_response_dto.dart';
|
||||||
part 'model/activity_statistics_response_dto.dart';
|
part 'model/activity_statistics_response_dto.dart';
|
||||||
part 'model/add_users_dto.dart';
|
part 'model/add_users_dto.dart';
|
||||||
|
part 'model/admin_onboarding_update_dto.dart';
|
||||||
part 'model/album_count_response_dto.dart';
|
part 'model/album_count_response_dto.dart';
|
||||||
part 'model/album_response_dto.dart';
|
part 'model/album_response_dto.dart';
|
||||||
part 'model/all_job_status_response_dto.dart';
|
part 'model/all_job_status_response_dto.dart';
|
||||||
@@ -159,6 +162,7 @@ part 'model/queue_status_dto.dart';
|
|||||||
part 'model/reaction_level.dart';
|
part 'model/reaction_level.dart';
|
||||||
part 'model/reaction_type.dart';
|
part 'model/reaction_type.dart';
|
||||||
part 'model/recognition_config.dart';
|
part 'model/recognition_config.dart';
|
||||||
|
part 'model/reverse_geocoding_state_response_dto.dart';
|
||||||
part 'model/scan_library_dto.dart';
|
part 'model/scan_library_dto.dart';
|
||||||
part 'model/search_album_response_dto.dart';
|
part 'model/search_album_response_dto.dart';
|
||||||
part 'model/search_asset_response_dto.dart';
|
part 'model/search_asset_response_dto.dart';
|
||||||
|
|||||||
Generated
-130
@@ -16,45 +16,6 @@ class AuditApi {
|
|||||||
|
|
||||||
final ApiClient apiClient;
|
final ApiClient apiClient;
|
||||||
|
|
||||||
/// Performs an HTTP 'POST /audit/file-report/fix' operation and returns the [Response].
|
|
||||||
/// Parameters:
|
|
||||||
///
|
|
||||||
/// * [FileReportFixDto] fileReportFixDto (required):
|
|
||||||
Future<Response> fixAuditFilesWithHttpInfo(FileReportFixDto fileReportFixDto,) async {
|
|
||||||
// ignore: prefer_const_declarations
|
|
||||||
final path = r'/audit/file-report/fix';
|
|
||||||
|
|
||||||
// ignore: prefer_final_locals
|
|
||||||
Object? postBody = fileReportFixDto;
|
|
||||||
|
|
||||||
final queryParams = <QueryParam>[];
|
|
||||||
final headerParams = <String, String>{};
|
|
||||||
final formParams = <String, String>{};
|
|
||||||
|
|
||||||
const contentTypes = <String>['application/json'];
|
|
||||||
|
|
||||||
|
|
||||||
return apiClient.invokeAPI(
|
|
||||||
path,
|
|
||||||
'POST',
|
|
||||||
queryParams,
|
|
||||||
postBody,
|
|
||||||
headerParams,
|
|
||||||
formParams,
|
|
||||||
contentTypes.isEmpty ? null : contentTypes.first,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parameters:
|
|
||||||
///
|
|
||||||
/// * [FileReportFixDto] fileReportFixDto (required):
|
|
||||||
Future<void> fixAuditFiles(FileReportFixDto fileReportFixDto,) async {
|
|
||||||
final response = await fixAuditFilesWithHttpInfo(fileReportFixDto,);
|
|
||||||
if (response.statusCode >= HttpStatus.badRequest) {
|
|
||||||
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Performs an HTTP 'GET /audit/deletes' operation and returns the [Response].
|
/// Performs an HTTP 'GET /audit/deletes' operation and returns the [Response].
|
||||||
/// Parameters:
|
/// Parameters:
|
||||||
///
|
///
|
||||||
@@ -115,95 +76,4 @@ class AuditApi {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Performs an HTTP 'GET /audit/file-report' operation and returns the [Response].
|
|
||||||
Future<Response> getAuditFilesWithHttpInfo() async {
|
|
||||||
// ignore: prefer_const_declarations
|
|
||||||
final path = r'/audit/file-report';
|
|
||||||
|
|
||||||
// ignore: prefer_final_locals
|
|
||||||
Object? postBody;
|
|
||||||
|
|
||||||
final queryParams = <QueryParam>[];
|
|
||||||
final headerParams = <String, String>{};
|
|
||||||
final formParams = <String, String>{};
|
|
||||||
|
|
||||||
const contentTypes = <String>[];
|
|
||||||
|
|
||||||
|
|
||||||
return apiClient.invokeAPI(
|
|
||||||
path,
|
|
||||||
'GET',
|
|
||||||
queryParams,
|
|
||||||
postBody,
|
|
||||||
headerParams,
|
|
||||||
formParams,
|
|
||||||
contentTypes.isEmpty ? null : contentTypes.first,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<FileReportDto?> getAuditFiles() async {
|
|
||||||
final response = await getAuditFilesWithHttpInfo();
|
|
||||||
if (response.statusCode >= HttpStatus.badRequest) {
|
|
||||||
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
|
||||||
}
|
|
||||||
// When a remote server returns no body with a status of 204, we shall not decode it.
|
|
||||||
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
|
|
||||||
// FormatException when trying to decode an empty string.
|
|
||||||
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
|
|
||||||
return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'FileReportDto',) as FileReportDto;
|
|
||||||
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Performs an HTTP 'POST /audit/file-report/checksum' operation and returns the [Response].
|
|
||||||
/// Parameters:
|
|
||||||
///
|
|
||||||
/// * [FileChecksumDto] fileChecksumDto (required):
|
|
||||||
Future<Response> getFileChecksumsWithHttpInfo(FileChecksumDto fileChecksumDto,) async {
|
|
||||||
// ignore: prefer_const_declarations
|
|
||||||
final path = r'/audit/file-report/checksum';
|
|
||||||
|
|
||||||
// ignore: prefer_final_locals
|
|
||||||
Object? postBody = fileChecksumDto;
|
|
||||||
|
|
||||||
final queryParams = <QueryParam>[];
|
|
||||||
final headerParams = <String, String>{};
|
|
||||||
final formParams = <String, String>{};
|
|
||||||
|
|
||||||
const contentTypes = <String>['application/json'];
|
|
||||||
|
|
||||||
|
|
||||||
return apiClient.invokeAPI(
|
|
||||||
path,
|
|
||||||
'POST',
|
|
||||||
queryParams,
|
|
||||||
postBody,
|
|
||||||
headerParams,
|
|
||||||
formParams,
|
|
||||||
contentTypes.isEmpty ? null : contentTypes.first,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parameters:
|
|
||||||
///
|
|
||||||
/// * [FileChecksumDto] fileChecksumDto (required):
|
|
||||||
Future<List<FileChecksumResponseDto>?> getFileChecksums(FileChecksumDto fileChecksumDto,) async {
|
|
||||||
final response = await getFileChecksumsWithHttpInfo(fileChecksumDto,);
|
|
||||||
if (response.statusCode >= HttpStatus.badRequest) {
|
|
||||||
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
|
||||||
}
|
|
||||||
// When a remote server returns no body with a status of 204, we shall not decode it.
|
|
||||||
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
|
|
||||||
// FormatException when trying to decode an empty string.
|
|
||||||
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
|
|
||||||
final responseBody = await _decodeBodyBytes(response);
|
|
||||||
return (await apiClient.deserializeAsync(responseBody, 'List<FileChecksumResponseDto>') as List)
|
|
||||||
.cast<FileChecksumResponseDto>()
|
|
||||||
.toList(growable: false);
|
|
||||||
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+148
@@ -0,0 +1,148 @@
|
|||||||
|
//
|
||||||
|
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||||
|
//
|
||||||
|
// @dart=2.12
|
||||||
|
|
||||||
|
// ignore_for_file: unused_element, unused_import
|
||||||
|
// ignore_for_file: always_put_required_named_parameters_first
|
||||||
|
// ignore_for_file: constant_identifier_names
|
||||||
|
// ignore_for_file: lines_longer_than_80_chars
|
||||||
|
|
||||||
|
part of openapi.api;
|
||||||
|
|
||||||
|
|
||||||
|
class FileReportApi {
|
||||||
|
FileReportApi([ApiClient? apiClient]) : apiClient = apiClient ?? defaultApiClient;
|
||||||
|
|
||||||
|
final ApiClient apiClient;
|
||||||
|
|
||||||
|
/// Performs an HTTP 'POST /report/fix' operation and returns the [Response].
|
||||||
|
/// Parameters:
|
||||||
|
///
|
||||||
|
/// * [FileReportFixDto] fileReportFixDto (required):
|
||||||
|
Future<Response> fixAuditFilesWithHttpInfo(FileReportFixDto fileReportFixDto,) async {
|
||||||
|
// ignore: prefer_const_declarations
|
||||||
|
final path = r'/report/fix';
|
||||||
|
|
||||||
|
// ignore: prefer_final_locals
|
||||||
|
Object? postBody = fileReportFixDto;
|
||||||
|
|
||||||
|
final queryParams = <QueryParam>[];
|
||||||
|
final headerParams = <String, String>{};
|
||||||
|
final formParams = <String, String>{};
|
||||||
|
|
||||||
|
const contentTypes = <String>['application/json'];
|
||||||
|
|
||||||
|
|
||||||
|
return apiClient.invokeAPI(
|
||||||
|
path,
|
||||||
|
'POST',
|
||||||
|
queryParams,
|
||||||
|
postBody,
|
||||||
|
headerParams,
|
||||||
|
formParams,
|
||||||
|
contentTypes.isEmpty ? null : contentTypes.first,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parameters:
|
||||||
|
///
|
||||||
|
/// * [FileReportFixDto] fileReportFixDto (required):
|
||||||
|
Future<void> fixAuditFiles(FileReportFixDto fileReportFixDto,) async {
|
||||||
|
final response = await fixAuditFilesWithHttpInfo(fileReportFixDto,);
|
||||||
|
if (response.statusCode >= HttpStatus.badRequest) {
|
||||||
|
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Performs an HTTP 'GET /report' operation and returns the [Response].
|
||||||
|
Future<Response> getAuditFilesWithHttpInfo() async {
|
||||||
|
// ignore: prefer_const_declarations
|
||||||
|
final path = r'/report';
|
||||||
|
|
||||||
|
// ignore: prefer_final_locals
|
||||||
|
Object? postBody;
|
||||||
|
|
||||||
|
final queryParams = <QueryParam>[];
|
||||||
|
final headerParams = <String, String>{};
|
||||||
|
final formParams = <String, String>{};
|
||||||
|
|
||||||
|
const contentTypes = <String>[];
|
||||||
|
|
||||||
|
|
||||||
|
return apiClient.invokeAPI(
|
||||||
|
path,
|
||||||
|
'GET',
|
||||||
|
queryParams,
|
||||||
|
postBody,
|
||||||
|
headerParams,
|
||||||
|
formParams,
|
||||||
|
contentTypes.isEmpty ? null : contentTypes.first,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<FileReportDto?> getAuditFiles() async {
|
||||||
|
final response = await getAuditFilesWithHttpInfo();
|
||||||
|
if (response.statusCode >= HttpStatus.badRequest) {
|
||||||
|
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||||
|
}
|
||||||
|
// When a remote server returns no body with a status of 204, we shall not decode it.
|
||||||
|
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
|
||||||
|
// FormatException when trying to decode an empty string.
|
||||||
|
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
|
||||||
|
return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'FileReportDto',) as FileReportDto;
|
||||||
|
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Performs an HTTP 'POST /report/checksum' operation and returns the [Response].
|
||||||
|
/// Parameters:
|
||||||
|
///
|
||||||
|
/// * [FileChecksumDto] fileChecksumDto (required):
|
||||||
|
Future<Response> getFileChecksumsWithHttpInfo(FileChecksumDto fileChecksumDto,) async {
|
||||||
|
// ignore: prefer_const_declarations
|
||||||
|
final path = r'/report/checksum';
|
||||||
|
|
||||||
|
// ignore: prefer_final_locals
|
||||||
|
Object? postBody = fileChecksumDto;
|
||||||
|
|
||||||
|
final queryParams = <QueryParam>[];
|
||||||
|
final headerParams = <String, String>{};
|
||||||
|
final formParams = <String, String>{};
|
||||||
|
|
||||||
|
const contentTypes = <String>['application/json'];
|
||||||
|
|
||||||
|
|
||||||
|
return apiClient.invokeAPI(
|
||||||
|
path,
|
||||||
|
'POST',
|
||||||
|
queryParams,
|
||||||
|
postBody,
|
||||||
|
headerParams,
|
||||||
|
formParams,
|
||||||
|
contentTypes.isEmpty ? null : contentTypes.first,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parameters:
|
||||||
|
///
|
||||||
|
/// * [FileChecksumDto] fileChecksumDto (required):
|
||||||
|
Future<List<FileChecksumResponseDto>?> getFileChecksums(FileChecksumDto fileChecksumDto,) async {
|
||||||
|
final response = await getFileChecksumsWithHttpInfo(fileChecksumDto,);
|
||||||
|
if (response.statusCode >= HttpStatus.badRequest) {
|
||||||
|
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||||
|
}
|
||||||
|
// When a remote server returns no body with a status of 204, we shall not decode it.
|
||||||
|
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
|
||||||
|
// FormatException when trying to decode an empty string.
|
||||||
|
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
|
||||||
|
final responseBody = await _decodeBodyBytes(response);
|
||||||
|
return (await apiClient.deserializeAsync(responseBody, 'List<FileChecksumResponseDto>') as List)
|
||||||
|
.cast<FileChecksumResponseDto>()
|
||||||
|
.toList(growable: false);
|
||||||
|
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
-33
@@ -343,37 +343,4 @@ class ServerInfoApi {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Performs an HTTP 'POST /server-info/admin-onboarding' operation and returns the [Response].
|
|
||||||
Future<Response> setAdminOnboardingWithHttpInfo() async {
|
|
||||||
// ignore: prefer_const_declarations
|
|
||||||
final path = r'/server-info/admin-onboarding';
|
|
||||||
|
|
||||||
// ignore: prefer_final_locals
|
|
||||||
Object? postBody;
|
|
||||||
|
|
||||||
final queryParams = <QueryParam>[];
|
|
||||||
final headerParams = <String, String>{};
|
|
||||||
final formParams = <String, String>{};
|
|
||||||
|
|
||||||
const contentTypes = <String>[];
|
|
||||||
|
|
||||||
|
|
||||||
return apiClient.invokeAPI(
|
|
||||||
path,
|
|
||||||
'POST',
|
|
||||||
queryParams,
|
|
||||||
postBody,
|
|
||||||
headerParams,
|
|
||||||
formParams,
|
|
||||||
contentTypes.isEmpty ? null : contentTypes.first,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> setAdminOnboarding() async {
|
|
||||||
final response = await setAdminOnboardingWithHttpInfo();
|
|
||||||
if (response.statusCode >= HttpStatus.badRequest) {
|
|
||||||
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+139
@@ -0,0 +1,139 @@
|
|||||||
|
//
|
||||||
|
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||||
|
//
|
||||||
|
// @dart=2.12
|
||||||
|
|
||||||
|
// ignore_for_file: unused_element, unused_import
|
||||||
|
// ignore_for_file: always_put_required_named_parameters_first
|
||||||
|
// ignore_for_file: constant_identifier_names
|
||||||
|
// ignore_for_file: lines_longer_than_80_chars
|
||||||
|
|
||||||
|
part of openapi.api;
|
||||||
|
|
||||||
|
|
||||||
|
class SystemMetadataApi {
|
||||||
|
SystemMetadataApi([ApiClient? apiClient]) : apiClient = apiClient ?? defaultApiClient;
|
||||||
|
|
||||||
|
final ApiClient apiClient;
|
||||||
|
|
||||||
|
/// Performs an HTTP 'GET /system-metadata/admin-onboarding' operation and returns the [Response].
|
||||||
|
Future<Response> getAdminOnboardingWithHttpInfo() async {
|
||||||
|
// ignore: prefer_const_declarations
|
||||||
|
final path = r'/system-metadata/admin-onboarding';
|
||||||
|
|
||||||
|
// ignore: prefer_final_locals
|
||||||
|
Object? postBody;
|
||||||
|
|
||||||
|
final queryParams = <QueryParam>[];
|
||||||
|
final headerParams = <String, String>{};
|
||||||
|
final formParams = <String, String>{};
|
||||||
|
|
||||||
|
const contentTypes = <String>[];
|
||||||
|
|
||||||
|
|
||||||
|
return apiClient.invokeAPI(
|
||||||
|
path,
|
||||||
|
'GET',
|
||||||
|
queryParams,
|
||||||
|
postBody,
|
||||||
|
headerParams,
|
||||||
|
formParams,
|
||||||
|
contentTypes.isEmpty ? null : contentTypes.first,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<AdminOnboardingUpdateDto?> getAdminOnboarding() async {
|
||||||
|
final response = await getAdminOnboardingWithHttpInfo();
|
||||||
|
if (response.statusCode >= HttpStatus.badRequest) {
|
||||||
|
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||||
|
}
|
||||||
|
// When a remote server returns no body with a status of 204, we shall not decode it.
|
||||||
|
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
|
||||||
|
// FormatException when trying to decode an empty string.
|
||||||
|
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
|
||||||
|
return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'AdminOnboardingUpdateDto',) as AdminOnboardingUpdateDto;
|
||||||
|
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Performs an HTTP 'GET /system-metadata/reverse-geocoding-state' operation and returns the [Response].
|
||||||
|
Future<Response> getReverseGeocodingStateWithHttpInfo() async {
|
||||||
|
// ignore: prefer_const_declarations
|
||||||
|
final path = r'/system-metadata/reverse-geocoding-state';
|
||||||
|
|
||||||
|
// ignore: prefer_final_locals
|
||||||
|
Object? postBody;
|
||||||
|
|
||||||
|
final queryParams = <QueryParam>[];
|
||||||
|
final headerParams = <String, String>{};
|
||||||
|
final formParams = <String, String>{};
|
||||||
|
|
||||||
|
const contentTypes = <String>[];
|
||||||
|
|
||||||
|
|
||||||
|
return apiClient.invokeAPI(
|
||||||
|
path,
|
||||||
|
'GET',
|
||||||
|
queryParams,
|
||||||
|
postBody,
|
||||||
|
headerParams,
|
||||||
|
formParams,
|
||||||
|
contentTypes.isEmpty ? null : contentTypes.first,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<ReverseGeocodingStateResponseDto?> getReverseGeocodingState() async {
|
||||||
|
final response = await getReverseGeocodingStateWithHttpInfo();
|
||||||
|
if (response.statusCode >= HttpStatus.badRequest) {
|
||||||
|
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||||
|
}
|
||||||
|
// When a remote server returns no body with a status of 204, we shall not decode it.
|
||||||
|
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
|
||||||
|
// FormatException when trying to decode an empty string.
|
||||||
|
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
|
||||||
|
return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'ReverseGeocodingStateResponseDto',) as ReverseGeocodingStateResponseDto;
|
||||||
|
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Performs an HTTP 'POST /system-metadata/admin-onboarding' operation and returns the [Response].
|
||||||
|
/// Parameters:
|
||||||
|
///
|
||||||
|
/// * [AdminOnboardingUpdateDto] adminOnboardingUpdateDto (required):
|
||||||
|
Future<Response> updateAdminOnboardingWithHttpInfo(AdminOnboardingUpdateDto adminOnboardingUpdateDto,) async {
|
||||||
|
// ignore: prefer_const_declarations
|
||||||
|
final path = r'/system-metadata/admin-onboarding';
|
||||||
|
|
||||||
|
// ignore: prefer_final_locals
|
||||||
|
Object? postBody = adminOnboardingUpdateDto;
|
||||||
|
|
||||||
|
final queryParams = <QueryParam>[];
|
||||||
|
final headerParams = <String, String>{};
|
||||||
|
final formParams = <String, String>{};
|
||||||
|
|
||||||
|
const contentTypes = <String>['application/json'];
|
||||||
|
|
||||||
|
|
||||||
|
return apiClient.invokeAPI(
|
||||||
|
path,
|
||||||
|
'POST',
|
||||||
|
queryParams,
|
||||||
|
postBody,
|
||||||
|
headerParams,
|
||||||
|
formParams,
|
||||||
|
contentTypes.isEmpty ? null : contentTypes.first,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parameters:
|
||||||
|
///
|
||||||
|
/// * [AdminOnboardingUpdateDto] adminOnboardingUpdateDto (required):
|
||||||
|
Future<void> updateAdminOnboarding(AdminOnboardingUpdateDto adminOnboardingUpdateDto,) async {
|
||||||
|
final response = await updateAdminOnboardingWithHttpInfo(adminOnboardingUpdateDto,);
|
||||||
|
if (response.statusCode >= HttpStatus.badRequest) {
|
||||||
|
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Generated
+4
@@ -198,6 +198,8 @@ class ApiClient {
|
|||||||
return ActivityStatisticsResponseDto.fromJson(value);
|
return ActivityStatisticsResponseDto.fromJson(value);
|
||||||
case 'AddUsersDto':
|
case 'AddUsersDto':
|
||||||
return AddUsersDto.fromJson(value);
|
return AddUsersDto.fromJson(value);
|
||||||
|
case 'AdminOnboardingUpdateDto':
|
||||||
|
return AdminOnboardingUpdateDto.fromJson(value);
|
||||||
case 'AlbumCountResponseDto':
|
case 'AlbumCountResponseDto':
|
||||||
return AlbumCountResponseDto.fromJson(value);
|
return AlbumCountResponseDto.fromJson(value);
|
||||||
case 'AlbumResponseDto':
|
case 'AlbumResponseDto':
|
||||||
@@ -392,6 +394,8 @@ class ApiClient {
|
|||||||
return ReactionTypeTypeTransformer().decode(value);
|
return ReactionTypeTypeTransformer().decode(value);
|
||||||
case 'RecognitionConfig':
|
case 'RecognitionConfig':
|
||||||
return RecognitionConfig.fromJson(value);
|
return RecognitionConfig.fromJson(value);
|
||||||
|
case 'ReverseGeocodingStateResponseDto':
|
||||||
|
return ReverseGeocodingStateResponseDto.fromJson(value);
|
||||||
case 'ScanLibraryDto':
|
case 'ScanLibraryDto':
|
||||||
return ScanLibraryDto.fromJson(value);
|
return ScanLibraryDto.fromJson(value);
|
||||||
case 'SearchAlbumResponseDto':
|
case 'SearchAlbumResponseDto':
|
||||||
|
|||||||
@@ -0,0 +1,98 @@
|
|||||||
|
//
|
||||||
|
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||||
|
//
|
||||||
|
// @dart=2.12
|
||||||
|
|
||||||
|
// ignore_for_file: unused_element, unused_import
|
||||||
|
// ignore_for_file: always_put_required_named_parameters_first
|
||||||
|
// ignore_for_file: constant_identifier_names
|
||||||
|
// ignore_for_file: lines_longer_than_80_chars
|
||||||
|
|
||||||
|
part of openapi.api;
|
||||||
|
|
||||||
|
class AdminOnboardingUpdateDto {
|
||||||
|
/// Returns a new [AdminOnboardingUpdateDto] instance.
|
||||||
|
AdminOnboardingUpdateDto({
|
||||||
|
required this.isOnboarded,
|
||||||
|
});
|
||||||
|
|
||||||
|
bool isOnboarded;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) => identical(this, other) || other is AdminOnboardingUpdateDto &&
|
||||||
|
other.isOnboarded == isOnboarded;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode =>
|
||||||
|
// ignore: unnecessary_parenthesis
|
||||||
|
(isOnboarded.hashCode);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'AdminOnboardingUpdateDto[isOnboarded=$isOnboarded]';
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final json = <String, dynamic>{};
|
||||||
|
json[r'isOnboarded'] = this.isOnboarded;
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a new [AdminOnboardingUpdateDto] instance and imports its values from
|
||||||
|
/// [value] if it's a [Map], null otherwise.
|
||||||
|
// ignore: prefer_constructors_over_static_methods
|
||||||
|
static AdminOnboardingUpdateDto? fromJson(dynamic value) {
|
||||||
|
if (value is Map) {
|
||||||
|
final json = value.cast<String, dynamic>();
|
||||||
|
|
||||||
|
return AdminOnboardingUpdateDto(
|
||||||
|
isOnboarded: mapValueOfType<bool>(json, r'isOnboarded')!,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<AdminOnboardingUpdateDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||||
|
final result = <AdminOnboardingUpdateDto>[];
|
||||||
|
if (json is List && json.isNotEmpty) {
|
||||||
|
for (final row in json) {
|
||||||
|
final value = AdminOnboardingUpdateDto.fromJson(row);
|
||||||
|
if (value != null) {
|
||||||
|
result.add(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.toList(growable: growable);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Map<String, AdminOnboardingUpdateDto> mapFromJson(dynamic json) {
|
||||||
|
final map = <String, AdminOnboardingUpdateDto>{};
|
||||||
|
if (json is Map && json.isNotEmpty) {
|
||||||
|
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||||
|
for (final entry in json.entries) {
|
||||||
|
final value = AdminOnboardingUpdateDto.fromJson(entry.value);
|
||||||
|
if (value != null) {
|
||||||
|
map[entry.key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
// maps a json object with a list of AdminOnboardingUpdateDto-objects as value to a dart map
|
||||||
|
static Map<String, List<AdminOnboardingUpdateDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||||
|
final map = <String, List<AdminOnboardingUpdateDto>>{};
|
||||||
|
if (json is Map && json.isNotEmpty) {
|
||||||
|
// ignore: parameter_assignments
|
||||||
|
json = json.cast<String, dynamic>();
|
||||||
|
for (final entry in json.entries) {
|
||||||
|
map[entry.key] = AdminOnboardingUpdateDto.listFromJson(entry.value, growable: growable,);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The list of required keys that must be present in a JSON.
|
||||||
|
static const requiredKeys = <String>{
|
||||||
|
'isOnboarded',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
//
|
||||||
|
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||||
|
//
|
||||||
|
// @dart=2.12
|
||||||
|
|
||||||
|
// ignore_for_file: unused_element, unused_import
|
||||||
|
// ignore_for_file: always_put_required_named_parameters_first
|
||||||
|
// ignore_for_file: constant_identifier_names
|
||||||
|
// ignore_for_file: lines_longer_than_80_chars
|
||||||
|
|
||||||
|
part of openapi.api;
|
||||||
|
|
||||||
|
class ReverseGeocodingStateResponseDto {
|
||||||
|
/// Returns a new [ReverseGeocodingStateResponseDto] instance.
|
||||||
|
ReverseGeocodingStateResponseDto({
|
||||||
|
required this.lastImportFileName,
|
||||||
|
required this.lastUpdate,
|
||||||
|
});
|
||||||
|
|
||||||
|
String? lastImportFileName;
|
||||||
|
|
||||||
|
String? lastUpdate;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) => identical(this, other) || other is ReverseGeocodingStateResponseDto &&
|
||||||
|
other.lastImportFileName == lastImportFileName &&
|
||||||
|
other.lastUpdate == lastUpdate;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode =>
|
||||||
|
// ignore: unnecessary_parenthesis
|
||||||
|
(lastImportFileName == null ? 0 : lastImportFileName!.hashCode) +
|
||||||
|
(lastUpdate == null ? 0 : lastUpdate!.hashCode);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'ReverseGeocodingStateResponseDto[lastImportFileName=$lastImportFileName, lastUpdate=$lastUpdate]';
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final json = <String, dynamic>{};
|
||||||
|
if (this.lastImportFileName != null) {
|
||||||
|
json[r'lastImportFileName'] = this.lastImportFileName;
|
||||||
|
} else {
|
||||||
|
// json[r'lastImportFileName'] = null;
|
||||||
|
}
|
||||||
|
if (this.lastUpdate != null) {
|
||||||
|
json[r'lastUpdate'] = this.lastUpdate;
|
||||||
|
} else {
|
||||||
|
// json[r'lastUpdate'] = null;
|
||||||
|
}
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a new [ReverseGeocodingStateResponseDto] instance and imports its values from
|
||||||
|
/// [value] if it's a [Map], null otherwise.
|
||||||
|
// ignore: prefer_constructors_over_static_methods
|
||||||
|
static ReverseGeocodingStateResponseDto? fromJson(dynamic value) {
|
||||||
|
if (value is Map) {
|
||||||
|
final json = value.cast<String, dynamic>();
|
||||||
|
|
||||||
|
return ReverseGeocodingStateResponseDto(
|
||||||
|
lastImportFileName: mapValueOfType<String>(json, r'lastImportFileName'),
|
||||||
|
lastUpdate: mapValueOfType<String>(json, r'lastUpdate'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<ReverseGeocodingStateResponseDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||||
|
final result = <ReverseGeocodingStateResponseDto>[];
|
||||||
|
if (json is List && json.isNotEmpty) {
|
||||||
|
for (final row in json) {
|
||||||
|
final value = ReverseGeocodingStateResponseDto.fromJson(row);
|
||||||
|
if (value != null) {
|
||||||
|
result.add(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.toList(growable: growable);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Map<String, ReverseGeocodingStateResponseDto> mapFromJson(dynamic json) {
|
||||||
|
final map = <String, ReverseGeocodingStateResponseDto>{};
|
||||||
|
if (json is Map && json.isNotEmpty) {
|
||||||
|
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||||
|
for (final entry in json.entries) {
|
||||||
|
final value = ReverseGeocodingStateResponseDto.fromJson(entry.value);
|
||||||
|
if (value != null) {
|
||||||
|
map[entry.key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
// maps a json object with a list of ReverseGeocodingStateResponseDto-objects as value to a dart map
|
||||||
|
static Map<String, List<ReverseGeocodingStateResponseDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||||
|
final map = <String, List<ReverseGeocodingStateResponseDto>>{};
|
||||||
|
if (json is Map && json.isNotEmpty) {
|
||||||
|
// ignore: parameter_assignments
|
||||||
|
json = json.cast<String, dynamic>();
|
||||||
|
for (final entry in json.entries) {
|
||||||
|
map[entry.key] = ReverseGeocodingStateResponseDto.listFromJson(entry.value, growable: growable,);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The list of required keys that must be present in a JSON.
|
||||||
|
static const requiredKeys = <String>{
|
||||||
|
'lastImportFileName',
|
||||||
|
'lastUpdate',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||||
|
//
|
||||||
|
// @dart=2.12
|
||||||
|
|
||||||
|
// ignore_for_file: unused_element, unused_import
|
||||||
|
// ignore_for_file: always_put_required_named_parameters_first
|
||||||
|
// ignore_for_file: constant_identifier_names
|
||||||
|
// ignore_for_file: lines_longer_than_80_chars
|
||||||
|
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
// tests for AdminOnboardingUpdateDto
|
||||||
|
void main() {
|
||||||
|
// final instance = AdminOnboardingUpdateDto();
|
||||||
|
|
||||||
|
group('test AdminOnboardingUpdateDto', () {
|
||||||
|
// bool isOnboarded
|
||||||
|
test('to test the property `isOnboarded`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
Generated
-15
@@ -17,25 +17,10 @@ void main() {
|
|||||||
// final instance = AuditApi();
|
// final instance = AuditApi();
|
||||||
|
|
||||||
group('tests for AuditApi', () {
|
group('tests for AuditApi', () {
|
||||||
//Future fixAuditFiles(FileReportFixDto fileReportFixDto) async
|
|
||||||
test('test fixAuditFiles', () async {
|
|
||||||
// TODO
|
|
||||||
});
|
|
||||||
|
|
||||||
//Future<AuditDeletesResponseDto> getAuditDeletes(DateTime after, EntityType entityType, { String userId }) async
|
//Future<AuditDeletesResponseDto> getAuditDeletes(DateTime after, EntityType entityType, { String userId }) async
|
||||||
test('test getAuditDeletes', () async {
|
test('test getAuditDeletes', () async {
|
||||||
// TODO
|
// TODO
|
||||||
});
|
});
|
||||||
|
|
||||||
//Future<FileReportDto> getAuditFiles() async
|
|
||||||
test('test getAuditFiles', () async {
|
|
||||||
// TODO
|
|
||||||
});
|
|
||||||
|
|
||||||
//Future<List<FileChecksumResponseDto>> getFileChecksums(FileChecksumDto fileChecksumDto) async
|
|
||||||
test('test getFileChecksums', () async {
|
|
||||||
// TODO
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
+36
@@ -0,0 +1,36 @@
|
|||||||
|
//
|
||||||
|
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||||
|
//
|
||||||
|
// @dart=2.12
|
||||||
|
|
||||||
|
// ignore_for_file: unused_element, unused_import
|
||||||
|
// ignore_for_file: always_put_required_named_parameters_first
|
||||||
|
// ignore_for_file: constant_identifier_names
|
||||||
|
// ignore_for_file: lines_longer_than_80_chars
|
||||||
|
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
|
||||||
|
/// tests for FileReportApi
|
||||||
|
void main() {
|
||||||
|
// final instance = FileReportApi();
|
||||||
|
|
||||||
|
group('tests for FileReportApi', () {
|
||||||
|
//Future fixAuditFiles(FileReportFixDto fileReportFixDto) async
|
||||||
|
test('test fixAuditFiles', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
//Future<FileReportDto> getAuditFiles() async
|
||||||
|
test('test getAuditFiles', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
//Future<List<FileChecksumResponseDto>> getFileChecksums(FileChecksumDto fileChecksumDto) async
|
||||||
|
test('test getFileChecksums', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
//
|
||||||
|
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||||
|
//
|
||||||
|
// @dart=2.12
|
||||||
|
|
||||||
|
// ignore_for_file: unused_element, unused_import
|
||||||
|
// ignore_for_file: always_put_required_named_parameters_first
|
||||||
|
// ignore_for_file: constant_identifier_names
|
||||||
|
// ignore_for_file: lines_longer_than_80_chars
|
||||||
|
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
// tests for ReverseGeocodingStateResponseDto
|
||||||
|
void main() {
|
||||||
|
// final instance = ReverseGeocodingStateResponseDto();
|
||||||
|
|
||||||
|
group('test ReverseGeocodingStateResponseDto', () {
|
||||||
|
// String lastImportFileName
|
||||||
|
test('to test the property `lastImportFileName`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// String lastUpdate
|
||||||
|
test('to test the property `lastUpdate`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
-5
@@ -57,10 +57,5 @@ void main() {
|
|||||||
// TODO
|
// TODO
|
||||||
});
|
});
|
||||||
|
|
||||||
//Future setAdminOnboarding() async
|
|
||||||
test('test setAdminOnboarding', () async {
|
|
||||||
// TODO
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
+36
@@ -0,0 +1,36 @@
|
|||||||
|
//
|
||||||
|
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||||
|
//
|
||||||
|
// @dart=2.12
|
||||||
|
|
||||||
|
// ignore_for_file: unused_element, unused_import
|
||||||
|
// ignore_for_file: always_put_required_named_parameters_first
|
||||||
|
// ignore_for_file: constant_identifier_names
|
||||||
|
// ignore_for_file: lines_longer_than_80_chars
|
||||||
|
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
|
||||||
|
/// tests for SystemMetadataApi
|
||||||
|
void main() {
|
||||||
|
// final instance = SystemMetadataApi();
|
||||||
|
|
||||||
|
group('tests for SystemMetadataApi', () {
|
||||||
|
//Future<AdminOnboardingUpdateDto> getAdminOnboarding() async
|
||||||
|
test('test getAdminOnboarding', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
//Future<ReverseGeocodingStateResponseDto> getReverseGeocodingState() async
|
||||||
|
test('test getReverseGeocodingState', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
//Future updateAdminOnboarding(AdminOnboardingUpdateDto adminOnboardingUpdateDto) async
|
||||||
|
test('test updateAdminOnboarding', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
+1
-1
@@ -1804,5 +1804,5 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.2"
|
version: "3.1.2"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=3.2.0 <4.0.0"
|
dart: ">=3.3.0 <4.0.0"
|
||||||
flutter: ">=3.16.0"
|
flutter: ">=3.16.0"
|
||||||
|
|||||||
+2
-2
@@ -2,10 +2,10 @@ name: immich_mobile
|
|||||||
description: Immich - selfhosted backup media file on mobile phone
|
description: Immich - selfhosted backup media file on mobile phone
|
||||||
|
|
||||||
publish_to: 'none'
|
publish_to: 'none'
|
||||||
version: 1.102.0+132
|
version: 1.102.3+136
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=3.0.0 <4.0.0'
|
sdk: '>=3.3.0 <4.0.0'
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
flutter:
|
flutter:
|
||||||
|
|||||||
+563
-157
@@ -2345,118 +2345,6 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/audit/file-report": {
|
|
||||||
"get": {
|
|
||||||
"operationId": "getAuditFiles",
|
|
||||||
"parameters": [],
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/components/schemas/FileReportDto"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"description": ""
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"security": [
|
|
||||||
{
|
|
||||||
"bearer": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cookie": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"api_key": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"tags": [
|
|
||||||
"Audit"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/audit/file-report/checksum": {
|
|
||||||
"post": {
|
|
||||||
"operationId": "getFileChecksums",
|
|
||||||
"parameters": [],
|
|
||||||
"requestBody": {
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/components/schemas/FileChecksumDto"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
"responses": {
|
|
||||||
"201": {
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"items": {
|
|
||||||
"$ref": "#/components/schemas/FileChecksumResponseDto"
|
|
||||||
},
|
|
||||||
"type": "array"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"description": ""
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"security": [
|
|
||||||
{
|
|
||||||
"bearer": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cookie": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"api_key": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"tags": [
|
|
||||||
"Audit"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/audit/file-report/fix": {
|
|
||||||
"post": {
|
|
||||||
"operationId": "fixAuditFiles",
|
|
||||||
"parameters": [],
|
|
||||||
"requestBody": {
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/components/schemas/FileReportFixDto"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
"responses": {
|
|
||||||
"201": {
|
|
||||||
"description": ""
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"security": [
|
|
||||||
{
|
|
||||||
"bearer": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cookie": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"api_key": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"tags": [
|
|
||||||
"Audit"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/auth/admin-sign-up": {
|
"/auth/admin-sign-up": {
|
||||||
"post": {
|
"post": {
|
||||||
"operationId": "signUpAdmin",
|
"operationId": "signUpAdmin",
|
||||||
@@ -4429,6 +4317,118 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/report": {
|
||||||
|
"get": {
|
||||||
|
"operationId": "getAuditFiles",
|
||||||
|
"parameters": [],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/FileReportDto"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"bearer": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cookie": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"api_key": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"File Report"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/report/checksum": {
|
||||||
|
"post": {
|
||||||
|
"operationId": "getFileChecksums",
|
||||||
|
"parameters": [],
|
||||||
|
"requestBody": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/FileChecksumDto"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"201": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/FileChecksumResponseDto"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"bearer": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cookie": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"api_key": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"File Report"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/report/fix": {
|
||||||
|
"post": {
|
||||||
|
"operationId": "fixAuditFiles",
|
||||||
|
"parameters": [],
|
||||||
|
"requestBody": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/FileReportFixDto"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"201": {
|
||||||
|
"description": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"bearer": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cookie": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"api_key": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"File Report"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
"/search": {
|
"/search": {
|
||||||
"get": {
|
"get": {
|
||||||
"deprecated": true,
|
"deprecated": true,
|
||||||
@@ -4908,31 +4908,6 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/server-info/admin-onboarding": {
|
|
||||||
"post": {
|
|
||||||
"operationId": "setAdminOnboarding",
|
|
||||||
"parameters": [],
|
|
||||||
"responses": {
|
|
||||||
"204": {
|
|
||||||
"description": ""
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"security": [
|
|
||||||
{
|
|
||||||
"bearer": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cookie": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"api_key": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"tags": [
|
|
||||||
"Server Info"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/server-info/config": {
|
"/server-info/config": {
|
||||||
"get": {
|
"get": {
|
||||||
"operationId": "getServerConfig",
|
"operationId": "getServerConfig",
|
||||||
@@ -5885,6 +5860,103 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/system-metadata/admin-onboarding": {
|
||||||
|
"get": {
|
||||||
|
"operationId": "getAdminOnboarding",
|
||||||
|
"parameters": [],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/AdminOnboardingUpdateDto"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"bearer": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cookie": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"api_key": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"System Metadata"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"post": {
|
||||||
|
"operationId": "updateAdminOnboarding",
|
||||||
|
"parameters": [],
|
||||||
|
"requestBody": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/AdminOnboardingUpdateDto"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"204": {
|
||||||
|
"description": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"bearer": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cookie": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"api_key": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"System Metadata"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/system-metadata/reverse-geocoding-state": {
|
||||||
|
"get": {
|
||||||
|
"operationId": "getReverseGeocodingState",
|
||||||
|
"parameters": [],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/ReverseGeocodingStateResponseDto"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"bearer": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cookie": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"api_key": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"System Metadata"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
"/tag": {
|
"/tag": {
|
||||||
"get": {
|
"get": {
|
||||||
"operationId": "getAllTags",
|
"operationId": "getAllTags",
|
||||||
@@ -6356,15 +6428,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"security": [
|
"security": [
|
||||||
{
|
|
||||||
"bearer": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cookie": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"api_key": []
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"bearer": []
|
"bearer": []
|
||||||
},
|
},
|
||||||
@@ -6492,15 +6555,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"security": [
|
"security": [
|
||||||
{
|
|
||||||
"bearer": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cookie": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"api_key": []
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"bearer": []
|
"bearer": []
|
||||||
},
|
},
|
||||||
@@ -7006,7 +7060,7 @@
|
|||||||
"info": {
|
"info": {
|
||||||
"title": "Immich",
|
"title": "Immich",
|
||||||
"description": "Immich API",
|
"description": "Immich API",
|
||||||
"version": "1.102.0",
|
"version": "1.102.3",
|
||||||
"contact": {}
|
"contact": {}
|
||||||
},
|
},
|
||||||
"tags": [],
|
"tags": [],
|
||||||
@@ -7180,6 +7234,17 @@
|
|||||||
],
|
],
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
|
"AdminOnboardingUpdateDto": {
|
||||||
|
"properties": {
|
||||||
|
"isOnboarded": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"isOnboarded"
|
||||||
|
],
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
"AlbumCountResponseDto": {
|
"AlbumCountResponseDto": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"notShared": {
|
"notShared": {
|
||||||
@@ -7892,6 +7957,103 @@
|
|||||||
],
|
],
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
|
"AuthorizationPermission": {
|
||||||
|
"enum": [
|
||||||
|
"activity.create",
|
||||||
|
"activity.read",
|
||||||
|
"activity.update",
|
||||||
|
"activity.delete",
|
||||||
|
"album.create",
|
||||||
|
"album.read",
|
||||||
|
"album.update",
|
||||||
|
"album.delete",
|
||||||
|
"asset.create",
|
||||||
|
"asset.read",
|
||||||
|
"asset.update",
|
||||||
|
"asset.delete",
|
||||||
|
"apiKey.create",
|
||||||
|
"apiKey.read",
|
||||||
|
"apiKey.update",
|
||||||
|
"apiKey.delete",
|
||||||
|
"authDevice.create",
|
||||||
|
"authDevice.read",
|
||||||
|
"authDevice.update",
|
||||||
|
"authDevice.delete",
|
||||||
|
"face.create",
|
||||||
|
"face.read",
|
||||||
|
"face.update",
|
||||||
|
"face.delete",
|
||||||
|
"library.create",
|
||||||
|
"library.read",
|
||||||
|
"library.update",
|
||||||
|
"library.delete",
|
||||||
|
"memory.create",
|
||||||
|
"memory.read",
|
||||||
|
"memory.update",
|
||||||
|
"memory.delete",
|
||||||
|
"memory.addAsset",
|
||||||
|
"memory.removeAsset",
|
||||||
|
"partner.create",
|
||||||
|
"partner.read",
|
||||||
|
"partner.update",
|
||||||
|
"partner.delete",
|
||||||
|
"person.create",
|
||||||
|
"person.read",
|
||||||
|
"person.update",
|
||||||
|
"person.delete",
|
||||||
|
"report.create",
|
||||||
|
"report.read",
|
||||||
|
"report.update",
|
||||||
|
"report.delete",
|
||||||
|
"session.create",
|
||||||
|
"session.read",
|
||||||
|
"session.update",
|
||||||
|
"session.delete",
|
||||||
|
"sharedLink.create",
|
||||||
|
"sharedLink.read",
|
||||||
|
"sharedLink.update",
|
||||||
|
"sharedLink.delete",
|
||||||
|
"systemConfig.create",
|
||||||
|
"systemConfig.read",
|
||||||
|
"systemConfig.update",
|
||||||
|
"systemConfig.delete",
|
||||||
|
"systemMetadata.create",
|
||||||
|
"systemMetadata.read",
|
||||||
|
"systemMetadata.update",
|
||||||
|
"systemMetadata.delete",
|
||||||
|
"stack.create",
|
||||||
|
"stack.read",
|
||||||
|
"stack.update",
|
||||||
|
"stack.delete",
|
||||||
|
"tag.create",
|
||||||
|
"tag.read",
|
||||||
|
"tag.update",
|
||||||
|
"tag.delete",
|
||||||
|
"user.create",
|
||||||
|
"user.read",
|
||||||
|
"user.update",
|
||||||
|
"user.delete",
|
||||||
|
"auth.changePassword",
|
||||||
|
"auth.oauth",
|
||||||
|
"album.addAsset",
|
||||||
|
"album.removeAsset",
|
||||||
|
"album.addUser",
|
||||||
|
"album.removeUser",
|
||||||
|
"asset.viewThumb",
|
||||||
|
"asset.viewPreview",
|
||||||
|
"asset.viewOriginal",
|
||||||
|
"asset.upload",
|
||||||
|
"asset.download",
|
||||||
|
"job.read",
|
||||||
|
"job.run",
|
||||||
|
"map.read",
|
||||||
|
"user.readSimple",
|
||||||
|
"user.changePassword",
|
||||||
|
"server.read",
|
||||||
|
"server.setup"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"BulkIdResponseDto": {
|
"BulkIdResponseDto": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"error": {
|
"error": {
|
||||||
@@ -8201,6 +8363,15 @@
|
|||||||
"password": {
|
"password": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"permissionPreset": {
|
||||||
|
"$ref": "#/components/schemas/PermissionPreset"
|
||||||
|
},
|
||||||
|
"permissions": {
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/AuthorizationPermission"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
},
|
||||||
"quotaSizeInBytes": {
|
"quotaSizeInBytes": {
|
||||||
"format": "int64",
|
"format": "int64",
|
||||||
"nullable": true,
|
"nullable": true,
|
||||||
@@ -8217,7 +8388,8 @@
|
|||||||
"required": [
|
"required": [
|
||||||
"email",
|
"email",
|
||||||
"name",
|
"name",
|
||||||
"password"
|
"password",
|
||||||
|
"permissionPreset"
|
||||||
],
|
],
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
@@ -9281,6 +9453,106 @@
|
|||||||
"oauthId": {
|
"oauthId": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"permissions": {
|
||||||
|
"items": {
|
||||||
|
"enum": [
|
||||||
|
"activity.create",
|
||||||
|
"activity.read",
|
||||||
|
"activity.update",
|
||||||
|
"activity.delete",
|
||||||
|
"album.create",
|
||||||
|
"album.read",
|
||||||
|
"album.update",
|
||||||
|
"album.delete",
|
||||||
|
"asset.create",
|
||||||
|
"asset.read",
|
||||||
|
"asset.update",
|
||||||
|
"asset.delete",
|
||||||
|
"apiKey.create",
|
||||||
|
"apiKey.read",
|
||||||
|
"apiKey.update",
|
||||||
|
"apiKey.delete",
|
||||||
|
"authDevice.create",
|
||||||
|
"authDevice.read",
|
||||||
|
"authDevice.update",
|
||||||
|
"authDevice.delete",
|
||||||
|
"face.create",
|
||||||
|
"face.read",
|
||||||
|
"face.update",
|
||||||
|
"face.delete",
|
||||||
|
"library.create",
|
||||||
|
"library.read",
|
||||||
|
"library.update",
|
||||||
|
"library.delete",
|
||||||
|
"memory.create",
|
||||||
|
"memory.read",
|
||||||
|
"memory.update",
|
||||||
|
"memory.delete",
|
||||||
|
"memory.addAsset",
|
||||||
|
"memory.removeAsset",
|
||||||
|
"partner.create",
|
||||||
|
"partner.read",
|
||||||
|
"partner.update",
|
||||||
|
"partner.delete",
|
||||||
|
"person.create",
|
||||||
|
"person.read",
|
||||||
|
"person.update",
|
||||||
|
"person.delete",
|
||||||
|
"report.create",
|
||||||
|
"report.read",
|
||||||
|
"report.update",
|
||||||
|
"report.delete",
|
||||||
|
"session.create",
|
||||||
|
"session.read",
|
||||||
|
"session.update",
|
||||||
|
"session.delete",
|
||||||
|
"sharedLink.create",
|
||||||
|
"sharedLink.read",
|
||||||
|
"sharedLink.update",
|
||||||
|
"sharedLink.delete",
|
||||||
|
"systemConfig.create",
|
||||||
|
"systemConfig.read",
|
||||||
|
"systemConfig.update",
|
||||||
|
"systemConfig.delete",
|
||||||
|
"systemMetadata.create",
|
||||||
|
"systemMetadata.read",
|
||||||
|
"systemMetadata.update",
|
||||||
|
"systemMetadata.delete",
|
||||||
|
"stack.create",
|
||||||
|
"stack.read",
|
||||||
|
"stack.update",
|
||||||
|
"stack.delete",
|
||||||
|
"tag.create",
|
||||||
|
"tag.read",
|
||||||
|
"tag.update",
|
||||||
|
"tag.delete",
|
||||||
|
"user.create",
|
||||||
|
"user.read",
|
||||||
|
"user.update",
|
||||||
|
"user.delete",
|
||||||
|
"auth.changePassword",
|
||||||
|
"auth.oauth",
|
||||||
|
"album.addAsset",
|
||||||
|
"album.removeAsset",
|
||||||
|
"album.addUser",
|
||||||
|
"album.removeUser",
|
||||||
|
"asset.viewThumb",
|
||||||
|
"asset.viewPreview",
|
||||||
|
"asset.viewOriginal",
|
||||||
|
"asset.upload",
|
||||||
|
"asset.download",
|
||||||
|
"job.read",
|
||||||
|
"job.run",
|
||||||
|
"map.read",
|
||||||
|
"user.readSimple",
|
||||||
|
"user.changePassword",
|
||||||
|
"server.read",
|
||||||
|
"server.setup"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
},
|
||||||
"profileImagePath": {
|
"profileImagePath": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
@@ -9414,6 +9686,14 @@
|
|||||||
],
|
],
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
|
"PermissionPreset": {
|
||||||
|
"enum": [
|
||||||
|
"user",
|
||||||
|
"admin",
|
||||||
|
"custom"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"PersonCreateDto": {
|
"PersonCreateDto": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"birthDate": {
|
"birthDate": {
|
||||||
@@ -9618,6 +9898,23 @@
|
|||||||
],
|
],
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
|
"ReverseGeocodingStateResponseDto": {
|
||||||
|
"properties": {
|
||||||
|
"lastImportFileName": {
|
||||||
|
"nullable": true,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"lastUpdate": {
|
||||||
|
"nullable": true,
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"lastImportFileName",
|
||||||
|
"lastUpdate"
|
||||||
|
],
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
"ScanLibraryDto": {
|
"ScanLibraryDto": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"refreshAllFiles": {
|
"refreshAllFiles": {
|
||||||
@@ -11152,6 +11449,15 @@
|
|||||||
"password": {
|
"password": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"permissionPreset": {
|
||||||
|
"$ref": "#/components/schemas/PermissionPreset"
|
||||||
|
},
|
||||||
|
"permissions": {
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/AuthorizationPermission"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
},
|
||||||
"quotaSizeInBytes": {
|
"quotaSizeInBytes": {
|
||||||
"format": "int64",
|
"format": "int64",
|
||||||
"nullable": true,
|
"nullable": true,
|
||||||
@@ -11277,6 +11583,106 @@
|
|||||||
"oauthId": {
|
"oauthId": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"permissions": {
|
||||||
|
"items": {
|
||||||
|
"enum": [
|
||||||
|
"activity.create",
|
||||||
|
"activity.read",
|
||||||
|
"activity.update",
|
||||||
|
"activity.delete",
|
||||||
|
"album.create",
|
||||||
|
"album.read",
|
||||||
|
"album.update",
|
||||||
|
"album.delete",
|
||||||
|
"asset.create",
|
||||||
|
"asset.read",
|
||||||
|
"asset.update",
|
||||||
|
"asset.delete",
|
||||||
|
"apiKey.create",
|
||||||
|
"apiKey.read",
|
||||||
|
"apiKey.update",
|
||||||
|
"apiKey.delete",
|
||||||
|
"authDevice.create",
|
||||||
|
"authDevice.read",
|
||||||
|
"authDevice.update",
|
||||||
|
"authDevice.delete",
|
||||||
|
"face.create",
|
||||||
|
"face.read",
|
||||||
|
"face.update",
|
||||||
|
"face.delete",
|
||||||
|
"library.create",
|
||||||
|
"library.read",
|
||||||
|
"library.update",
|
||||||
|
"library.delete",
|
||||||
|
"memory.create",
|
||||||
|
"memory.read",
|
||||||
|
"memory.update",
|
||||||
|
"memory.delete",
|
||||||
|
"memory.addAsset",
|
||||||
|
"memory.removeAsset",
|
||||||
|
"partner.create",
|
||||||
|
"partner.read",
|
||||||
|
"partner.update",
|
||||||
|
"partner.delete",
|
||||||
|
"person.create",
|
||||||
|
"person.read",
|
||||||
|
"person.update",
|
||||||
|
"person.delete",
|
||||||
|
"report.create",
|
||||||
|
"report.read",
|
||||||
|
"report.update",
|
||||||
|
"report.delete",
|
||||||
|
"session.create",
|
||||||
|
"session.read",
|
||||||
|
"session.update",
|
||||||
|
"session.delete",
|
||||||
|
"sharedLink.create",
|
||||||
|
"sharedLink.read",
|
||||||
|
"sharedLink.update",
|
||||||
|
"sharedLink.delete",
|
||||||
|
"systemConfig.create",
|
||||||
|
"systemConfig.read",
|
||||||
|
"systemConfig.update",
|
||||||
|
"systemConfig.delete",
|
||||||
|
"systemMetadata.create",
|
||||||
|
"systemMetadata.read",
|
||||||
|
"systemMetadata.update",
|
||||||
|
"systemMetadata.delete",
|
||||||
|
"stack.create",
|
||||||
|
"stack.read",
|
||||||
|
"stack.update",
|
||||||
|
"stack.delete",
|
||||||
|
"tag.create",
|
||||||
|
"tag.read",
|
||||||
|
"tag.update",
|
||||||
|
"tag.delete",
|
||||||
|
"user.create",
|
||||||
|
"user.read",
|
||||||
|
"user.update",
|
||||||
|
"user.delete",
|
||||||
|
"auth.changePassword",
|
||||||
|
"auth.oauth",
|
||||||
|
"album.addAsset",
|
||||||
|
"album.removeAsset",
|
||||||
|
"album.addUser",
|
||||||
|
"album.removeUser",
|
||||||
|
"asset.viewThumb",
|
||||||
|
"asset.viewPreview",
|
||||||
|
"asset.viewOriginal",
|
||||||
|
"asset.upload",
|
||||||
|
"asset.download",
|
||||||
|
"job.read",
|
||||||
|
"job.run",
|
||||||
|
"map.read",
|
||||||
|
"user.readSimple",
|
||||||
|
"user.changePassword",
|
||||||
|
"server.read",
|
||||||
|
"server.setup"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
},
|
||||||
"profileImagePath": {
|
"profileImagePath": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
|||||||
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "@immich/sdk",
|
"name": "@immich/sdk",
|
||||||
"version": "1.102.0",
|
"version": "1.102.3",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@immich/sdk",
|
"name": "@immich/sdk",
|
||||||
"version": "1.102.0",
|
"version": "1.102.3",
|
||||||
"license": "GNU Affero General Public License version 3",
|
"license": "GNU Affero General Public License version 3",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@oazapfts/runtime": "^1.0.2"
|
"@oazapfts/runtime": "^1.0.2"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@immich/sdk",
|
"name": "@immich/sdk",
|
||||||
"version": "1.102.0",
|
"version": "1.102.3",
|
||||||
"description": "Auto-generated TypeScript SDK for the Immich API",
|
"description": "Auto-generated TypeScript SDK for the Immich API",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./build/index.js",
|
"main": "./build/index.js",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Immich
|
* Immich
|
||||||
* 1.102.0
|
* 1.102.3
|
||||||
* DO NOT MODIFY - This file has been generated using oazapfts.
|
* DO NOT MODIFY - This file has been generated using oazapfts.
|
||||||
* See https://www.npmjs.com/package/oazapfts
|
* See https://www.npmjs.com/package/oazapfts
|
||||||
*/
|
*/
|
||||||
@@ -71,6 +71,7 @@ export type UserResponseDto = {
|
|||||||
memoriesEnabled?: boolean;
|
memoriesEnabled?: boolean;
|
||||||
name: string;
|
name: string;
|
||||||
oauthId: string;
|
oauthId: string;
|
||||||
|
permissions?: ("activity.create" | "activity.read" | "activity.update" | "activity.delete" | "album.create" | "album.read" | "album.update" | "album.delete" | "apiKey.create" | "apiKey.read" | "apiKey.update" | "apiKey.delete" | "asset.create" | "asset.read" | "asset.update" | "asset.delete" | "authDevice.create" | "authDevice.read" | "authDevice.update" | "authDevice.delete" | "face.create" | "face.read" | "face.update" | "face.delete" | "memory.create" | "memory.read" | "memory.update" | "memory.delete" | "partner.create" | "partner.read" | "partner.update" | "partner.delete" | "person.create" | "person.read" | "person.update" | "person.delete" | "sharedLink.create" | "sharedLink.read" | "sharedLink.update" | "sharedLink.delete" | "systemConfig.read" | "systemConfig.update" | "systemConfig.delete" | "stack.create" | "stack.read" | "stack.update" | "stack.delete" | "tag.create" | "tag.read" | "tag.update" | "tag.delete" | "user.create" | "user.readSimple" | "user.read" | "user.update" | "user.delete")[];
|
||||||
profileImagePath: string;
|
profileImagePath: string;
|
||||||
quotaSizeInBytes: number | null;
|
quotaSizeInBytes: number | null;
|
||||||
quotaUsageInBytes: number | null;
|
quotaUsageInBytes: number | null;
|
||||||
@@ -316,27 +317,6 @@ export type AuditDeletesResponseDto = {
|
|||||||
ids: string[];
|
ids: string[];
|
||||||
needsFullSync: boolean;
|
needsFullSync: boolean;
|
||||||
};
|
};
|
||||||
export type FileReportItemDto = {
|
|
||||||
checksum?: string;
|
|
||||||
entityId: string;
|
|
||||||
entityType: PathEntityType;
|
|
||||||
pathType: PathType;
|
|
||||||
pathValue: string;
|
|
||||||
};
|
|
||||||
export type FileReportDto = {
|
|
||||||
extras: string[];
|
|
||||||
orphans: FileReportItemDto[];
|
|
||||||
};
|
|
||||||
export type FileChecksumDto = {
|
|
||||||
filenames: string[];
|
|
||||||
};
|
|
||||||
export type FileChecksumResponseDto = {
|
|
||||||
checksum: string;
|
|
||||||
filename: string;
|
|
||||||
};
|
|
||||||
export type FileReportFixDto = {
|
|
||||||
items: FileReportItemDto[];
|
|
||||||
};
|
|
||||||
export type SignUpDto = {
|
export type SignUpDto = {
|
||||||
email: string;
|
email: string;
|
||||||
name: string;
|
name: string;
|
||||||
@@ -534,6 +514,7 @@ export type PartnerResponseDto = {
|
|||||||
memoriesEnabled?: boolean;
|
memoriesEnabled?: boolean;
|
||||||
name: string;
|
name: string;
|
||||||
oauthId: string;
|
oauthId: string;
|
||||||
|
permissions?: ("activity.create" | "activity.read" | "activity.update" | "activity.delete" | "album.create" | "album.read" | "album.update" | "album.delete" | "apiKey.create" | "apiKey.read" | "apiKey.update" | "apiKey.delete" | "asset.create" | "asset.read" | "asset.update" | "asset.delete" | "authDevice.create" | "authDevice.read" | "authDevice.update" | "authDevice.delete" | "face.create" | "face.read" | "face.update" | "face.delete" | "memory.create" | "memory.read" | "memory.update" | "memory.delete" | "partner.create" | "partner.read" | "partner.update" | "partner.delete" | "person.create" | "person.read" | "person.update" | "person.delete" | "sharedLink.create" | "sharedLink.read" | "sharedLink.update" | "sharedLink.delete" | "systemConfig.read" | "systemConfig.update" | "systemConfig.delete" | "stack.create" | "stack.read" | "stack.update" | "stack.delete" | "tag.create" | "tag.read" | "tag.update" | "tag.delete" | "user.create" | "user.readSimple" | "user.read" | "user.update" | "user.delete")[];
|
||||||
profileImagePath: string;
|
profileImagePath: string;
|
||||||
quotaSizeInBytes: number | null;
|
quotaSizeInBytes: number | null;
|
||||||
quotaUsageInBytes: number | null;
|
quotaUsageInBytes: number | null;
|
||||||
@@ -599,6 +580,27 @@ export type AssetFaceUpdateDto = {
|
|||||||
export type PersonStatisticsResponseDto = {
|
export type PersonStatisticsResponseDto = {
|
||||||
assets: number;
|
assets: number;
|
||||||
};
|
};
|
||||||
|
export type FileReportItemDto = {
|
||||||
|
checksum?: string;
|
||||||
|
entityId: string;
|
||||||
|
entityType: PathEntityType;
|
||||||
|
pathType: PathType;
|
||||||
|
pathValue: string;
|
||||||
|
};
|
||||||
|
export type FileReportDto = {
|
||||||
|
extras: string[];
|
||||||
|
orphans: FileReportItemDto[];
|
||||||
|
};
|
||||||
|
export type FileChecksumDto = {
|
||||||
|
filenames: string[];
|
||||||
|
};
|
||||||
|
export type FileChecksumResponseDto = {
|
||||||
|
checksum: string;
|
||||||
|
filename: string;
|
||||||
|
};
|
||||||
|
export type FileReportFixDto = {
|
||||||
|
items: FileReportItemDto[];
|
||||||
|
};
|
||||||
export type SearchFacetCountResponseDto = {
|
export type SearchFacetCountResponseDto = {
|
||||||
count: number;
|
count: number;
|
||||||
value: string;
|
value: string;
|
||||||
@@ -998,6 +1000,13 @@ export type SystemConfigTemplateStorageOptionDto = {
|
|||||||
weekOptions: string[];
|
weekOptions: string[];
|
||||||
yearOptions: string[];
|
yearOptions: string[];
|
||||||
};
|
};
|
||||||
|
export type AdminOnboardingUpdateDto = {
|
||||||
|
isOnboarded: boolean;
|
||||||
|
};
|
||||||
|
export type ReverseGeocodingStateResponseDto = {
|
||||||
|
lastImportFileName: string | null;
|
||||||
|
lastUpdate: string | null;
|
||||||
|
};
|
||||||
export type CreateTagDto = {
|
export type CreateTagDto = {
|
||||||
name: string;
|
name: string;
|
||||||
"type": TagTypeEnum;
|
"type": TagTypeEnum;
|
||||||
@@ -1014,6 +1023,8 @@ export type CreateUserDto = {
|
|||||||
memoriesEnabled?: boolean;
|
memoriesEnabled?: boolean;
|
||||||
name: string;
|
name: string;
|
||||||
password: string;
|
password: string;
|
||||||
|
permissionPreset: PermissionPreset;
|
||||||
|
permissions?: AuthorizationPermission[];
|
||||||
quotaSizeInBytes?: number | null;
|
quotaSizeInBytes?: number | null;
|
||||||
shouldChangePassword?: boolean;
|
shouldChangePassword?: boolean;
|
||||||
storageLabel?: string | null;
|
storageLabel?: string | null;
|
||||||
@@ -1026,6 +1037,8 @@ export type UpdateUserDto = {
|
|||||||
memoriesEnabled?: boolean;
|
memoriesEnabled?: boolean;
|
||||||
name?: string;
|
name?: string;
|
||||||
password?: string;
|
password?: string;
|
||||||
|
permissionPreset?: PermissionPreset;
|
||||||
|
permissions?: AuthorizationPermission[];
|
||||||
quotaSizeInBytes?: number | null;
|
quotaSizeInBytes?: number | null;
|
||||||
shouldChangePassword?: boolean;
|
shouldChangePassword?: boolean;
|
||||||
storageLabel?: string;
|
storageLabel?: string;
|
||||||
@@ -1651,35 +1664,6 @@ export function getAuditDeletes({ after, entityType, userId }: {
|
|||||||
...opts
|
...opts
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
export function getAuditFiles(opts?: Oazapfts.RequestOpts) {
|
|
||||||
return oazapfts.ok(oazapfts.fetchJson<{
|
|
||||||
status: 200;
|
|
||||||
data: FileReportDto;
|
|
||||||
}>("/audit/file-report", {
|
|
||||||
...opts
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
export function getFileChecksums({ fileChecksumDto }: {
|
|
||||||
fileChecksumDto: FileChecksumDto;
|
|
||||||
}, opts?: Oazapfts.RequestOpts) {
|
|
||||||
return oazapfts.ok(oazapfts.fetchJson<{
|
|
||||||
status: 201;
|
|
||||||
data: FileChecksumResponseDto[];
|
|
||||||
}>("/audit/file-report/checksum", oazapfts.json({
|
|
||||||
...opts,
|
|
||||||
method: "POST",
|
|
||||||
body: fileChecksumDto
|
|
||||||
})));
|
|
||||||
}
|
|
||||||
export function fixAuditFiles({ fileReportFixDto }: {
|
|
||||||
fileReportFixDto: FileReportFixDto;
|
|
||||||
}, opts?: Oazapfts.RequestOpts) {
|
|
||||||
return oazapfts.ok(oazapfts.fetchText("/audit/file-report/fix", oazapfts.json({
|
|
||||||
...opts,
|
|
||||||
method: "POST",
|
|
||||||
body: fileReportFixDto
|
|
||||||
})));
|
|
||||||
}
|
|
||||||
export function signUpAdmin({ signUpDto }: {
|
export function signUpAdmin({ signUpDto }: {
|
||||||
signUpDto: SignUpDto;
|
signUpDto: SignUpDto;
|
||||||
}, opts?: Oazapfts.RequestOpts) {
|
}, opts?: Oazapfts.RequestOpts) {
|
||||||
@@ -2206,6 +2190,35 @@ export function getPersonThumbnail({ id }: {
|
|||||||
...opts
|
...opts
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
export function getAuditFiles(opts?: Oazapfts.RequestOpts) {
|
||||||
|
return oazapfts.ok(oazapfts.fetchJson<{
|
||||||
|
status: 200;
|
||||||
|
data: FileReportDto;
|
||||||
|
}>("/report", {
|
||||||
|
...opts
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
export function getFileChecksums({ fileChecksumDto }: {
|
||||||
|
fileChecksumDto: FileChecksumDto;
|
||||||
|
}, opts?: Oazapfts.RequestOpts) {
|
||||||
|
return oazapfts.ok(oazapfts.fetchJson<{
|
||||||
|
status: 201;
|
||||||
|
data: FileChecksumResponseDto[];
|
||||||
|
}>("/report/checksum", oazapfts.json({
|
||||||
|
...opts,
|
||||||
|
method: "POST",
|
||||||
|
body: fileChecksumDto
|
||||||
|
})));
|
||||||
|
}
|
||||||
|
export function fixAuditFiles({ fileReportFixDto }: {
|
||||||
|
fileReportFixDto: FileReportFixDto;
|
||||||
|
}, opts?: Oazapfts.RequestOpts) {
|
||||||
|
return oazapfts.ok(oazapfts.fetchText("/report/fix", oazapfts.json({
|
||||||
|
...opts,
|
||||||
|
method: "POST",
|
||||||
|
body: fileReportFixDto
|
||||||
|
})));
|
||||||
|
}
|
||||||
export function search({ clip, motion, page, q, query, recent, size, smart, $type, withArchived }: {
|
export function search({ clip, motion, page, q, query, recent, size, smart, $type, withArchived }: {
|
||||||
clip?: boolean;
|
clip?: boolean;
|
||||||
motion?: boolean;
|
motion?: boolean;
|
||||||
@@ -2330,12 +2343,6 @@ export function getServerInfo(opts?: Oazapfts.RequestOpts) {
|
|||||||
...opts
|
...opts
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
export function setAdminOnboarding(opts?: Oazapfts.RequestOpts) {
|
|
||||||
return oazapfts.ok(oazapfts.fetchText("/server-info/admin-onboarding", {
|
|
||||||
...opts,
|
|
||||||
method: "POST"
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
export function getServerConfig(opts?: Oazapfts.RequestOpts) {
|
export function getServerConfig(opts?: Oazapfts.RequestOpts) {
|
||||||
return oazapfts.ok(oazapfts.fetchJson<{
|
return oazapfts.ok(oazapfts.fetchJson<{
|
||||||
status: 200;
|
status: 200;
|
||||||
@@ -2597,6 +2604,31 @@ export function getStorageTemplateOptions(opts?: Oazapfts.RequestOpts) {
|
|||||||
...opts
|
...opts
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
export function getAdminOnboarding(opts?: Oazapfts.RequestOpts) {
|
||||||
|
return oazapfts.ok(oazapfts.fetchJson<{
|
||||||
|
status: 200;
|
||||||
|
data: AdminOnboardingUpdateDto;
|
||||||
|
}>("/system-metadata/admin-onboarding", {
|
||||||
|
...opts
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
export function updateAdminOnboarding({ adminOnboardingUpdateDto }: {
|
||||||
|
adminOnboardingUpdateDto: AdminOnboardingUpdateDto;
|
||||||
|
}, opts?: Oazapfts.RequestOpts) {
|
||||||
|
return oazapfts.ok(oazapfts.fetchText("/system-metadata/admin-onboarding", oazapfts.json({
|
||||||
|
...opts,
|
||||||
|
method: "POST",
|
||||||
|
body: adminOnboardingUpdateDto
|
||||||
|
})));
|
||||||
|
}
|
||||||
|
export function getReverseGeocodingState(opts?: Oazapfts.RequestOpts) {
|
||||||
|
return oazapfts.ok(oazapfts.fetchJson<{
|
||||||
|
status: 200;
|
||||||
|
data: ReverseGeocodingStateResponseDto;
|
||||||
|
}>("/system-metadata/reverse-geocoding-state", {
|
||||||
|
...opts
|
||||||
|
}));
|
||||||
|
}
|
||||||
export function getAllTags(opts?: Oazapfts.RequestOpts) {
|
export function getAllTags(opts?: Oazapfts.RequestOpts) {
|
||||||
return oazapfts.ok(oazapfts.fetchJson<{
|
return oazapfts.ok(oazapfts.fetchJson<{
|
||||||
status: 200;
|
status: 200;
|
||||||
@@ -2948,20 +2980,6 @@ export enum EntityType {
|
|||||||
Asset = "ASSET",
|
Asset = "ASSET",
|
||||||
Album = "ALBUM"
|
Album = "ALBUM"
|
||||||
}
|
}
|
||||||
export enum PathEntityType {
|
|
||||||
Asset = "asset",
|
|
||||||
Person = "person",
|
|
||||||
User = "user"
|
|
||||||
}
|
|
||||||
export enum PathType {
|
|
||||||
Original = "original",
|
|
||||||
Preview = "preview",
|
|
||||||
Thumbnail = "thumbnail",
|
|
||||||
EncodedVideo = "encoded_video",
|
|
||||||
Sidecar = "sidecar",
|
|
||||||
Face = "face",
|
|
||||||
Profile = "profile"
|
|
||||||
}
|
|
||||||
export enum JobName {
|
export enum JobName {
|
||||||
ThumbnailGeneration = "thumbnailGeneration",
|
ThumbnailGeneration = "thumbnailGeneration",
|
||||||
MetadataExtraction = "metadataExtraction",
|
MetadataExtraction = "metadataExtraction",
|
||||||
@@ -2993,6 +3011,20 @@ export enum Type2 {
|
|||||||
export enum MemoryType {
|
export enum MemoryType {
|
||||||
OnThisDay = "on_this_day"
|
OnThisDay = "on_this_day"
|
||||||
}
|
}
|
||||||
|
export enum PathEntityType {
|
||||||
|
Asset = "asset",
|
||||||
|
Person = "person",
|
||||||
|
User = "user"
|
||||||
|
}
|
||||||
|
export enum PathType {
|
||||||
|
Original = "original",
|
||||||
|
Preview = "preview",
|
||||||
|
Thumbnail = "thumbnail",
|
||||||
|
EncodedVideo = "encoded_video",
|
||||||
|
Sidecar = "sidecar",
|
||||||
|
Face = "face",
|
||||||
|
Profile = "profile"
|
||||||
|
}
|
||||||
export enum SearchSuggestionType {
|
export enum SearchSuggestionType {
|
||||||
Country = "country",
|
Country = "country",
|
||||||
State = "state",
|
State = "state",
|
||||||
@@ -3077,3 +3109,66 @@ export enum TimeBucketSize {
|
|||||||
Day = "DAY",
|
Day = "DAY",
|
||||||
Month = "MONTH"
|
Month = "MONTH"
|
||||||
}
|
}
|
||||||
|
export enum PermissionPreset {
|
||||||
|
User = "user",
|
||||||
|
Admin = "admin",
|
||||||
|
Custom = "custom"
|
||||||
|
}
|
||||||
|
export enum AuthorizationPermission {
|
||||||
|
ActivityCreate = "activity.create",
|
||||||
|
ActivityRead = "activity.read",
|
||||||
|
ActivityUpdate = "activity.update",
|
||||||
|
ActivityDelete = "activity.delete",
|
||||||
|
AlbumCreate = "album.create",
|
||||||
|
AlbumRead = "album.read",
|
||||||
|
AlbumUpdate = "album.update",
|
||||||
|
AlbumDelete = "album.delete",
|
||||||
|
ApiKeyCreate = "apiKey.create",
|
||||||
|
ApiKeyRead = "apiKey.read",
|
||||||
|
ApiKeyUpdate = "apiKey.update",
|
||||||
|
ApiKeyDelete = "apiKey.delete",
|
||||||
|
AssetCreate = "asset.create",
|
||||||
|
AssetRead = "asset.read",
|
||||||
|
AssetUpdate = "asset.update",
|
||||||
|
AssetDelete = "asset.delete",
|
||||||
|
AuthDeviceCreate = "authDevice.create",
|
||||||
|
AuthDeviceRead = "authDevice.read",
|
||||||
|
AuthDeviceUpdate = "authDevice.update",
|
||||||
|
AuthDeviceDelete = "authDevice.delete",
|
||||||
|
FaceCreate = "face.create",
|
||||||
|
FaceRead = "face.read",
|
||||||
|
FaceUpdate = "face.update",
|
||||||
|
FaceDelete = "face.delete",
|
||||||
|
MemoryCreate = "memory.create",
|
||||||
|
MemoryRead = "memory.read",
|
||||||
|
MemoryUpdate = "memory.update",
|
||||||
|
MemoryDelete = "memory.delete",
|
||||||
|
PartnerCreate = "partner.create",
|
||||||
|
PartnerRead = "partner.read",
|
||||||
|
PartnerUpdate = "partner.update",
|
||||||
|
PartnerDelete = "partner.delete",
|
||||||
|
PersonCreate = "person.create",
|
||||||
|
PersonRead = "person.read",
|
||||||
|
PersonUpdate = "person.update",
|
||||||
|
PersonDelete = "person.delete",
|
||||||
|
SharedLinkCreate = "sharedLink.create",
|
||||||
|
SharedLinkRead = "sharedLink.read",
|
||||||
|
SharedLinkUpdate = "sharedLink.update",
|
||||||
|
SharedLinkDelete = "sharedLink.delete",
|
||||||
|
SystemConfigRead = "systemConfig.read",
|
||||||
|
SystemConfigUpdate = "systemConfig.update",
|
||||||
|
SystemConfigDelete = "systemConfig.delete",
|
||||||
|
StackCreate = "stack.create",
|
||||||
|
StackRead = "stack.read",
|
||||||
|
StackUpdate = "stack.update",
|
||||||
|
StackDelete = "stack.delete",
|
||||||
|
TagCreate = "tag.create",
|
||||||
|
TagRead = "tag.read",
|
||||||
|
TagUpdate = "tag.update",
|
||||||
|
TagDelete = "tag.delete",
|
||||||
|
UserCreate = "user.create",
|
||||||
|
UserReadSimple = "user.readSimple",
|
||||||
|
UserRead = "user.read",
|
||||||
|
UserUpdate = "user.update",
|
||||||
|
UserDelete = "user.delete"
|
||||||
|
}
|
||||||
|
|||||||
+2
-1
@@ -27,7 +27,8 @@
|
|||||||
"matchFileNames": ["mobile/**"],
|
"matchFileNames": ["mobile/**"],
|
||||||
"groupName": "mobile",
|
"groupName": "mobile",
|
||||||
"matchUpdateTypes": ["minor", "patch"],
|
"matchUpdateTypes": ["minor", "patch"],
|
||||||
"schedule": "on tuesday"
|
"schedule": "on tuesday",
|
||||||
|
"addLabels": ["📱mobile"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"groupName": "exiftool",
|
"groupName": "exiftool",
|
||||||
|
|||||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "immich",
|
"name": "immich",
|
||||||
"version": "1.102.0",
|
"version": "1.102.3",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "immich",
|
"name": "immich",
|
||||||
"version": "1.102.0",
|
"version": "1.102.3",
|
||||||
"license": "GNU Affero General Public License version 3",
|
"license": "GNU Affero General Public License version 3",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nestjs/bullmq": "^10.0.1",
|
"@nestjs/bullmq": "^10.0.1",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "immich",
|
"name": "immich",
|
||||||
"version": "1.102.0",
|
"version": "1.102.3",
|
||||||
"description": "",
|
"description": "",
|
||||||
"author": "",
|
"author": "",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
|||||||
@@ -8,28 +8,30 @@ import {
|
|||||||
ActivitySearchDto,
|
ActivitySearchDto,
|
||||||
ActivityStatisticsResponseDto,
|
ActivityStatisticsResponseDto,
|
||||||
} from 'src/dtos/activity.dto';
|
} from 'src/dtos/activity.dto';
|
||||||
import { AuthDto } from 'src/dtos/auth.dto';
|
import { AuthDto, Permission } from 'src/dtos/auth.dto';
|
||||||
import { Auth, Authenticated } from 'src/middleware/auth.guard';
|
import { Auth, Authenticated } from 'src/middleware/auth.guard';
|
||||||
import { ActivityService } from 'src/services/activity.service';
|
import { ActivityService } from 'src/services/activity.service';
|
||||||
import { UUIDParamDto } from 'src/validation';
|
import { UUIDParamDto } from 'src/validation';
|
||||||
|
|
||||||
@ApiTags('Activity')
|
@ApiTags('Activity')
|
||||||
@Controller('activity')
|
@Controller('activity')
|
||||||
@Authenticated()
|
|
||||||
export class ActivityController {
|
export class ActivityController {
|
||||||
constructor(private service: ActivityService) {}
|
constructor(private service: ActivityService) {}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
|
@Authenticated(Permission.ACTIVITY_READ)
|
||||||
getActivities(@Auth() auth: AuthDto, @Query() dto: ActivitySearchDto): Promise<ActivityResponseDto[]> {
|
getActivities(@Auth() auth: AuthDto, @Query() dto: ActivitySearchDto): Promise<ActivityResponseDto[]> {
|
||||||
return this.service.getAll(auth, dto);
|
return this.service.getAll(auth, dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get('statistics')
|
@Get('statistics')
|
||||||
|
@Authenticated(Permission.ACTIVITY_READ)
|
||||||
getActivityStatistics(@Auth() auth: AuthDto, @Query() dto: ActivityDto): Promise<ActivityStatisticsResponseDto> {
|
getActivityStatistics(@Auth() auth: AuthDto, @Query() dto: ActivityDto): Promise<ActivityStatisticsResponseDto> {
|
||||||
return this.service.getStatistics(auth, dto);
|
return this.service.getStatistics(auth, dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post()
|
@Post()
|
||||||
|
@Authenticated(Permission.ACTIVITY_CREATE)
|
||||||
async createActivity(
|
async createActivity(
|
||||||
@Auth() auth: AuthDto,
|
@Auth() auth: AuthDto,
|
||||||
@Body() dto: ActivityCreateDto,
|
@Body() dto: ActivityCreateDto,
|
||||||
@@ -43,6 +45,7 @@ export class ActivityController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Delete(':id')
|
@Delete(':id')
|
||||||
|
@Authenticated(Permission.ACTIVITY_DELETE)
|
||||||
@HttpCode(HttpStatus.NO_CONTENT)
|
@HttpCode(HttpStatus.NO_CONTENT)
|
||||||
deleteActivity(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<void> {
|
deleteActivity(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<void> {
|
||||||
return this.service.delete(auth, id);
|
return this.service.delete(auth, id);
|
||||||
|
|||||||
@@ -10,34 +10,36 @@ import {
|
|||||||
UpdateAlbumDto,
|
UpdateAlbumDto,
|
||||||
} from 'src/dtos/album.dto';
|
} from 'src/dtos/album.dto';
|
||||||
import { BulkIdResponseDto, BulkIdsDto } from 'src/dtos/asset-ids.response.dto';
|
import { BulkIdResponseDto, BulkIdsDto } from 'src/dtos/asset-ids.response.dto';
|
||||||
import { AuthDto } from 'src/dtos/auth.dto';
|
import { AuthDto, Permission } from 'src/dtos/auth.dto';
|
||||||
import { Auth, Authenticated, SharedLinkRoute } from 'src/middleware/auth.guard';
|
import { Auth, Authenticated } from 'src/middleware/auth.guard';
|
||||||
import { AlbumService } from 'src/services/album.service';
|
import { AlbumService } from 'src/services/album.service';
|
||||||
import { ParseMeUUIDPipe, UUIDParamDto } from 'src/validation';
|
import { ParseMeUUIDPipe, UUIDParamDto } from 'src/validation';
|
||||||
|
|
||||||
@ApiTags('Album')
|
@ApiTags('Album')
|
||||||
@Controller('album')
|
@Controller('album')
|
||||||
@Authenticated()
|
|
||||||
export class AlbumController {
|
export class AlbumController {
|
||||||
constructor(private service: AlbumService) {}
|
constructor(private service: AlbumService) {}
|
||||||
|
|
||||||
@Get('count')
|
@Get('count')
|
||||||
|
@Authenticated(Permission.ALBUM_READ)
|
||||||
getAlbumCount(@Auth() auth: AuthDto): Promise<AlbumCountResponseDto> {
|
getAlbumCount(@Auth() auth: AuthDto): Promise<AlbumCountResponseDto> {
|
||||||
return this.service.getCount(auth);
|
return this.service.getCount(auth);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
|
@Authenticated(Permission.ALBUM_READ)
|
||||||
getAllAlbums(@Auth() auth: AuthDto, @Query() query: GetAlbumsDto): Promise<AlbumResponseDto[]> {
|
getAllAlbums(@Auth() auth: AuthDto, @Query() query: GetAlbumsDto): Promise<AlbumResponseDto[]> {
|
||||||
return this.service.getAll(auth, query);
|
return this.service.getAll(auth, query);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post()
|
@Post()
|
||||||
|
@Authenticated(Permission.ALBUM_CREATE)
|
||||||
createAlbum(@Auth() auth: AuthDto, @Body() dto: CreateAlbumDto): Promise<AlbumResponseDto> {
|
createAlbum(@Auth() auth: AuthDto, @Body() dto: CreateAlbumDto): Promise<AlbumResponseDto> {
|
||||||
return this.service.create(auth, dto);
|
return this.service.create(auth, dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SharedLinkRoute()
|
|
||||||
@Get(':id')
|
@Get(':id')
|
||||||
|
@Authenticated(Permission.ALBUM_READ, { sharedLink: true })
|
||||||
getAlbumInfo(
|
getAlbumInfo(
|
||||||
@Auth() auth: AuthDto,
|
@Auth() auth: AuthDto,
|
||||||
@Param() { id }: UUIDParamDto,
|
@Param() { id }: UUIDParamDto,
|
||||||
@@ -47,6 +49,7 @@ export class AlbumController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Patch(':id')
|
@Patch(':id')
|
||||||
|
@Authenticated(Permission.ALBUM_UPDATE)
|
||||||
updateAlbumInfo(
|
updateAlbumInfo(
|
||||||
@Auth() auth: AuthDto,
|
@Auth() auth: AuthDto,
|
||||||
@Param() { id }: UUIDParamDto,
|
@Param() { id }: UUIDParamDto,
|
||||||
@@ -56,12 +59,13 @@ export class AlbumController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Delete(':id')
|
@Delete(':id')
|
||||||
|
@Authenticated(Permission.ALBUM_DELETE)
|
||||||
deleteAlbum(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto) {
|
deleteAlbum(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto) {
|
||||||
return this.service.delete(auth, id);
|
return this.service.delete(auth, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SharedLinkRoute()
|
|
||||||
@Put(':id/assets')
|
@Put(':id/assets')
|
||||||
|
@Authenticated(Permission.ALBUM_ADD_ASSET, { sharedLink: true })
|
||||||
addAssetsToAlbum(
|
addAssetsToAlbum(
|
||||||
@Auth() auth: AuthDto,
|
@Auth() auth: AuthDto,
|
||||||
@Param() { id }: UUIDParamDto,
|
@Param() { id }: UUIDParamDto,
|
||||||
@@ -71,6 +75,7 @@ export class AlbumController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Delete(':id/assets')
|
@Delete(':id/assets')
|
||||||
|
@Authenticated(Permission.ALBUM_REMOVE_ASSET)
|
||||||
removeAssetFromAlbum(
|
removeAssetFromAlbum(
|
||||||
@Auth() auth: AuthDto,
|
@Auth() auth: AuthDto,
|
||||||
@Body() dto: BulkIdsDto,
|
@Body() dto: BulkIdsDto,
|
||||||
@@ -80,6 +85,7 @@ export class AlbumController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Put(':id/users')
|
@Put(':id/users')
|
||||||
|
@Authenticated(Permission.ALBUM_ADD_USER)
|
||||||
addUsersToAlbum(
|
addUsersToAlbum(
|
||||||
@Auth() auth: AuthDto,
|
@Auth() auth: AuthDto,
|
||||||
@Param() { id }: UUIDParamDto,
|
@Param() { id }: UUIDParamDto,
|
||||||
@@ -89,6 +95,7 @@ export class AlbumController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Delete(':id/user/:userId')
|
@Delete(':id/user/:userId')
|
||||||
|
@Authenticated(Permission.ALBUM_REMOVE_USER, { bypassParamId: 'userId' })
|
||||||
removeUserFromAlbum(
|
removeUserFromAlbum(
|
||||||
@Auth() auth: AuthDto,
|
@Auth() auth: AuthDto,
|
||||||
@Param() { id }: UUIDParamDto,
|
@Param() { id }: UUIDParamDto,
|
||||||
|
|||||||
@@ -1,33 +1,36 @@
|
|||||||
import { Body, Controller, Delete, Get, Param, Post, Put } from '@nestjs/common';
|
import { Body, Controller, Delete, Get, Param, Post, Put } from '@nestjs/common';
|
||||||
import { ApiTags } from '@nestjs/swagger';
|
import { ApiTags } from '@nestjs/swagger';
|
||||||
import { APIKeyCreateDto, APIKeyCreateResponseDto, APIKeyResponseDto, APIKeyUpdateDto } from 'src/dtos/api-key.dto';
|
import { APIKeyCreateDto, APIKeyCreateResponseDto, APIKeyResponseDto, APIKeyUpdateDto } from 'src/dtos/api-key.dto';
|
||||||
import { AuthDto } from 'src/dtos/auth.dto';
|
import { AuthDto, Permission } from 'src/dtos/auth.dto';
|
||||||
import { Auth, Authenticated } from 'src/middleware/auth.guard';
|
import { Auth, Authenticated } from 'src/middleware/auth.guard';
|
||||||
import { APIKeyService } from 'src/services/api-key.service';
|
import { APIKeyService } from 'src/services/api-key.service';
|
||||||
import { UUIDParamDto } from 'src/validation';
|
import { UUIDParamDto } from 'src/validation';
|
||||||
|
|
||||||
@ApiTags('API Key')
|
@ApiTags('API Key')
|
||||||
@Controller('api-key')
|
@Controller('api-key')
|
||||||
@Authenticated()
|
|
||||||
export class APIKeyController {
|
export class APIKeyController {
|
||||||
constructor(private service: APIKeyService) {}
|
constructor(private service: APIKeyService) {}
|
||||||
|
|
||||||
@Post()
|
@Post()
|
||||||
|
@Authenticated(Permission.API_KEY_CREATE)
|
||||||
createApiKey(@Auth() auth: AuthDto, @Body() dto: APIKeyCreateDto): Promise<APIKeyCreateResponseDto> {
|
createApiKey(@Auth() auth: AuthDto, @Body() dto: APIKeyCreateDto): Promise<APIKeyCreateResponseDto> {
|
||||||
return this.service.create(auth, dto);
|
return this.service.create(auth, dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
|
@Authenticated(Permission.API_KEY_READ)
|
||||||
getApiKeys(@Auth() auth: AuthDto): Promise<APIKeyResponseDto[]> {
|
getApiKeys(@Auth() auth: AuthDto): Promise<APIKeyResponseDto[]> {
|
||||||
return this.service.getAll(auth);
|
return this.service.getAll(auth);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get(':id')
|
@Get(':id')
|
||||||
|
@Authenticated(Permission.API_KEY_READ)
|
||||||
getApiKey(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<APIKeyResponseDto> {
|
getApiKey(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<APIKeyResponseDto> {
|
||||||
return this.service.getById(auth, id);
|
return this.service.getById(auth, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Put(':id')
|
@Put(':id')
|
||||||
|
@Authenticated(Permission.API_KEY_UPDATE)
|
||||||
updateApiKey(
|
updateApiKey(
|
||||||
@Auth() auth: AuthDto,
|
@Auth() auth: AuthDto,
|
||||||
@Param() { id }: UUIDParamDto,
|
@Param() { id }: UUIDParamDto,
|
||||||
@@ -37,6 +40,7 @@ export class APIKeyController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Delete(':id')
|
@Delete(':id')
|
||||||
|
@Authenticated(Permission.API_KEY_DELETE)
|
||||||
deleteApiKey(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<void> {
|
deleteApiKey(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<void> {
|
||||||
return this.service.delete(auth, id);
|
return this.service.delete(auth, id);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { Controller, Get, Header } from '@nestjs/common';
|
import { Controller, Get, Header } from '@nestjs/common';
|
||||||
import { ApiExcludeEndpoint } from '@nestjs/swagger';
|
import { ApiExcludeEndpoint } from '@nestjs/swagger';
|
||||||
import { PublicRoute } from 'src/middleware/auth.guard';
|
|
||||||
import { SystemConfigService } from 'src/services/system-config.service';
|
import { SystemConfigService } from 'src/services/system-config.service';
|
||||||
|
|
||||||
@Controller()
|
@Controller()
|
||||||
@@ -18,7 +17,6 @@ export class AppController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ApiExcludeEndpoint()
|
@ApiExcludeEndpoint()
|
||||||
@PublicRoute()
|
|
||||||
@Get('custom.css')
|
@Get('custom.css')
|
||||||
@Header('Content-Type', 'text/css')
|
@Header('Content-Type', 'text/css')
|
||||||
getCustomCss() {
|
getCustomCss() {
|
||||||
|
|||||||
@@ -31,8 +31,8 @@ import {
|
|||||||
GetAssetThumbnailDto,
|
GetAssetThumbnailDto,
|
||||||
ServeFileDto,
|
ServeFileDto,
|
||||||
} from 'src/dtos/asset-v1.dto';
|
} from 'src/dtos/asset-v1.dto';
|
||||||
import { AuthDto } from 'src/dtos/auth.dto';
|
import { AuthDto, Permission } from 'src/dtos/auth.dto';
|
||||||
import { Auth, Authenticated, FileResponse, SharedLinkRoute } from 'src/middleware/auth.guard';
|
import { Auth, Authenticated, FileResponse } from 'src/middleware/auth.guard';
|
||||||
import { FileUploadInterceptor, ImmichFile, Route, mapToUploadFile } from 'src/middleware/file-upload.interceptor';
|
import { FileUploadInterceptor, ImmichFile, Route, mapToUploadFile } from 'src/middleware/file-upload.interceptor';
|
||||||
import { AssetServiceV1 } from 'src/services/asset-v1.service';
|
import { AssetServiceV1 } from 'src/services/asset-v1.service';
|
||||||
import { sendFile } from 'src/utils/file';
|
import { sendFile } from 'src/utils/file';
|
||||||
@@ -46,12 +46,11 @@ interface UploadFiles {
|
|||||||
|
|
||||||
@ApiTags('Asset')
|
@ApiTags('Asset')
|
||||||
@Controller(Route.ASSET)
|
@Controller(Route.ASSET)
|
||||||
@Authenticated()
|
|
||||||
export class AssetControllerV1 {
|
export class AssetControllerV1 {
|
||||||
constructor(private service: AssetServiceV1) {}
|
constructor(private service: AssetServiceV1) {}
|
||||||
|
|
||||||
@SharedLinkRoute()
|
|
||||||
@Post('upload')
|
@Post('upload')
|
||||||
|
@Authenticated(Permission.ASSET_UPLOAD, { sharedLink: true })
|
||||||
@UseInterceptors(FileUploadInterceptor)
|
@UseInterceptors(FileUploadInterceptor)
|
||||||
@ApiConsumes('multipart/form-data')
|
@ApiConsumes('multipart/form-data')
|
||||||
@ApiBody({
|
@ApiBody({
|
||||||
@@ -85,8 +84,8 @@ export class AssetControllerV1 {
|
|||||||
return responseDto;
|
return responseDto;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SharedLinkRoute()
|
|
||||||
@Get('/file/:id')
|
@Get('/file/:id')
|
||||||
|
@Authenticated(Permission.ASSET_VIEW_ORIGINAL, { sharedLink: true })
|
||||||
@FileResponse()
|
@FileResponse()
|
||||||
async serveFile(
|
async serveFile(
|
||||||
@Res() res: Response,
|
@Res() res: Response,
|
||||||
@@ -98,8 +97,8 @@ export class AssetControllerV1 {
|
|||||||
await sendFile(res, next, () => this.service.serveFile(auth, id, dto));
|
await sendFile(res, next, () => this.service.serveFile(auth, id, dto));
|
||||||
}
|
}
|
||||||
|
|
||||||
@SharedLinkRoute()
|
|
||||||
@Get('/thumbnail/:id')
|
@Get('/thumbnail/:id')
|
||||||
|
@Authenticated(Permission.ASSET_VIEW_THUMB, { sharedLink: true })
|
||||||
@FileResponse()
|
@FileResponse()
|
||||||
async getAssetThumbnail(
|
async getAssetThumbnail(
|
||||||
@Res() res: Response,
|
@Res() res: Response,
|
||||||
@@ -112,16 +111,19 @@ export class AssetControllerV1 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Get('/curated-objects')
|
@Get('/curated-objects')
|
||||||
|
@Authenticated(Permission.ASSET_READ)
|
||||||
getCuratedObjects(@Auth() auth: AuthDto): Promise<CuratedObjectsResponseDto[]> {
|
getCuratedObjects(@Auth() auth: AuthDto): Promise<CuratedObjectsResponseDto[]> {
|
||||||
return this.service.getCuratedObject(auth);
|
return this.service.getCuratedObject(auth);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get('/curated-locations')
|
@Get('/curated-locations')
|
||||||
|
@Authenticated(Permission.ASSET_READ)
|
||||||
getCuratedLocations(@Auth() auth: AuthDto): Promise<CuratedLocationsResponseDto[]> {
|
getCuratedLocations(@Auth() auth: AuthDto): Promise<CuratedLocationsResponseDto[]> {
|
||||||
return this.service.getCuratedLocation(auth);
|
return this.service.getCuratedLocation(auth);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get('/search-terms')
|
@Get('/search-terms')
|
||||||
|
@Authenticated(Permission.ASSET_READ)
|
||||||
getAssetSearchTerms(@Auth() auth: AuthDto): Promise<string[]> {
|
getAssetSearchTerms(@Auth() auth: AuthDto): Promise<string[]> {
|
||||||
return this.service.getAssetSearchTerm(auth);
|
return this.service.getAssetSearchTerm(auth);
|
||||||
}
|
}
|
||||||
@@ -130,6 +132,7 @@ export class AssetControllerV1 {
|
|||||||
* Get all AssetEntity belong to the user
|
* Get all AssetEntity belong to the user
|
||||||
*/
|
*/
|
||||||
@Get('/')
|
@Get('/')
|
||||||
|
@Authenticated(Permission.ASSET_READ)
|
||||||
@ApiHeader({
|
@ApiHeader({
|
||||||
name: 'if-none-match',
|
name: 'if-none-match',
|
||||||
description: 'ETag of data already cached on the client',
|
description: 'ETag of data already cached on the client',
|
||||||
@@ -144,6 +147,7 @@ export class AssetControllerV1 {
|
|||||||
* Checks if multiple assets exist on the server and returns all existing - used by background backup
|
* Checks if multiple assets exist on the server and returns all existing - used by background backup
|
||||||
*/
|
*/
|
||||||
@Post('/exist')
|
@Post('/exist')
|
||||||
|
@Authenticated(Permission.ASSET_READ)
|
||||||
@HttpCode(HttpStatus.OK)
|
@HttpCode(HttpStatus.OK)
|
||||||
checkExistingAssets(
|
checkExistingAssets(
|
||||||
@Auth() auth: AuthDto,
|
@Auth() auth: AuthDto,
|
||||||
@@ -156,6 +160,7 @@ export class AssetControllerV1 {
|
|||||||
* Checks if assets exist by checksums
|
* Checks if assets exist by checksums
|
||||||
*/
|
*/
|
||||||
@Post('/bulk-upload-check')
|
@Post('/bulk-upload-check')
|
||||||
|
@Authenticated(Permission.ASSET_READ)
|
||||||
@HttpCode(HttpStatus.OK)
|
@HttpCode(HttpStatus.OK)
|
||||||
checkBulkUpload(
|
checkBulkUpload(
|
||||||
@Auth() auth: AuthDto,
|
@Auth() auth: AuthDto,
|
||||||
|
|||||||
@@ -11,10 +11,10 @@ import {
|
|||||||
RandomAssetsDto,
|
RandomAssetsDto,
|
||||||
UpdateAssetDto,
|
UpdateAssetDto,
|
||||||
} from 'src/dtos/asset.dto';
|
} from 'src/dtos/asset.dto';
|
||||||
import { AuthDto } from 'src/dtos/auth.dto';
|
import { AuthDto, Permission } from 'src/dtos/auth.dto';
|
||||||
import { MapMarkerDto, MapMarkerResponseDto, MemoryLaneDto, MetadataSearchDto } from 'src/dtos/search.dto';
|
import { MapMarkerDto, MapMarkerResponseDto, MemoryLaneDto, MetadataSearchDto } from 'src/dtos/search.dto';
|
||||||
import { UpdateStackParentDto } from 'src/dtos/stack.dto';
|
import { UpdateStackParentDto } from 'src/dtos/stack.dto';
|
||||||
import { Auth, Authenticated, SharedLinkRoute } from 'src/middleware/auth.guard';
|
import { Auth, Authenticated } from 'src/middleware/auth.guard';
|
||||||
import { Route } from 'src/middleware/file-upload.interceptor';
|
import { Route } from 'src/middleware/file-upload.interceptor';
|
||||||
import { AssetService } from 'src/services/asset.service';
|
import { AssetService } from 'src/services/asset.service';
|
||||||
import { SearchService } from 'src/services/search.service';
|
import { SearchService } from 'src/services/search.service';
|
||||||
@@ -22,11 +22,11 @@ import { UUIDParamDto } from 'src/validation';
|
|||||||
|
|
||||||
@ApiTags('Asset')
|
@ApiTags('Asset')
|
||||||
@Controller('assets')
|
@Controller('assets')
|
||||||
@Authenticated()
|
|
||||||
export class AssetsController {
|
export class AssetsController {
|
||||||
constructor(private searchService: SearchService) {}
|
constructor(private searchService: SearchService) {}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
|
@Authenticated(Permission.ASSET_READ)
|
||||||
@ApiOperation({ deprecated: true })
|
@ApiOperation({ deprecated: true })
|
||||||
async searchAssets(@Auth() auth: AuthDto, @Query() dto: MetadataSearchDto): Promise<AssetResponseDto[]> {
|
async searchAssets(@Auth() auth: AuthDto, @Query() dto: MetadataSearchDto): Promise<AssetResponseDto[]> {
|
||||||
const {
|
const {
|
||||||
@@ -38,21 +38,23 @@ export class AssetsController {
|
|||||||
|
|
||||||
@ApiTags('Asset')
|
@ApiTags('Asset')
|
||||||
@Controller(Route.ASSET)
|
@Controller(Route.ASSET)
|
||||||
@Authenticated()
|
|
||||||
export class AssetController {
|
export class AssetController {
|
||||||
constructor(private service: AssetService) {}
|
constructor(private service: AssetService) {}
|
||||||
|
|
||||||
@Get('map-marker')
|
@Get('map-marker')
|
||||||
|
@Authenticated(Permission.ASSET_READ)
|
||||||
getMapMarkers(@Auth() auth: AuthDto, @Query() options: MapMarkerDto): Promise<MapMarkerResponseDto[]> {
|
getMapMarkers(@Auth() auth: AuthDto, @Query() options: MapMarkerDto): Promise<MapMarkerResponseDto[]> {
|
||||||
return this.service.getMapMarkers(auth, options);
|
return this.service.getMapMarkers(auth, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get('memory-lane')
|
@Get('memory-lane')
|
||||||
|
@Authenticated(Permission.MEMORY_READ)
|
||||||
getMemoryLane(@Auth() auth: AuthDto, @Query() dto: MemoryLaneDto): Promise<MemoryLaneResponseDto[]> {
|
getMemoryLane(@Auth() auth: AuthDto, @Query() dto: MemoryLaneDto): Promise<MemoryLaneResponseDto[]> {
|
||||||
return this.service.getMemoryLane(auth, dto);
|
return this.service.getMemoryLane(auth, dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get('random')
|
@Get('random')
|
||||||
|
@Authenticated(Permission.ASSET_READ)
|
||||||
getRandom(@Auth() auth: AuthDto, @Query() dto: RandomAssetsDto): Promise<AssetResponseDto[]> {
|
getRandom(@Auth() auth: AuthDto, @Query() dto: RandomAssetsDto): Promise<AssetResponseDto[]> {
|
||||||
return this.service.getRandom(auth, dto.count ?? 1);
|
return this.service.getRandom(auth, dto.count ?? 1);
|
||||||
}
|
}
|
||||||
@@ -61,46 +63,54 @@ export class AssetController {
|
|||||||
* Get all asset of a device that are in the database, ID only.
|
* Get all asset of a device that are in the database, ID only.
|
||||||
*/
|
*/
|
||||||
@Get('/device/:deviceId')
|
@Get('/device/:deviceId')
|
||||||
|
@Authenticated(Permission.ASSET_READ)
|
||||||
getAllUserAssetsByDeviceId(@Auth() auth: AuthDto, @Param() { deviceId }: DeviceIdDto) {
|
getAllUserAssetsByDeviceId(@Auth() auth: AuthDto, @Param() { deviceId }: DeviceIdDto) {
|
||||||
return this.service.getUserAssetsByDeviceId(auth, deviceId);
|
return this.service.getUserAssetsByDeviceId(auth, deviceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get('statistics')
|
@Get('statistics')
|
||||||
|
@Authenticated(Permission.ASSET_READ)
|
||||||
getAssetStatistics(@Auth() auth: AuthDto, @Query() dto: AssetStatsDto): Promise<AssetStatsResponseDto> {
|
getAssetStatistics(@Auth() auth: AuthDto, @Query() dto: AssetStatsDto): Promise<AssetStatsResponseDto> {
|
||||||
return this.service.getStatistics(auth, dto);
|
return this.service.getStatistics(auth, dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post('jobs')
|
@Post('jobs')
|
||||||
|
// TODO
|
||||||
|
@Authenticated(Permission.ASSET_READ)
|
||||||
@HttpCode(HttpStatus.NO_CONTENT)
|
@HttpCode(HttpStatus.NO_CONTENT)
|
||||||
runAssetJobs(@Auth() auth: AuthDto, @Body() dto: AssetJobsDto): Promise<void> {
|
runAssetJobs(@Auth() auth: AuthDto, @Body() dto: AssetJobsDto): Promise<void> {
|
||||||
return this.service.run(auth, dto);
|
return this.service.run(auth, dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Put()
|
@Put()
|
||||||
|
@Authenticated(Permission.ASSET_UPDATE)
|
||||||
@HttpCode(HttpStatus.NO_CONTENT)
|
@HttpCode(HttpStatus.NO_CONTENT)
|
||||||
updateAssets(@Auth() auth: AuthDto, @Body() dto: AssetBulkUpdateDto): Promise<void> {
|
updateAssets(@Auth() auth: AuthDto, @Body() dto: AssetBulkUpdateDto): Promise<void> {
|
||||||
return this.service.updateAll(auth, dto);
|
return this.service.updateAll(auth, dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Delete()
|
@Delete()
|
||||||
|
@Authenticated(Permission.ASSET_DELETE)
|
||||||
@HttpCode(HttpStatus.NO_CONTENT)
|
@HttpCode(HttpStatus.NO_CONTENT)
|
||||||
deleteAssets(@Auth() auth: AuthDto, @Body() dto: AssetBulkDeleteDto): Promise<void> {
|
deleteAssets(@Auth() auth: AuthDto, @Body() dto: AssetBulkDeleteDto): Promise<void> {
|
||||||
return this.service.deleteAll(auth, dto);
|
return this.service.deleteAll(auth, dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Put('stack/parent')
|
@Put('stack/parent')
|
||||||
|
@Authenticated(Permission.STACK_UPDATE)
|
||||||
@HttpCode(HttpStatus.OK)
|
@HttpCode(HttpStatus.OK)
|
||||||
updateStackParent(@Auth() auth: AuthDto, @Body() dto: UpdateStackParentDto): Promise<void> {
|
updateStackParent(@Auth() auth: AuthDto, @Body() dto: UpdateStackParentDto): Promise<void> {
|
||||||
return this.service.updateStackParent(auth, dto);
|
return this.service.updateStackParent(auth, dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SharedLinkRoute()
|
|
||||||
@Get(':id')
|
@Get(':id')
|
||||||
|
@Authenticated(Permission.ASSET_READ, { sharedLink: true })
|
||||||
getAssetInfo(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<AssetResponseDto> {
|
getAssetInfo(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<AssetResponseDto> {
|
||||||
return this.service.get(auth, id) as Promise<AssetResponseDto>;
|
return this.service.get(auth, id) as Promise<AssetResponseDto>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Put(':id')
|
@Put(':id')
|
||||||
|
@Authenticated(Permission.ASSET_UPDATE)
|
||||||
updateAsset(
|
updateAsset(
|
||||||
@Auth() auth: AuthDto,
|
@Auth() auth: AuthDto,
|
||||||
@Param() { id }: UUIDParamDto,
|
@Param() { id }: UUIDParamDto,
|
||||||
|
|||||||
@@ -1,43 +1,18 @@
|
|||||||
import { Body, Controller, Get, Post, Query } from '@nestjs/common';
|
import { Controller, Get, Query } from '@nestjs/common';
|
||||||
import { ApiTags } from '@nestjs/swagger';
|
import { ApiTags } from '@nestjs/swagger';
|
||||||
import {
|
import { AuditDeletesDto, AuditDeletesResponseDto } from 'src/dtos/audit.dto';
|
||||||
AuditDeletesDto,
|
import { AuthDto, Permission } from 'src/dtos/auth.dto';
|
||||||
AuditDeletesResponseDto,
|
import { Auth, Authenticated } from 'src/middleware/auth.guard';
|
||||||
FileChecksumDto,
|
|
||||||
FileChecksumResponseDto,
|
|
||||||
FileReportDto,
|
|
||||||
FileReportFixDto,
|
|
||||||
} from 'src/dtos/audit.dto';
|
|
||||||
import { AuthDto } from 'src/dtos/auth.dto';
|
|
||||||
import { AdminRoute, Auth, Authenticated } from 'src/middleware/auth.guard';
|
|
||||||
import { AuditService } from 'src/services/audit.service';
|
import { AuditService } from 'src/services/audit.service';
|
||||||
|
|
||||||
@ApiTags('Audit')
|
@ApiTags('Audit')
|
||||||
@Controller('audit')
|
@Controller('audit')
|
||||||
@Authenticated()
|
|
||||||
export class AuditController {
|
export class AuditController {
|
||||||
constructor(private service: AuditService) {}
|
constructor(private service: AuditService) {}
|
||||||
|
|
||||||
@Get('deletes')
|
@Get('deletes')
|
||||||
|
@Authenticated(Permission.ASSET_READ)
|
||||||
getAuditDeletes(@Auth() auth: AuthDto, @Query() dto: AuditDeletesDto): Promise<AuditDeletesResponseDto> {
|
getAuditDeletes(@Auth() auth: AuthDto, @Query() dto: AuditDeletesDto): Promise<AuditDeletesResponseDto> {
|
||||||
return this.service.getDeletes(auth, dto);
|
return this.service.getDeletes(auth, dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@AdminRoute()
|
|
||||||
@Get('file-report')
|
|
||||||
getAuditFiles(): Promise<FileReportDto> {
|
|
||||||
return this.service.getFileReport();
|
|
||||||
}
|
|
||||||
|
|
||||||
@AdminRoute()
|
|
||||||
@Post('file-report/checksum')
|
|
||||||
getFileChecksums(@Body() dto: FileChecksumDto): Promise<FileChecksumResponseDto[]> {
|
|
||||||
return this.service.getChecksums(dto);
|
|
||||||
}
|
|
||||||
|
|
||||||
@AdminRoute()
|
|
||||||
@Post('file-report/fix')
|
|
||||||
fixAuditFiles(@Body() dto: FileReportFixDto): Promise<void> {
|
|
||||||
return this.service.fixItems(dto.items);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,21 +9,20 @@ import {
|
|||||||
LoginCredentialDto,
|
LoginCredentialDto,
|
||||||
LoginResponseDto,
|
LoginResponseDto,
|
||||||
LogoutResponseDto,
|
LogoutResponseDto,
|
||||||
|
Permission,
|
||||||
SignUpDto,
|
SignUpDto,
|
||||||
ValidateAccessTokenResponseDto,
|
ValidateAccessTokenResponseDto,
|
||||||
} from 'src/dtos/auth.dto';
|
} from 'src/dtos/auth.dto';
|
||||||
import { UserResponseDto, mapUser } from 'src/dtos/user.dto';
|
import { UserResponseDto, mapUser } from 'src/dtos/user.dto';
|
||||||
import { Auth, Authenticated, GetLoginDetails, PublicRoute } from 'src/middleware/auth.guard';
|
import { Auth, Authenticated, GetLoginDetails } from 'src/middleware/auth.guard';
|
||||||
import { AuthService, LoginDetails } from 'src/services/auth.service';
|
import { AuthService, LoginDetails } from 'src/services/auth.service';
|
||||||
import { respondWithCookie, respondWithoutCookie } from 'src/utils/response';
|
import { respondWithCookie, respondWithoutCookie } from 'src/utils/response';
|
||||||
|
|
||||||
@ApiTags('Authentication')
|
@ApiTags('Authentication')
|
||||||
@Controller('auth')
|
@Controller('auth')
|
||||||
@Authenticated()
|
|
||||||
export class AuthController {
|
export class AuthController {
|
||||||
constructor(private service: AuthService) {}
|
constructor(private service: AuthService) {}
|
||||||
|
|
||||||
@PublicRoute()
|
|
||||||
@Post('login')
|
@Post('login')
|
||||||
async login(
|
async login(
|
||||||
@Body() loginCredential: LoginCredentialDto,
|
@Body() loginCredential: LoginCredentialDto,
|
||||||
@@ -41,25 +40,27 @@ export class AuthController {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@PublicRoute()
|
|
||||||
@Post('admin-sign-up')
|
@Post('admin-sign-up')
|
||||||
signUpAdmin(@Body() dto: SignUpDto): Promise<UserResponseDto> {
|
signUpAdmin(@Body() dto: SignUpDto): Promise<UserResponseDto> {
|
||||||
return this.service.adminSignUp(dto);
|
return this.service.adminSignUp(dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post('validateToken')
|
@Post('validateToken')
|
||||||
|
@Authenticated(Permission.AUTH_DEVICE_READ)
|
||||||
@HttpCode(HttpStatus.OK)
|
@HttpCode(HttpStatus.OK)
|
||||||
validateAccessToken(): ValidateAccessTokenResponseDto {
|
validateAccessToken(): ValidateAccessTokenResponseDto {
|
||||||
return { authStatus: true };
|
return { authStatus: true };
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post('change-password')
|
@Post('change-password')
|
||||||
|
@Authenticated(Permission.AUTH_CHANGE_PASSWORD)
|
||||||
@HttpCode(HttpStatus.OK)
|
@HttpCode(HttpStatus.OK)
|
||||||
changePassword(@Auth() auth: AuthDto, @Body() dto: ChangePasswordDto): Promise<UserResponseDto> {
|
changePassword(@Auth() auth: AuthDto, @Body() dto: ChangePasswordDto): Promise<UserResponseDto> {
|
||||||
return this.service.changePassword(auth, dto).then(mapUser);
|
return this.service.changePassword(auth, dto).then(mapUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post('logout')
|
@Post('logout')
|
||||||
|
@Authenticated(Permission.AUTH_DEVICE_DELETE)
|
||||||
@HttpCode(HttpStatus.OK)
|
@HttpCode(HttpStatus.OK)
|
||||||
async logout(
|
async logout(
|
||||||
@Req() request: Request,
|
@Req() request: Request,
|
||||||
|
|||||||
@@ -2,35 +2,34 @@ import { Body, Controller, HttpCode, HttpStatus, Next, Param, Post, Res, Streama
|
|||||||
import { ApiTags } from '@nestjs/swagger';
|
import { ApiTags } from '@nestjs/swagger';
|
||||||
import { NextFunction, Response } from 'express';
|
import { NextFunction, Response } from 'express';
|
||||||
import { AssetIdsDto } from 'src/dtos/asset.dto';
|
import { AssetIdsDto } from 'src/dtos/asset.dto';
|
||||||
import { AuthDto } from 'src/dtos/auth.dto';
|
import { AuthDto, Permission } from 'src/dtos/auth.dto';
|
||||||
import { DownloadInfoDto, DownloadResponseDto } from 'src/dtos/download.dto';
|
import { DownloadInfoDto, DownloadResponseDto } from 'src/dtos/download.dto';
|
||||||
import { Auth, Authenticated, FileResponse, SharedLinkRoute } from 'src/middleware/auth.guard';
|
import { Auth, Authenticated, FileResponse } from 'src/middleware/auth.guard';
|
||||||
import { DownloadService } from 'src/services/download.service';
|
import { DownloadService } from 'src/services/download.service';
|
||||||
import { asStreamableFile, sendFile } from 'src/utils/file';
|
import { asStreamableFile, sendFile } from 'src/utils/file';
|
||||||
import { UUIDParamDto } from 'src/validation';
|
import { UUIDParamDto } from 'src/validation';
|
||||||
|
|
||||||
@ApiTags('Download')
|
@ApiTags('Download')
|
||||||
@Controller('download')
|
@Controller('download')
|
||||||
@Authenticated()
|
|
||||||
export class DownloadController {
|
export class DownloadController {
|
||||||
constructor(private service: DownloadService) {}
|
constructor(private service: DownloadService) {}
|
||||||
|
|
||||||
@SharedLinkRoute()
|
|
||||||
@Post('info')
|
@Post('info')
|
||||||
|
@Authenticated(Permission.ASSET_READ, { sharedLink: true })
|
||||||
getDownloadInfo(@Auth() auth: AuthDto, @Body() dto: DownloadInfoDto): Promise<DownloadResponseDto> {
|
getDownloadInfo(@Auth() auth: AuthDto, @Body() dto: DownloadInfoDto): Promise<DownloadResponseDto> {
|
||||||
return this.service.getDownloadInfo(auth, dto);
|
return this.service.getDownloadInfo(auth, dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SharedLinkRoute()
|
|
||||||
@Post('archive')
|
@Post('archive')
|
||||||
|
@Authenticated(Permission.ASSET_DOWNLOAD, { sharedLink: true })
|
||||||
@HttpCode(HttpStatus.OK)
|
@HttpCode(HttpStatus.OK)
|
||||||
@FileResponse()
|
@FileResponse()
|
||||||
downloadArchive(@Auth() auth: AuthDto, @Body() dto: AssetIdsDto): Promise<StreamableFile> {
|
downloadArchive(@Auth() auth: AuthDto, @Body() dto: AssetIdsDto): Promise<StreamableFile> {
|
||||||
return this.service.downloadArchive(auth, dto).then(asStreamableFile);
|
return this.service.downloadArchive(auth, dto).then(asStreamableFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SharedLinkRoute()
|
|
||||||
@Post('asset/:id')
|
@Post('asset/:id')
|
||||||
|
@Authenticated(Permission.ASSET_DOWNLOAD, { sharedLink: true })
|
||||||
@HttpCode(HttpStatus.OK)
|
@HttpCode(HttpStatus.OK)
|
||||||
@FileResponse()
|
@FileResponse()
|
||||||
async downloadFile(
|
async downloadFile(
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Body, Controller, Get, Param, Put, Query } from '@nestjs/common';
|
import { Body, Controller, Get, Param, Put, Query } from '@nestjs/common';
|
||||||
import { ApiTags } from '@nestjs/swagger';
|
import { ApiTags } from '@nestjs/swagger';
|
||||||
import { AuthDto } from 'src/dtos/auth.dto';
|
import { AuthDto, Permission } from 'src/dtos/auth.dto';
|
||||||
import { AssetFaceResponseDto, FaceDto, PersonResponseDto } from 'src/dtos/person.dto';
|
import { AssetFaceResponseDto, FaceDto, PersonResponseDto } from 'src/dtos/person.dto';
|
||||||
import { Auth, Authenticated } from 'src/middleware/auth.guard';
|
import { Auth, Authenticated } from 'src/middleware/auth.guard';
|
||||||
import { PersonService } from 'src/services/person.service';
|
import { PersonService } from 'src/services/person.service';
|
||||||
@@ -8,16 +8,17 @@ import { UUIDParamDto } from 'src/validation';
|
|||||||
|
|
||||||
@ApiTags('Face')
|
@ApiTags('Face')
|
||||||
@Controller('face')
|
@Controller('face')
|
||||||
@Authenticated()
|
|
||||||
export class FaceController {
|
export class FaceController {
|
||||||
constructor(private service: PersonService) {}
|
constructor(private service: PersonService) {}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
|
@Authenticated(Permission.FACE_READ)
|
||||||
getFaces(@Auth() auth: AuthDto, @Query() dto: FaceDto): Promise<AssetFaceResponseDto[]> {
|
getFaces(@Auth() auth: AuthDto, @Query() dto: FaceDto): Promise<AssetFaceResponseDto[]> {
|
||||||
return this.service.getFacesById(auth, dto);
|
return this.service.getFacesById(auth, dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Put(':id')
|
@Put(':id')
|
||||||
|
@Authenticated(Permission.FACE_UPDATE)
|
||||||
reassignFacesById(
|
reassignFacesById(
|
||||||
@Auth() auth: AuthDto,
|
@Auth() auth: AuthDto,
|
||||||
@Param() { id }: UUIDParamDto,
|
@Param() { id }: UUIDParamDto,
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import { Body, Controller, Get, Post } from '@nestjs/common';
|
||||||
|
import { ApiTags } from '@nestjs/swagger';
|
||||||
|
import { FileChecksumDto, FileChecksumResponseDto, FileReportDto, FileReportFixDto } from 'src/dtos/audit.dto';
|
||||||
|
import { Permission } from 'src/dtos/auth.dto';
|
||||||
|
import { Authenticated } from 'src/middleware/auth.guard';
|
||||||
|
import { AuditService } from 'src/services/audit.service';
|
||||||
|
|
||||||
|
@ApiTags('File Report')
|
||||||
|
@Controller('report')
|
||||||
|
export class ReportController {
|
||||||
|
constructor(private service: AuditService) {}
|
||||||
|
|
||||||
|
@Get()
|
||||||
|
@Authenticated(Permission.REPORT_READ)
|
||||||
|
getAuditFiles(): Promise<FileReportDto> {
|
||||||
|
return this.service.getFileReport();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post('/checksum')
|
||||||
|
@Authenticated(Permission.REPORT_READ)
|
||||||
|
getFileChecksums(@Body() dto: FileChecksumDto): Promise<FileChecksumResponseDto[]> {
|
||||||
|
return this.service.getChecksums(dto);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post('/fix')
|
||||||
|
@Authenticated(Permission.REPORT_UPDATE)
|
||||||
|
fixAuditFiles(@Body() dto: FileReportFixDto): Promise<void> {
|
||||||
|
return this.service.fixItems(dto.items);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@ import { AuditController } from 'src/controllers/audit.controller';
|
|||||||
import { AuthController } from 'src/controllers/auth.controller';
|
import { AuthController } from 'src/controllers/auth.controller';
|
||||||
import { DownloadController } from 'src/controllers/download.controller';
|
import { DownloadController } from 'src/controllers/download.controller';
|
||||||
import { FaceController } from 'src/controllers/face.controller';
|
import { FaceController } from 'src/controllers/face.controller';
|
||||||
|
import { ReportController } from 'src/controllers/file-report.controller';
|
||||||
import { JobController } from 'src/controllers/job.controller';
|
import { JobController } from 'src/controllers/job.controller';
|
||||||
import { LibraryController } from 'src/controllers/library.controller';
|
import { LibraryController } from 'src/controllers/library.controller';
|
||||||
import { MemoryController } from 'src/controllers/memory.controller';
|
import { MemoryController } from 'src/controllers/memory.controller';
|
||||||
@@ -20,19 +21,20 @@ import { SessionController } from 'src/controllers/session.controller';
|
|||||||
import { SharedLinkController } from 'src/controllers/shared-link.controller';
|
import { SharedLinkController } from 'src/controllers/shared-link.controller';
|
||||||
import { SyncController } from 'src/controllers/sync.controller';
|
import { SyncController } from 'src/controllers/sync.controller';
|
||||||
import { SystemConfigController } from 'src/controllers/system-config.controller';
|
import { SystemConfigController } from 'src/controllers/system-config.controller';
|
||||||
|
import { SystemMetadataController } from 'src/controllers/system-metadata.controller';
|
||||||
import { TagController } from 'src/controllers/tag.controller';
|
import { TagController } from 'src/controllers/tag.controller';
|
||||||
import { TimelineController } from 'src/controllers/timeline.controller';
|
import { TimelineController } from 'src/controllers/timeline.controller';
|
||||||
import { TrashController } from 'src/controllers/trash.controller';
|
import { TrashController } from 'src/controllers/trash.controller';
|
||||||
import { UserController } from 'src/controllers/user.controller';
|
import { UserController } from 'src/controllers/user.controller';
|
||||||
|
|
||||||
export const controllers = [
|
export const controllers = [
|
||||||
ActivityController,
|
|
||||||
AssetsController,
|
|
||||||
AssetControllerV1,
|
|
||||||
AssetController,
|
|
||||||
AppController,
|
|
||||||
AlbumController,
|
|
||||||
APIKeyController,
|
APIKeyController,
|
||||||
|
ActivityController,
|
||||||
|
AlbumController,
|
||||||
|
AppController,
|
||||||
|
AssetController,
|
||||||
|
AssetControllerV1,
|
||||||
|
AssetsController,
|
||||||
AuditController,
|
AuditController,
|
||||||
AuthController,
|
AuthController,
|
||||||
DownloadController,
|
DownloadController,
|
||||||
@@ -42,15 +44,17 @@ export const controllers = [
|
|||||||
MemoryController,
|
MemoryController,
|
||||||
OAuthController,
|
OAuthController,
|
||||||
PartnerController,
|
PartnerController,
|
||||||
|
PersonController,
|
||||||
|
ReportController,
|
||||||
SearchController,
|
SearchController,
|
||||||
ServerInfoController,
|
ServerInfoController,
|
||||||
SessionController,
|
SessionController,
|
||||||
SharedLinkController,
|
SharedLinkController,
|
||||||
SyncController,
|
SyncController,
|
||||||
SystemConfigController,
|
SystemConfigController,
|
||||||
|
SystemMetadataController,
|
||||||
TagController,
|
TagController,
|
||||||
TimelineController,
|
TimelineController,
|
||||||
TrashController,
|
TrashController,
|
||||||
UserController,
|
UserController,
|
||||||
PersonController,
|
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1,21 +1,23 @@
|
|||||||
import { Body, Controller, Get, Param, Put } from '@nestjs/common';
|
import { Body, Controller, Get, Param, Put } from '@nestjs/common';
|
||||||
import { ApiTags } from '@nestjs/swagger';
|
import { ApiTags } from '@nestjs/swagger';
|
||||||
|
import { Permission } from 'src/dtos/auth.dto';
|
||||||
import { AllJobStatusResponseDto, JobCommandDto, JobIdParamDto, JobStatusDto } from 'src/dtos/job.dto';
|
import { AllJobStatusResponseDto, JobCommandDto, JobIdParamDto, JobStatusDto } from 'src/dtos/job.dto';
|
||||||
import { Authenticated } from 'src/middleware/auth.guard';
|
import { Authenticated } from 'src/middleware/auth.guard';
|
||||||
import { JobService } from 'src/services/job.service';
|
import { JobService } from 'src/services/job.service';
|
||||||
|
|
||||||
@ApiTags('Job')
|
@ApiTags('Job')
|
||||||
@Controller('jobs')
|
@Controller('jobs')
|
||||||
@Authenticated({ admin: true })
|
|
||||||
export class JobController {
|
export class JobController {
|
||||||
constructor(private service: JobService) {}
|
constructor(private service: JobService) {}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
|
@Authenticated(Permission.JOB_READ)
|
||||||
getAllJobsStatus(): Promise<AllJobStatusResponseDto> {
|
getAllJobsStatus(): Promise<AllJobStatusResponseDto> {
|
||||||
return this.service.getAllJobsStatus();
|
return this.service.getAllJobsStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Put(':id')
|
@Put(':id')
|
||||||
|
@Authenticated(Permission.JOB_RUN)
|
||||||
sendJobCommand(@Param() { id }: JobIdParamDto, @Body() dto: JobCommandDto): Promise<JobStatusDto> {
|
sendJobCommand(@Param() { id }: JobIdParamDto, @Body() dto: JobCommandDto): Promise<JobStatusDto> {
|
||||||
return this.service.handleCommand(id, dto);
|
return this.service.handleCommand(id, dto);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Post, Put, Query } from '@nestjs/common';
|
import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Post, Put, Query } from '@nestjs/common';
|
||||||
import { ApiTags } from '@nestjs/swagger';
|
import { ApiTags } from '@nestjs/swagger';
|
||||||
|
import { Permission } from 'src/dtos/auth.dto';
|
||||||
import {
|
import {
|
||||||
CreateLibraryDto,
|
CreateLibraryDto,
|
||||||
LibraryResponseDto,
|
LibraryResponseDto,
|
||||||
@@ -10,38 +11,41 @@ import {
|
|||||||
ValidateLibraryDto,
|
ValidateLibraryDto,
|
||||||
ValidateLibraryResponseDto,
|
ValidateLibraryResponseDto,
|
||||||
} from 'src/dtos/library.dto';
|
} from 'src/dtos/library.dto';
|
||||||
import { AdminRoute, Authenticated } from 'src/middleware/auth.guard';
|
import { Authenticated } from 'src/middleware/auth.guard';
|
||||||
import { LibraryService } from 'src/services/library.service';
|
import { LibraryService } from 'src/services/library.service';
|
||||||
import { UUIDParamDto } from 'src/validation';
|
import { UUIDParamDto } from 'src/validation';
|
||||||
|
|
||||||
@ApiTags('Library')
|
@ApiTags('Library')
|
||||||
@Controller('library')
|
@Controller('library')
|
||||||
@Authenticated()
|
|
||||||
@AdminRoute()
|
|
||||||
export class LibraryController {
|
export class LibraryController {
|
||||||
constructor(private service: LibraryService) {}
|
constructor(private service: LibraryService) {}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
|
@Authenticated(Permission.LIBRARY_READ)
|
||||||
getAllLibraries(@Query() dto: SearchLibraryDto): Promise<LibraryResponseDto[]> {
|
getAllLibraries(@Query() dto: SearchLibraryDto): Promise<LibraryResponseDto[]> {
|
||||||
return this.service.getAll(dto);
|
return this.service.getAll(dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post()
|
@Post()
|
||||||
|
@Authenticated(Permission.LIBRARY_CREATE)
|
||||||
createLibrary(@Body() dto: CreateLibraryDto): Promise<LibraryResponseDto> {
|
createLibrary(@Body() dto: CreateLibraryDto): Promise<LibraryResponseDto> {
|
||||||
return this.service.create(dto);
|
return this.service.create(dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Put(':id')
|
@Put(':id')
|
||||||
|
@Authenticated(Permission.LIBRARY_UPDATE)
|
||||||
updateLibrary(@Param() { id }: UUIDParamDto, @Body() dto: UpdateLibraryDto): Promise<LibraryResponseDto> {
|
updateLibrary(@Param() { id }: UUIDParamDto, @Body() dto: UpdateLibraryDto): Promise<LibraryResponseDto> {
|
||||||
return this.service.update(id, dto);
|
return this.service.update(id, dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get(':id')
|
@Get(':id')
|
||||||
|
@Authenticated(Permission.LIBRARY_READ)
|
||||||
getLibrary(@Param() { id }: UUIDParamDto): Promise<LibraryResponseDto> {
|
getLibrary(@Param() { id }: UUIDParamDto): Promise<LibraryResponseDto> {
|
||||||
return this.service.get(id);
|
return this.service.get(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post(':id/validate')
|
@Post(':id/validate')
|
||||||
|
@Authenticated(Permission.LIBRARY_READ)
|
||||||
@HttpCode(200)
|
@HttpCode(200)
|
||||||
// TODO: change endpoint to validate current settings instead
|
// TODO: change endpoint to validate current settings instead
|
||||||
validate(@Param() { id }: UUIDParamDto, @Body() dto: ValidateLibraryDto): Promise<ValidateLibraryResponseDto> {
|
validate(@Param() { id }: UUIDParamDto, @Body() dto: ValidateLibraryDto): Promise<ValidateLibraryResponseDto> {
|
||||||
@@ -49,23 +53,27 @@ export class LibraryController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Delete(':id')
|
@Delete(':id')
|
||||||
|
@Authenticated(Permission.LIBRARY_DELETE)
|
||||||
@HttpCode(HttpStatus.NO_CONTENT)
|
@HttpCode(HttpStatus.NO_CONTENT)
|
||||||
deleteLibrary(@Param() { id }: UUIDParamDto): Promise<void> {
|
deleteLibrary(@Param() { id }: UUIDParamDto): Promise<void> {
|
||||||
return this.service.delete(id);
|
return this.service.delete(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get(':id/statistics')
|
@Get(':id/statistics')
|
||||||
|
@Authenticated(Permission.LIBRARY_READ)
|
||||||
getLibraryStatistics(@Param() { id }: UUIDParamDto): Promise<LibraryStatsResponseDto> {
|
getLibraryStatistics(@Param() { id }: UUIDParamDto): Promise<LibraryStatsResponseDto> {
|
||||||
return this.service.getStatistics(id);
|
return this.service.getStatistics(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post(':id/scan')
|
@Post(':id/scan')
|
||||||
|
@Authenticated(Permission.LIBRARY_UPDATE)
|
||||||
@HttpCode(HttpStatus.NO_CONTENT)
|
@HttpCode(HttpStatus.NO_CONTENT)
|
||||||
scanLibrary(@Param() { id }: UUIDParamDto, @Body() dto: ScanLibraryDto) {
|
scanLibrary(@Param() { id }: UUIDParamDto, @Body() dto: ScanLibraryDto) {
|
||||||
return this.service.queueScan(id, dto);
|
return this.service.queueScan(id, dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post(':id/removeOffline')
|
@Post(':id/removeOffline')
|
||||||
|
@Authenticated(Permission.LIBRARY_UPDATE)
|
||||||
@HttpCode(HttpStatus.NO_CONTENT)
|
@HttpCode(HttpStatus.NO_CONTENT)
|
||||||
removeOfflineFiles(@Param() { id }: UUIDParamDto) {
|
removeOfflineFiles(@Param() { id }: UUIDParamDto) {
|
||||||
return this.service.queueRemoveOffline(id);
|
return this.service.queueRemoveOffline(id);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Post, Put } from '@nestjs/common';
|
import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Post, Put } from '@nestjs/common';
|
||||||
import { ApiTags } from '@nestjs/swagger';
|
import { ApiTags } from '@nestjs/swagger';
|
||||||
import { BulkIdResponseDto, BulkIdsDto } from 'src/dtos/asset-ids.response.dto';
|
import { BulkIdResponseDto, BulkIdsDto } from 'src/dtos/asset-ids.response.dto';
|
||||||
import { AuthDto } from 'src/dtos/auth.dto';
|
import { AuthDto, Permission } from 'src/dtos/auth.dto';
|
||||||
import { MemoryCreateDto, MemoryResponseDto, MemoryUpdateDto } from 'src/dtos/memory.dto';
|
import { MemoryCreateDto, MemoryResponseDto, MemoryUpdateDto } from 'src/dtos/memory.dto';
|
||||||
import { Auth, Authenticated } from 'src/middleware/auth.guard';
|
import { Auth, Authenticated } from 'src/middleware/auth.guard';
|
||||||
import { MemoryService } from 'src/services/memory.service';
|
import { MemoryService } from 'src/services/memory.service';
|
||||||
@@ -9,26 +9,29 @@ import { UUIDParamDto } from 'src/validation';
|
|||||||
|
|
||||||
@ApiTags('Memory')
|
@ApiTags('Memory')
|
||||||
@Controller('memories')
|
@Controller('memories')
|
||||||
@Authenticated()
|
|
||||||
export class MemoryController {
|
export class MemoryController {
|
||||||
constructor(private service: MemoryService) {}
|
constructor(private service: MemoryService) {}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
|
@Authenticated(Permission.MEMORY_READ)
|
||||||
searchMemories(@Auth() auth: AuthDto): Promise<MemoryResponseDto[]> {
|
searchMemories(@Auth() auth: AuthDto): Promise<MemoryResponseDto[]> {
|
||||||
return this.service.search(auth);
|
return this.service.search(auth);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post()
|
@Post()
|
||||||
|
@Authenticated(Permission.MEMORY_CREATE)
|
||||||
createMemory(@Auth() auth: AuthDto, @Body() dto: MemoryCreateDto): Promise<MemoryResponseDto> {
|
createMemory(@Auth() auth: AuthDto, @Body() dto: MemoryCreateDto): Promise<MemoryResponseDto> {
|
||||||
return this.service.create(auth, dto);
|
return this.service.create(auth, dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get(':id')
|
@Get(':id')
|
||||||
|
@Authenticated(Permission.MEMORY_READ)
|
||||||
getMemory(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<MemoryResponseDto> {
|
getMemory(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<MemoryResponseDto> {
|
||||||
return this.service.get(auth, id);
|
return this.service.get(auth, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Put(':id')
|
@Put(':id')
|
||||||
|
@Authenticated(Permission.MEMORY_UPDATE)
|
||||||
updateMemory(
|
updateMemory(
|
||||||
@Auth() auth: AuthDto,
|
@Auth() auth: AuthDto,
|
||||||
@Param() { id }: UUIDParamDto,
|
@Param() { id }: UUIDParamDto,
|
||||||
@@ -38,12 +41,14 @@ export class MemoryController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Delete(':id')
|
@Delete(':id')
|
||||||
|
@Authenticated(Permission.MEMORY_DELETE)
|
||||||
@HttpCode(HttpStatus.NO_CONTENT)
|
@HttpCode(HttpStatus.NO_CONTENT)
|
||||||
deleteMemory(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<void> {
|
deleteMemory(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<void> {
|
||||||
return this.service.remove(auth, id);
|
return this.service.remove(auth, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Put(':id/assets')
|
@Put(':id/assets')
|
||||||
|
@Authenticated(Permission.MEMORY_ADD_ASSET)
|
||||||
addMemoryAssets(
|
addMemoryAssets(
|
||||||
@Auth() auth: AuthDto,
|
@Auth() auth: AuthDto,
|
||||||
@Param() { id }: UUIDParamDto,
|
@Param() { id }: UUIDParamDto,
|
||||||
@@ -53,6 +58,7 @@ export class MemoryController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Delete(':id/assets')
|
@Delete(':id/assets')
|
||||||
|
@Authenticated(Permission.MEMORY_REMOVE_ASSET)
|
||||||
@HttpCode(HttpStatus.OK)
|
@HttpCode(HttpStatus.OK)
|
||||||
removeMemoryAssets(
|
removeMemoryAssets(
|
||||||
@Auth() auth: AuthDto,
|
@Auth() auth: AuthDto,
|
||||||
|
|||||||
@@ -9,19 +9,18 @@ import {
|
|||||||
OAuthAuthorizeResponseDto,
|
OAuthAuthorizeResponseDto,
|
||||||
OAuthCallbackDto,
|
OAuthCallbackDto,
|
||||||
OAuthConfigDto,
|
OAuthConfigDto,
|
||||||
|
Permission,
|
||||||
} from 'src/dtos/auth.dto';
|
} from 'src/dtos/auth.dto';
|
||||||
import { UserResponseDto } from 'src/dtos/user.dto';
|
import { UserResponseDto } from 'src/dtos/user.dto';
|
||||||
import { Auth, Authenticated, GetLoginDetails, PublicRoute } from 'src/middleware/auth.guard';
|
import { Auth, Authenticated, GetLoginDetails } from 'src/middleware/auth.guard';
|
||||||
import { AuthService, LoginDetails } from 'src/services/auth.service';
|
import { AuthService, LoginDetails } from 'src/services/auth.service';
|
||||||
import { respondWithCookie } from 'src/utils/response';
|
import { respondWithCookie } from 'src/utils/response';
|
||||||
|
|
||||||
@ApiTags('OAuth')
|
@ApiTags('OAuth')
|
||||||
@Controller('oauth')
|
@Controller('oauth')
|
||||||
@Authenticated()
|
|
||||||
export class OAuthController {
|
export class OAuthController {
|
||||||
constructor(private service: AuthService) {}
|
constructor(private service: AuthService) {}
|
||||||
|
|
||||||
@PublicRoute()
|
|
||||||
@Get('mobile-redirect')
|
@Get('mobile-redirect')
|
||||||
@Redirect()
|
@Redirect()
|
||||||
redirectOAuthToMobile(@Req() request: Request) {
|
redirectOAuthToMobile(@Req() request: Request) {
|
||||||
@@ -31,13 +30,11 @@ export class OAuthController {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@PublicRoute()
|
|
||||||
@Post('authorize')
|
@Post('authorize')
|
||||||
startOAuth(@Body() dto: OAuthConfigDto): Promise<OAuthAuthorizeResponseDto> {
|
startOAuth(@Body() dto: OAuthConfigDto): Promise<OAuthAuthorizeResponseDto> {
|
||||||
return this.service.authorize(dto);
|
return this.service.authorize(dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PublicRoute()
|
|
||||||
@Post('callback')
|
@Post('callback')
|
||||||
async finishOAuth(
|
async finishOAuth(
|
||||||
@Res({ passthrough: true }) res: Response,
|
@Res({ passthrough: true }) res: Response,
|
||||||
@@ -56,11 +53,13 @@ export class OAuthController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Post('link')
|
@Post('link')
|
||||||
|
@Authenticated(Permission.AUTH_OAUTH)
|
||||||
linkOAuthAccount(@Auth() auth: AuthDto, @Body() dto: OAuthCallbackDto): Promise<UserResponseDto> {
|
linkOAuthAccount(@Auth() auth: AuthDto, @Body() dto: OAuthCallbackDto): Promise<UserResponseDto> {
|
||||||
return this.service.link(auth, dto);
|
return this.service.link(auth, dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post('unlink')
|
@Post('unlink')
|
||||||
|
@Authenticated(Permission.AUTH_OAUTH)
|
||||||
unlinkOAuthAccount(@Auth() auth: AuthDto): Promise<UserResponseDto> {
|
unlinkOAuthAccount(@Auth() auth: AuthDto): Promise<UserResponseDto> {
|
||||||
return this.service.unlink(auth);
|
return this.service.unlink(auth);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Body, Controller, Delete, Get, Param, Post, Put, Query } from '@nestjs/common';
|
import { Body, Controller, Delete, Get, Param, Post, Put, Query } from '@nestjs/common';
|
||||||
import { ApiQuery, ApiTags } from '@nestjs/swagger';
|
import { ApiQuery, ApiTags } from '@nestjs/swagger';
|
||||||
import { AuthDto } from 'src/dtos/auth.dto';
|
import { AuthDto, Permission } from 'src/dtos/auth.dto';
|
||||||
import { PartnerResponseDto, UpdatePartnerDto } from 'src/dtos/partner.dto';
|
import { PartnerResponseDto, UpdatePartnerDto } from 'src/dtos/partner.dto';
|
||||||
import { PartnerDirection } from 'src/interfaces/partner.interface';
|
import { PartnerDirection } from 'src/interfaces/partner.interface';
|
||||||
import { Auth, Authenticated } from 'src/middleware/auth.guard';
|
import { Auth, Authenticated } from 'src/middleware/auth.guard';
|
||||||
@@ -9,11 +9,11 @@ import { UUIDParamDto } from 'src/validation';
|
|||||||
|
|
||||||
@ApiTags('Partner')
|
@ApiTags('Partner')
|
||||||
@Controller('partner')
|
@Controller('partner')
|
||||||
@Authenticated()
|
|
||||||
export class PartnerController {
|
export class PartnerController {
|
||||||
constructor(private service: PartnerService) {}
|
constructor(private service: PartnerService) {}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
|
@Authenticated(Permission.PARTNER_READ)
|
||||||
@ApiQuery({ name: 'direction', type: 'string', enum: PartnerDirection, required: true })
|
@ApiQuery({ name: 'direction', type: 'string', enum: PartnerDirection, required: true })
|
||||||
// TODO: remove 'direction' and convert to full query dto
|
// TODO: remove 'direction' and convert to full query dto
|
||||||
getPartners(@Auth() auth: AuthDto, @Query('direction') direction: PartnerDirection): Promise<PartnerResponseDto[]> {
|
getPartners(@Auth() auth: AuthDto, @Query('direction') direction: PartnerDirection): Promise<PartnerResponseDto[]> {
|
||||||
@@ -21,11 +21,13 @@ export class PartnerController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Post(':id')
|
@Post(':id')
|
||||||
|
@Authenticated(Permission.PARTNER_CREATE)
|
||||||
createPartner(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<PartnerResponseDto> {
|
createPartner(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<PartnerResponseDto> {
|
||||||
return this.service.create(auth, id);
|
return this.service.create(auth, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Put(':id')
|
@Put(':id')
|
||||||
|
@Authenticated(Permission.PARTNER_UPDATE)
|
||||||
updatePartner(
|
updatePartner(
|
||||||
@Auth() auth: AuthDto,
|
@Auth() auth: AuthDto,
|
||||||
@Param() { id }: UUIDParamDto,
|
@Param() { id }: UUIDParamDto,
|
||||||
@@ -35,6 +37,7 @@ export class PartnerController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Delete(':id')
|
@Delete(':id')
|
||||||
|
@Authenticated(Permission.PARTNER_DELETE)
|
||||||
removePartner(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<void> {
|
removePartner(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<void> {
|
||||||
return this.service.remove(auth, id);
|
return this.service.remove(auth, id);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { ApiTags } from '@nestjs/swagger';
|
|||||||
import { NextFunction, Response } from 'express';
|
import { NextFunction, Response } from 'express';
|
||||||
import { BulkIdResponseDto } from 'src/dtos/asset-ids.response.dto';
|
import { BulkIdResponseDto } from 'src/dtos/asset-ids.response.dto';
|
||||||
import { AssetResponseDto } from 'src/dtos/asset-response.dto';
|
import { AssetResponseDto } from 'src/dtos/asset-response.dto';
|
||||||
import { AuthDto } from 'src/dtos/auth.dto';
|
import { AuthDto, Permission } from 'src/dtos/auth.dto';
|
||||||
import {
|
import {
|
||||||
AssetFaceUpdateDto,
|
AssetFaceUpdateDto,
|
||||||
MergePersonDto,
|
MergePersonDto,
|
||||||
@@ -22,31 +22,35 @@ import { UUIDParamDto } from 'src/validation';
|
|||||||
|
|
||||||
@ApiTags('Person')
|
@ApiTags('Person')
|
||||||
@Controller('person')
|
@Controller('person')
|
||||||
@Authenticated()
|
|
||||||
export class PersonController {
|
export class PersonController {
|
||||||
constructor(private service: PersonService) {}
|
constructor(private service: PersonService) {}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
|
@Authenticated(Permission.PERSON_READ)
|
||||||
getAllPeople(@Auth() auth: AuthDto, @Query() withHidden: PersonSearchDto): Promise<PeopleResponseDto> {
|
getAllPeople(@Auth() auth: AuthDto, @Query() withHidden: PersonSearchDto): Promise<PeopleResponseDto> {
|
||||||
return this.service.getAll(auth, withHidden);
|
return this.service.getAll(auth, withHidden);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post()
|
@Post()
|
||||||
|
@Authenticated(Permission.PERSON_CREATE)
|
||||||
createPerson(@Auth() auth: AuthDto, @Body() dto: PersonCreateDto): Promise<PersonResponseDto> {
|
createPerson(@Auth() auth: AuthDto, @Body() dto: PersonCreateDto): Promise<PersonResponseDto> {
|
||||||
return this.service.create(auth, dto);
|
return this.service.create(auth, dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Put()
|
@Put()
|
||||||
|
@Authenticated(Permission.PERSON_UPDATE)
|
||||||
updatePeople(@Auth() auth: AuthDto, @Body() dto: PeopleUpdateDto): Promise<BulkIdResponseDto[]> {
|
updatePeople(@Auth() auth: AuthDto, @Body() dto: PeopleUpdateDto): Promise<BulkIdResponseDto[]> {
|
||||||
return this.service.updateAll(auth, dto);
|
return this.service.updateAll(auth, dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get(':id')
|
@Get(':id')
|
||||||
|
@Authenticated(Permission.PERSON_READ)
|
||||||
getPerson(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<PersonResponseDto> {
|
getPerson(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<PersonResponseDto> {
|
||||||
return this.service.getById(auth, id);
|
return this.service.getById(auth, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Put(':id')
|
@Put(':id')
|
||||||
|
@Authenticated(Permission.PERSON_UPDATE)
|
||||||
updatePerson(
|
updatePerson(
|
||||||
@Auth() auth: AuthDto,
|
@Auth() auth: AuthDto,
|
||||||
@Param() { id }: UUIDParamDto,
|
@Param() { id }: UUIDParamDto,
|
||||||
@@ -56,11 +60,13 @@ export class PersonController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Get(':id/statistics')
|
@Get(':id/statistics')
|
||||||
|
@Authenticated(Permission.PERSON_READ)
|
||||||
getPersonStatistics(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<PersonStatisticsResponseDto> {
|
getPersonStatistics(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<PersonStatisticsResponseDto> {
|
||||||
return this.service.getStatistics(auth, id);
|
return this.service.getStatistics(auth, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get(':id/thumbnail')
|
@Get(':id/thumbnail')
|
||||||
|
@Authenticated(Permission.PERSON_READ)
|
||||||
@FileResponse()
|
@FileResponse()
|
||||||
async getPersonThumbnail(
|
async getPersonThumbnail(
|
||||||
@Res() res: Response,
|
@Res() res: Response,
|
||||||
@@ -72,11 +78,13 @@ export class PersonController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Get(':id/assets')
|
@Get(':id/assets')
|
||||||
|
@Authenticated(Permission.ASSET_READ)
|
||||||
getPersonAssets(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<AssetResponseDto[]> {
|
getPersonAssets(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<AssetResponseDto[]> {
|
||||||
return this.service.getAssets(auth, id);
|
return this.service.getAssets(auth, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Put(':id/reassign')
|
@Put(':id/reassign')
|
||||||
|
@Authenticated(Permission.PERSON_UPDATE)
|
||||||
reassignFaces(
|
reassignFaces(
|
||||||
@Auth() auth: AuthDto,
|
@Auth() auth: AuthDto,
|
||||||
@Param() { id }: UUIDParamDto,
|
@Param() { id }: UUIDParamDto,
|
||||||
@@ -86,6 +94,7 @@ export class PersonController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Post(':id/merge')
|
@Post(':id/merge')
|
||||||
|
@Authenticated(Permission.PERSON_UPDATE)
|
||||||
mergePerson(
|
mergePerson(
|
||||||
@Auth() auth: AuthDto,
|
@Auth() auth: AuthDto,
|
||||||
@Param() { id }: UUIDParamDto,
|
@Param() { id }: UUIDParamDto,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Body, Controller, Get, HttpCode, HttpStatus, Post, Query } from '@nestjs/common';
|
import { Body, Controller, Get, HttpCode, HttpStatus, Post, Query } from '@nestjs/common';
|
||||||
import { ApiOperation, ApiTags } from '@nestjs/swagger';
|
import { ApiOperation, ApiTags } from '@nestjs/swagger';
|
||||||
import { AssetResponseDto } from 'src/dtos/asset-response.dto';
|
import { AssetResponseDto } from 'src/dtos/asset-response.dto';
|
||||||
import { AuthDto } from 'src/dtos/auth.dto';
|
import { AuthDto, Permission } from 'src/dtos/auth.dto';
|
||||||
import { PersonResponseDto } from 'src/dtos/person.dto';
|
import { PersonResponseDto } from 'src/dtos/person.dto';
|
||||||
import {
|
import {
|
||||||
MetadataSearchDto,
|
MetadataSearchDto,
|
||||||
@@ -19,49 +19,56 @@ import { SearchService } from 'src/services/search.service';
|
|||||||
|
|
||||||
@ApiTags('Search')
|
@ApiTags('Search')
|
||||||
@Controller('search')
|
@Controller('search')
|
||||||
@Authenticated()
|
|
||||||
export class SearchController {
|
export class SearchController {
|
||||||
constructor(private service: SearchService) {}
|
constructor(private service: SearchService) {}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
|
@Authenticated(Permission.ASSET_READ)
|
||||||
@ApiOperation({ deprecated: true })
|
@ApiOperation({ deprecated: true })
|
||||||
search(@Auth() auth: AuthDto, @Query() dto: SearchDto): Promise<SearchResponseDto> {
|
search(@Auth() auth: AuthDto, @Query() dto: SearchDto): Promise<SearchResponseDto> {
|
||||||
return this.service.search(auth, dto);
|
return this.service.search(auth, dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post('metadata')
|
@Post('metadata')
|
||||||
|
@Authenticated(Permission.ASSET_READ)
|
||||||
@HttpCode(HttpStatus.OK)
|
@HttpCode(HttpStatus.OK)
|
||||||
searchMetadata(@Auth() auth: AuthDto, @Body() dto: MetadataSearchDto): Promise<SearchResponseDto> {
|
searchMetadata(@Auth() auth: AuthDto, @Body() dto: MetadataSearchDto): Promise<SearchResponseDto> {
|
||||||
return this.service.searchMetadata(auth, dto);
|
return this.service.searchMetadata(auth, dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post('smart')
|
@Post('smart')
|
||||||
|
@Authenticated(Permission.ASSET_READ)
|
||||||
@HttpCode(HttpStatus.OK)
|
@HttpCode(HttpStatus.OK)
|
||||||
searchSmart(@Auth() auth: AuthDto, @Body() dto: SmartSearchDto): Promise<SearchResponseDto> {
|
searchSmart(@Auth() auth: AuthDto, @Body() dto: SmartSearchDto): Promise<SearchResponseDto> {
|
||||||
return this.service.searchSmart(auth, dto);
|
return this.service.searchSmart(auth, dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get('explore')
|
@Get('explore')
|
||||||
|
@Authenticated(Permission.ASSET_READ)
|
||||||
getExploreData(@Auth() auth: AuthDto): Promise<SearchExploreResponseDto[]> {
|
getExploreData(@Auth() auth: AuthDto): Promise<SearchExploreResponseDto[]> {
|
||||||
return this.service.getExploreData(auth) as Promise<SearchExploreResponseDto[]>;
|
return this.service.getExploreData(auth) as Promise<SearchExploreResponseDto[]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get('person')
|
@Get('person')
|
||||||
|
@Authenticated(Permission.PERSON_READ)
|
||||||
searchPerson(@Auth() auth: AuthDto, @Query() dto: SearchPeopleDto): Promise<PersonResponseDto[]> {
|
searchPerson(@Auth() auth: AuthDto, @Query() dto: SearchPeopleDto): Promise<PersonResponseDto[]> {
|
||||||
return this.service.searchPerson(auth, dto);
|
return this.service.searchPerson(auth, dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get('places')
|
@Get('places')
|
||||||
|
@Authenticated(Permission.ASSET_READ)
|
||||||
searchPlaces(@Query() dto: SearchPlacesDto): Promise<PlacesResponseDto[]> {
|
searchPlaces(@Query() dto: SearchPlacesDto): Promise<PlacesResponseDto[]> {
|
||||||
return this.service.searchPlaces(dto);
|
return this.service.searchPlaces(dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get('cities')
|
@Get('cities')
|
||||||
|
@Authenticated(Permission.ASSET_READ)
|
||||||
getAssetsByCity(@Auth() auth: AuthDto): Promise<AssetResponseDto[]> {
|
getAssetsByCity(@Auth() auth: AuthDto): Promise<AssetResponseDto[]> {
|
||||||
return this.service.getAssetsByCity(auth);
|
return this.service.getAssetsByCity(auth);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get('suggestions')
|
@Get('suggestions')
|
||||||
|
@Authenticated(Permission.ASSET_READ)
|
||||||
getSearchSuggestions(@Auth() auth: AuthDto, @Query() dto: SearchSuggestionRequestDto): Promise<string[]> {
|
getSearchSuggestions(@Auth() auth: AuthDto, @Query() dto: SearchSuggestionRequestDto): Promise<string[]> {
|
||||||
return this.service.getSearchSuggestions(auth, dto);
|
return this.service.getSearchSuggestions(auth, dto);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { Controller, Get, HttpCode, HttpStatus, Post } from '@nestjs/common';
|
import { Controller, Get } from '@nestjs/common';
|
||||||
import { ApiTags } from '@nestjs/swagger';
|
import { ApiTags } from '@nestjs/swagger';
|
||||||
|
import { Permission } from 'src/dtos/auth.dto';
|
||||||
import {
|
import {
|
||||||
ServerConfigDto,
|
ServerConfigDto,
|
||||||
ServerFeaturesDto,
|
ServerFeaturesDto,
|
||||||
@@ -10,66 +11,53 @@ import {
|
|||||||
ServerThemeDto,
|
ServerThemeDto,
|
||||||
ServerVersionResponseDto,
|
ServerVersionResponseDto,
|
||||||
} from 'src/dtos/server-info.dto';
|
} from 'src/dtos/server-info.dto';
|
||||||
import { AdminRoute, Authenticated, PublicRoute } from 'src/middleware/auth.guard';
|
import { Authenticated } from 'src/middleware/auth.guard';
|
||||||
import { ServerInfoService } from 'src/services/server-info.service';
|
import { ServerInfoService } from 'src/services/server-info.service';
|
||||||
|
|
||||||
@ApiTags('Server Info')
|
@ApiTags('Server Info')
|
||||||
@Controller('server-info')
|
@Controller('server-info')
|
||||||
@Authenticated()
|
|
||||||
export class ServerInfoController {
|
export class ServerInfoController {
|
||||||
constructor(private service: ServerInfoService) {}
|
constructor(private service: ServerInfoService) {}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
|
@Authenticated(Permission.SERVER_READ)
|
||||||
getServerInfo(): Promise<ServerInfoResponseDto> {
|
getServerInfo(): Promise<ServerInfoResponseDto> {
|
||||||
return this.service.getInfo();
|
return this.service.getInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
@PublicRoute()
|
|
||||||
@Get('ping')
|
@Get('ping')
|
||||||
pingServer(): ServerPingResponse {
|
pingServer(): ServerPingResponse {
|
||||||
return this.service.ping();
|
return this.service.ping();
|
||||||
}
|
}
|
||||||
|
|
||||||
@PublicRoute()
|
|
||||||
@Get('version')
|
@Get('version')
|
||||||
getServerVersion(): ServerVersionResponseDto {
|
getServerVersion(): ServerVersionResponseDto {
|
||||||
return this.service.getVersion();
|
return this.service.getVersion();
|
||||||
}
|
}
|
||||||
|
|
||||||
@PublicRoute()
|
|
||||||
@Get('features')
|
@Get('features')
|
||||||
getServerFeatures(): Promise<ServerFeaturesDto> {
|
getServerFeatures(): Promise<ServerFeaturesDto> {
|
||||||
return this.service.getFeatures();
|
return this.service.getFeatures();
|
||||||
}
|
}
|
||||||
|
|
||||||
@PublicRoute()
|
|
||||||
@Get('theme')
|
@Get('theme')
|
||||||
getTheme(): Promise<ServerThemeDto> {
|
getTheme(): Promise<ServerThemeDto> {
|
||||||
return this.service.getTheme();
|
return this.service.getTheme();
|
||||||
}
|
}
|
||||||
|
|
||||||
@PublicRoute()
|
|
||||||
@Get('config')
|
@Get('config')
|
||||||
getServerConfig(): Promise<ServerConfigDto> {
|
getServerConfig(): Promise<ServerConfigDto> {
|
||||||
return this.service.getConfig();
|
return this.service.getConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
@AdminRoute()
|
|
||||||
@Get('statistics')
|
@Get('statistics')
|
||||||
|
@Authenticated(Permission.SERVER_READ)
|
||||||
getServerStatistics(): Promise<ServerStatsResponseDto> {
|
getServerStatistics(): Promise<ServerStatsResponseDto> {
|
||||||
return this.service.getStatistics();
|
return this.service.getStatistics();
|
||||||
}
|
}
|
||||||
|
|
||||||
@PublicRoute()
|
|
||||||
@Get('media-types')
|
@Get('media-types')
|
||||||
getSupportedMediaTypes(): ServerMediaTypesResponseDto {
|
getSupportedMediaTypes(): ServerMediaTypesResponseDto {
|
||||||
return this.service.getSupportedMediaTypes();
|
return this.service.getSupportedMediaTypes();
|
||||||
}
|
}
|
||||||
|
|
||||||
@AdminRoute()
|
|
||||||
@Post('admin-onboarding')
|
|
||||||
@HttpCode(HttpStatus.NO_CONTENT)
|
|
||||||
setAdminOnboarding(): Promise<void> {
|
|
||||||
return this.service.setAdminOnboarding();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Controller, Delete, Get, HttpCode, HttpStatus, Param } from '@nestjs/common';
|
import { Controller, Delete, Get, HttpCode, HttpStatus, Param } from '@nestjs/common';
|
||||||
import { ApiTags } from '@nestjs/swagger';
|
import { ApiTags } from '@nestjs/swagger';
|
||||||
import { AuthDto } from 'src/dtos/auth.dto';
|
import { AuthDto, Permission } from 'src/dtos/auth.dto';
|
||||||
import { SessionResponseDto } from 'src/dtos/session.dto';
|
import { SessionResponseDto } from 'src/dtos/session.dto';
|
||||||
import { Auth, Authenticated } from 'src/middleware/auth.guard';
|
import { Auth, Authenticated } from 'src/middleware/auth.guard';
|
||||||
import { SessionService } from 'src/services/session.service';
|
import { SessionService } from 'src/services/session.service';
|
||||||
@@ -8,22 +8,24 @@ import { UUIDParamDto } from 'src/validation';
|
|||||||
|
|
||||||
@ApiTags('Sessions')
|
@ApiTags('Sessions')
|
||||||
@Controller('sessions')
|
@Controller('sessions')
|
||||||
@Authenticated()
|
|
||||||
export class SessionController {
|
export class SessionController {
|
||||||
constructor(private service: SessionService) {}
|
constructor(private service: SessionService) {}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
|
@Authenticated(Permission.SESSION_READ)
|
||||||
getSessions(@Auth() auth: AuthDto): Promise<SessionResponseDto[]> {
|
getSessions(@Auth() auth: AuthDto): Promise<SessionResponseDto[]> {
|
||||||
return this.service.getAll(auth);
|
return this.service.getAll(auth);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Delete()
|
@Delete()
|
||||||
|
@Authenticated(Permission.SESSION_DELETE)
|
||||||
@HttpCode(HttpStatus.NO_CONTENT)
|
@HttpCode(HttpStatus.NO_CONTENT)
|
||||||
deleteAllSessions(@Auth() auth: AuthDto): Promise<void> {
|
deleteAllSessions(@Auth() auth: AuthDto): Promise<void> {
|
||||||
return this.service.deleteAll(auth);
|
return this.service.deleteAll(auth);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Delete(':id')
|
@Delete(':id')
|
||||||
|
@Authenticated(Permission.SESSION_DELETE)
|
||||||
@HttpCode(HttpStatus.NO_CONTENT)
|
@HttpCode(HttpStatus.NO_CONTENT)
|
||||||
deleteSession(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<void> {
|
deleteSession(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<void> {
|
||||||
return this.service.delete(auth, id);
|
return this.service.delete(auth, id);
|
||||||
|
|||||||
@@ -3,14 +3,14 @@ import { ApiTags } from '@nestjs/swagger';
|
|||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
import { AssetIdsResponseDto } from 'src/dtos/asset-ids.response.dto';
|
import { AssetIdsResponseDto } from 'src/dtos/asset-ids.response.dto';
|
||||||
import { AssetIdsDto } from 'src/dtos/asset.dto';
|
import { AssetIdsDto } from 'src/dtos/asset.dto';
|
||||||
import { AuthDto, ImmichCookie } from 'src/dtos/auth.dto';
|
import { AuthDto, ImmichCookie, Permission } from 'src/dtos/auth.dto';
|
||||||
import {
|
import {
|
||||||
SharedLinkCreateDto,
|
SharedLinkCreateDto,
|
||||||
SharedLinkEditDto,
|
SharedLinkEditDto,
|
||||||
SharedLinkPasswordDto,
|
SharedLinkPasswordDto,
|
||||||
SharedLinkResponseDto,
|
SharedLinkResponseDto,
|
||||||
} from 'src/dtos/shared-link.dto';
|
} from 'src/dtos/shared-link.dto';
|
||||||
import { Auth, Authenticated, GetLoginDetails, SharedLinkRoute } from 'src/middleware/auth.guard';
|
import { Auth, Authenticated, GetLoginDetails } from 'src/middleware/auth.guard';
|
||||||
import { LoginDetails } from 'src/services/auth.service';
|
import { LoginDetails } from 'src/services/auth.service';
|
||||||
import { SharedLinkService } from 'src/services/shared-link.service';
|
import { SharedLinkService } from 'src/services/shared-link.service';
|
||||||
import { respondWithCookie } from 'src/utils/response';
|
import { respondWithCookie } from 'src/utils/response';
|
||||||
@@ -18,17 +18,17 @@ import { UUIDParamDto } from 'src/validation';
|
|||||||
|
|
||||||
@ApiTags('Shared Link')
|
@ApiTags('Shared Link')
|
||||||
@Controller('shared-link')
|
@Controller('shared-link')
|
||||||
@Authenticated()
|
|
||||||
export class SharedLinkController {
|
export class SharedLinkController {
|
||||||
constructor(private service: SharedLinkService) {}
|
constructor(private service: SharedLinkService) {}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
|
@Authenticated(Permission.SHARED_LINK_READ)
|
||||||
getAllSharedLinks(@Auth() auth: AuthDto): Promise<SharedLinkResponseDto[]> {
|
getAllSharedLinks(@Auth() auth: AuthDto): Promise<SharedLinkResponseDto[]> {
|
||||||
return this.service.getAll(auth);
|
return this.service.getAll(auth);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SharedLinkRoute()
|
|
||||||
@Get('me')
|
@Get('me')
|
||||||
|
@Authenticated(Permission.SHARED_LINK_READ, { sharedLink: true })
|
||||||
async getMySharedLink(
|
async getMySharedLink(
|
||||||
@Auth() auth: AuthDto,
|
@Auth() auth: AuthDto,
|
||||||
@Query() dto: SharedLinkPasswordDto,
|
@Query() dto: SharedLinkPasswordDto,
|
||||||
@@ -48,16 +48,19 @@ export class SharedLinkController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Get(':id')
|
@Get(':id')
|
||||||
|
@Authenticated(Permission.SHARED_LINK_READ)
|
||||||
getSharedLinkById(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<SharedLinkResponseDto> {
|
getSharedLinkById(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<SharedLinkResponseDto> {
|
||||||
return this.service.get(auth, id);
|
return this.service.get(auth, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post()
|
@Post()
|
||||||
|
@Authenticated(Permission.SHARED_LINK_CREATE)
|
||||||
createSharedLink(@Auth() auth: AuthDto, @Body() dto: SharedLinkCreateDto) {
|
createSharedLink(@Auth() auth: AuthDto, @Body() dto: SharedLinkCreateDto) {
|
||||||
return this.service.create(auth, dto);
|
return this.service.create(auth, dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Patch(':id')
|
@Patch(':id')
|
||||||
|
@Authenticated(Permission.SHARED_LINK_UPDATE)
|
||||||
updateSharedLink(
|
updateSharedLink(
|
||||||
@Auth() auth: AuthDto,
|
@Auth() auth: AuthDto,
|
||||||
@Param() { id }: UUIDParamDto,
|
@Param() { id }: UUIDParamDto,
|
||||||
@@ -67,12 +70,13 @@ export class SharedLinkController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Delete(':id')
|
@Delete(':id')
|
||||||
|
@Authenticated(Permission.SHARED_LINK_DELETE)
|
||||||
removeSharedLink(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<void> {
|
removeSharedLink(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<void> {
|
||||||
return this.service.remove(auth, id);
|
return this.service.remove(auth, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SharedLinkRoute()
|
|
||||||
@Put(':id/assets')
|
@Put(':id/assets')
|
||||||
|
@Authenticated(Permission.SHARED_LINK_UPDATE, { sharedLink: true })
|
||||||
addSharedLinkAssets(
|
addSharedLinkAssets(
|
||||||
@Auth() auth: AuthDto,
|
@Auth() auth: AuthDto,
|
||||||
@Param() { id }: UUIDParamDto,
|
@Param() { id }: UUIDParamDto,
|
||||||
@@ -81,8 +85,8 @@ export class SharedLinkController {
|
|||||||
return this.service.addAssets(auth, id, dto);
|
return this.service.addAssets(auth, id, dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SharedLinkRoute()
|
|
||||||
@Delete(':id/assets')
|
@Delete(':id/assets')
|
||||||
|
@Authenticated(Permission.SHARED_LINK_DELETE, { sharedLink: true })
|
||||||
removeSharedLinkAssets(
|
removeSharedLinkAssets(
|
||||||
@Auth() auth: AuthDto,
|
@Auth() auth: AuthDto,
|
||||||
@Param() { id }: UUIDParamDto,
|
@Param() { id }: UUIDParamDto,
|
||||||
|
|||||||
@@ -1,23 +1,24 @@
|
|||||||
import { Controller, Get, Query } from '@nestjs/common';
|
import { Controller, Get, Query } from '@nestjs/common';
|
||||||
import { ApiTags } from '@nestjs/swagger';
|
import { ApiTags } from '@nestjs/swagger';
|
||||||
import { AssetResponseDto } from 'src/dtos/asset-response.dto';
|
import { AssetResponseDto } from 'src/dtos/asset-response.dto';
|
||||||
import { AuthDto } from 'src/dtos/auth.dto';
|
import { AuthDto, Permission } from 'src/dtos/auth.dto';
|
||||||
import { AssetDeltaSyncDto, AssetDeltaSyncResponseDto, AssetFullSyncDto } from 'src/dtos/sync.dto';
|
import { AssetDeltaSyncDto, AssetDeltaSyncResponseDto, AssetFullSyncDto } from 'src/dtos/sync.dto';
|
||||||
import { Auth, Authenticated } from 'src/middleware/auth.guard';
|
import { Auth, Authenticated } from 'src/middleware/auth.guard';
|
||||||
import { SyncService } from 'src/services/sync.service';
|
import { SyncService } from 'src/services/sync.service';
|
||||||
|
|
||||||
@ApiTags('Sync')
|
@ApiTags('Sync')
|
||||||
@Controller('sync')
|
@Controller('sync')
|
||||||
@Authenticated()
|
|
||||||
export class SyncController {
|
export class SyncController {
|
||||||
constructor(private service: SyncService) {}
|
constructor(private service: SyncService) {}
|
||||||
|
|
||||||
@Get('full-sync')
|
@Get('full-sync')
|
||||||
|
@Authenticated(Permission.ASSET_READ)
|
||||||
getAllForUserFullSync(@Auth() auth: AuthDto, @Query() dto: AssetFullSyncDto): Promise<AssetResponseDto[]> {
|
getAllForUserFullSync(@Auth() auth: AuthDto, @Query() dto: AssetFullSyncDto): Promise<AssetResponseDto[]> {
|
||||||
return this.service.getAllAssetsForUserFullSync(auth, dto);
|
return this.service.getAllAssetsForUserFullSync(auth, dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get('delta-sync')
|
@Get('delta-sync')
|
||||||
|
@Authenticated(Permission.ASSET_READ)
|
||||||
getDeltaSync(@Auth() auth: AuthDto, @Query() dto: AssetDeltaSyncDto): Promise<AssetDeltaSyncResponseDto> {
|
getDeltaSync(@Auth() auth: AuthDto, @Query() dto: AssetDeltaSyncDto): Promise<AssetDeltaSyncResponseDto> {
|
||||||
return this.service.getChangesForDeltaSync(auth, dto);
|
return this.service.getChangesForDeltaSync(auth, dto);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,38 +1,41 @@
|
|||||||
import { Body, Controller, Get, Put, Query } from '@nestjs/common';
|
import { Body, Controller, Get, Put, Query } from '@nestjs/common';
|
||||||
import { ApiTags } from '@nestjs/swagger';
|
import { ApiTags } from '@nestjs/swagger';
|
||||||
|
import { Permission } from 'src/dtos/auth.dto';
|
||||||
import { MapThemeDto, SystemConfigDto, SystemConfigTemplateStorageOptionDto } from 'src/dtos/system-config.dto';
|
import { MapThemeDto, SystemConfigDto, SystemConfigTemplateStorageOptionDto } from 'src/dtos/system-config.dto';
|
||||||
import { AdminRoute, Authenticated, SharedLinkRoute } from 'src/middleware/auth.guard';
|
import { Authenticated } from 'src/middleware/auth.guard';
|
||||||
import { SystemConfigService } from 'src/services/system-config.service';
|
import { SystemConfigService } from 'src/services/system-config.service';
|
||||||
|
|
||||||
@ApiTags('System Config')
|
@ApiTags('System Config')
|
||||||
@Controller('system-config')
|
@Controller('system-config')
|
||||||
@Authenticated({ admin: true })
|
|
||||||
export class SystemConfigController {
|
export class SystemConfigController {
|
||||||
constructor(private service: SystemConfigService) {}
|
constructor(private service: SystemConfigService) {}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
|
@Authenticated(Permission.SYSTEM_CONFIG_READ)
|
||||||
getConfig(): Promise<SystemConfigDto> {
|
getConfig(): Promise<SystemConfigDto> {
|
||||||
return this.service.getConfig();
|
return this.service.getConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get('defaults')
|
@Get('defaults')
|
||||||
|
@Authenticated(Permission.SYSTEM_CONFIG_READ)
|
||||||
getConfigDefaults(): SystemConfigDto {
|
getConfigDefaults(): SystemConfigDto {
|
||||||
return this.service.getDefaults();
|
return this.service.getDefaults();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Put()
|
@Put()
|
||||||
|
@Authenticated(Permission.SYSTEM_CONFIG_UPDATE)
|
||||||
updateConfig(@Body() dto: SystemConfigDto): Promise<SystemConfigDto> {
|
updateConfig(@Body() dto: SystemConfigDto): Promise<SystemConfigDto> {
|
||||||
return this.service.updateConfig(dto);
|
return this.service.updateConfig(dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get('storage-template-options')
|
@Get('storage-template-options')
|
||||||
|
@Authenticated(Permission.SYSTEM_CONFIG_READ)
|
||||||
getStorageTemplateOptions(): SystemConfigTemplateStorageOptionDto {
|
getStorageTemplateOptions(): SystemConfigTemplateStorageOptionDto {
|
||||||
return this.service.getStorageTemplateOptions();
|
return this.service.getStorageTemplateOptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
@AdminRoute(false)
|
|
||||||
@SharedLinkRoute()
|
|
||||||
@Get('map/style.json')
|
@Get('map/style.json')
|
||||||
|
@Authenticated(Permission.MAP_READ, { sharedLink: true })
|
||||||
getMapStyle(@Query() dto: MapThemeDto) {
|
getMapStyle(@Query() dto: MapThemeDto) {
|
||||||
return this.service.getMapStyle(dto.theme);
|
return this.service.getMapStyle(dto.theme);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import { Body, Controller, Get, HttpCode, HttpStatus, Post } from '@nestjs/common';
|
||||||
|
import { ApiTags } from '@nestjs/swagger';
|
||||||
|
import { Permission } from 'src/dtos/auth.dto';
|
||||||
|
import { AdminOnboardingUpdateDto, ReverseGeocodingStateResponseDto } from 'src/dtos/system-metadata.dto';
|
||||||
|
import { Authenticated } from 'src/middleware/auth.guard';
|
||||||
|
import { SystemMetadataService } from 'src/services/system-metadata.service';
|
||||||
|
|
||||||
|
@ApiTags('System Metadata')
|
||||||
|
@Controller('system-metadata')
|
||||||
|
export class SystemMetadataController {
|
||||||
|
constructor(private service: SystemMetadataService) {}
|
||||||
|
|
||||||
|
@Get('admin-onboarding')
|
||||||
|
@Authenticated(Permission.SYSTEM_METADATA_READ)
|
||||||
|
getAdminOnboarding(): Promise<AdminOnboardingUpdateDto> {
|
||||||
|
return this.service.getAdminOnboarding();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post('admin-onboarding')
|
||||||
|
@Authenticated(Permission.SYSTEM_METADATA_UPDATE)
|
||||||
|
@HttpCode(HttpStatus.NO_CONTENT)
|
||||||
|
updateAdminOnboarding(@Body() dto: AdminOnboardingUpdateDto): Promise<void> {
|
||||||
|
return this.service.updateAdminOnboarding(dto);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get('reverse-geocoding-state')
|
||||||
|
@Authenticated(Permission.SYSTEM_METADATA_READ)
|
||||||
|
getReverseGeocodingState(): Promise<ReverseGeocodingStateResponseDto> {
|
||||||
|
return this.service.getReverseGeocodingState();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@ import { ApiTags } from '@nestjs/swagger';
|
|||||||
import { AssetIdsResponseDto } from 'src/dtos/asset-ids.response.dto';
|
import { AssetIdsResponseDto } from 'src/dtos/asset-ids.response.dto';
|
||||||
import { AssetResponseDto } from 'src/dtos/asset-response.dto';
|
import { AssetResponseDto } from 'src/dtos/asset-response.dto';
|
||||||
import { AssetIdsDto } from 'src/dtos/asset.dto';
|
import { AssetIdsDto } from 'src/dtos/asset.dto';
|
||||||
import { AuthDto } from 'src/dtos/auth.dto';
|
import { AuthDto, Permission } from 'src/dtos/auth.dto';
|
||||||
import { CreateTagDto, TagResponseDto, UpdateTagDto } from 'src/dtos/tag.dto';
|
import { CreateTagDto, TagResponseDto, UpdateTagDto } from 'src/dtos/tag.dto';
|
||||||
import { Auth, Authenticated } from 'src/middleware/auth.guard';
|
import { Auth, Authenticated } from 'src/middleware/auth.guard';
|
||||||
import { TagService } from 'src/services/tag.service';
|
import { TagService } from 'src/services/tag.service';
|
||||||
@@ -11,41 +11,47 @@ import { UUIDParamDto } from 'src/validation';
|
|||||||
|
|
||||||
@ApiTags('Tag')
|
@ApiTags('Tag')
|
||||||
@Controller('tag')
|
@Controller('tag')
|
||||||
@Authenticated()
|
|
||||||
export class TagController {
|
export class TagController {
|
||||||
constructor(private service: TagService) {}
|
constructor(private service: TagService) {}
|
||||||
|
|
||||||
@Post()
|
@Post()
|
||||||
|
@Authenticated(Permission.TAG_CREATE)
|
||||||
createTag(@Auth() auth: AuthDto, @Body() dto: CreateTagDto): Promise<TagResponseDto> {
|
createTag(@Auth() auth: AuthDto, @Body() dto: CreateTagDto): Promise<TagResponseDto> {
|
||||||
return this.service.create(auth, dto);
|
return this.service.create(auth, dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
|
@Authenticated(Permission.TAG_READ)
|
||||||
getAllTags(@Auth() auth: AuthDto): Promise<TagResponseDto[]> {
|
getAllTags(@Auth() auth: AuthDto): Promise<TagResponseDto[]> {
|
||||||
return this.service.getAll(auth);
|
return this.service.getAll(auth);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get(':id')
|
@Get(':id')
|
||||||
|
@Authenticated(Permission.TAG_READ)
|
||||||
getTagById(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<TagResponseDto> {
|
getTagById(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<TagResponseDto> {
|
||||||
return this.service.getById(auth, id);
|
return this.service.getById(auth, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Patch(':id')
|
@Patch(':id')
|
||||||
|
@Authenticated(Permission.TAG_UPDATE)
|
||||||
updateTag(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto, @Body() dto: UpdateTagDto): Promise<TagResponseDto> {
|
updateTag(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto, @Body() dto: UpdateTagDto): Promise<TagResponseDto> {
|
||||||
return this.service.update(auth, id, dto);
|
return this.service.update(auth, id, dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Delete(':id')
|
@Delete(':id')
|
||||||
|
@Authenticated(Permission.TAG_DELETE)
|
||||||
deleteTag(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<void> {
|
deleteTag(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<void> {
|
||||||
return this.service.remove(auth, id);
|
return this.service.remove(auth, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get(':id/assets')
|
@Get(':id/assets')
|
||||||
|
@Authenticated(Permission.TAG_READ)
|
||||||
getTagAssets(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<AssetResponseDto[]> {
|
getTagAssets(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<AssetResponseDto[]> {
|
||||||
return this.service.getAssets(auth, id);
|
return this.service.getAssets(auth, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Put(':id/assets')
|
@Put(':id/assets')
|
||||||
|
@Authenticated(Permission.TAG_UPDATE)
|
||||||
tagAssets(
|
tagAssets(
|
||||||
@Auth() auth: AuthDto,
|
@Auth() auth: AuthDto,
|
||||||
@Param() { id }: UUIDParamDto,
|
@Param() { id }: UUIDParamDto,
|
||||||
@@ -55,6 +61,7 @@ export class TagController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Delete(':id/assets')
|
@Delete(':id/assets')
|
||||||
|
@Authenticated(Permission.TAG_UPDATE)
|
||||||
untagAssets(
|
untagAssets(
|
||||||
@Auth() auth: AuthDto,
|
@Auth() auth: AuthDto,
|
||||||
@Body() dto: AssetIdsDto,
|
@Body() dto: AssetIdsDto,
|
||||||
|
|||||||
@@ -1,24 +1,23 @@
|
|||||||
import { Controller, Get, Query } from '@nestjs/common';
|
import { Controller, Get, Query } from '@nestjs/common';
|
||||||
import { ApiTags } from '@nestjs/swagger';
|
import { ApiTags } from '@nestjs/swagger';
|
||||||
import { AssetResponseDto } from 'src/dtos/asset-response.dto';
|
import { AssetResponseDto } from 'src/dtos/asset-response.dto';
|
||||||
import { AuthDto } from 'src/dtos/auth.dto';
|
import { AuthDto, Permission } from 'src/dtos/auth.dto';
|
||||||
import { TimeBucketAssetDto, TimeBucketDto, TimeBucketResponseDto } from 'src/dtos/time-bucket.dto';
|
import { TimeBucketAssetDto, TimeBucketDto, TimeBucketResponseDto } from 'src/dtos/time-bucket.dto';
|
||||||
import { Auth, Authenticated } from 'src/middleware/auth.guard';
|
import { Auth, Authenticated } from 'src/middleware/auth.guard';
|
||||||
import { TimelineService } from 'src/services/timeline.service';
|
import { TimelineService } from 'src/services/timeline.service';
|
||||||
|
|
||||||
@ApiTags('Timeline')
|
@ApiTags('Timeline')
|
||||||
@Controller('timeline')
|
@Controller('timeline')
|
||||||
@Authenticated()
|
|
||||||
export class TimelineController {
|
export class TimelineController {
|
||||||
constructor(private service: TimelineService) {}
|
constructor(private service: TimelineService) {}
|
||||||
|
|
||||||
@Authenticated({ isShared: true })
|
@Authenticated(Permission.ASSET_READ, { sharedLink: true })
|
||||||
@Get('buckets')
|
@Get('buckets')
|
||||||
getTimeBuckets(@Auth() auth: AuthDto, @Query() dto: TimeBucketDto): Promise<TimeBucketResponseDto[]> {
|
getTimeBuckets(@Auth() auth: AuthDto, @Query() dto: TimeBucketDto): Promise<TimeBucketResponseDto[]> {
|
||||||
return this.service.getTimeBuckets(auth, dto);
|
return this.service.getTimeBuckets(auth, dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Authenticated({ isShared: true })
|
@Authenticated(Permission.ASSET_READ, { sharedLink: true })
|
||||||
@Get('bucket')
|
@Get('bucket')
|
||||||
getTimeBucket(@Auth() auth: AuthDto, @Query() dto: TimeBucketAssetDto): Promise<AssetResponseDto[]> {
|
getTimeBucket(@Auth() auth: AuthDto, @Query() dto: TimeBucketAssetDto): Promise<AssetResponseDto[]> {
|
||||||
return this.service.getTimeBucket(auth, dto) as Promise<AssetResponseDto[]>;
|
return this.service.getTimeBucket(auth, dto) as Promise<AssetResponseDto[]>;
|
||||||
|
|||||||
@@ -1,29 +1,31 @@
|
|||||||
import { Body, Controller, HttpCode, HttpStatus, Post } from '@nestjs/common';
|
import { Body, Controller, HttpCode, HttpStatus, Post } from '@nestjs/common';
|
||||||
import { ApiTags } from '@nestjs/swagger';
|
import { ApiTags } from '@nestjs/swagger';
|
||||||
import { BulkIdsDto } from 'src/dtos/asset-ids.response.dto';
|
import { BulkIdsDto } from 'src/dtos/asset-ids.response.dto';
|
||||||
import { AuthDto } from 'src/dtos/auth.dto';
|
import { AuthDto, Permission } from 'src/dtos/auth.dto';
|
||||||
import { Auth, Authenticated } from 'src/middleware/auth.guard';
|
import { Auth, Authenticated } from 'src/middleware/auth.guard';
|
||||||
import { TrashService } from 'src/services/trash.service';
|
import { TrashService } from 'src/services/trash.service';
|
||||||
|
|
||||||
@ApiTags('Trash')
|
@ApiTags('Trash')
|
||||||
@Controller('trash')
|
@Controller('trash')
|
||||||
@Authenticated()
|
|
||||||
export class TrashController {
|
export class TrashController {
|
||||||
constructor(private service: TrashService) {}
|
constructor(private service: TrashService) {}
|
||||||
|
|
||||||
@Post('empty')
|
@Post('empty')
|
||||||
|
@Authenticated(Permission.ASSET_DELETE)
|
||||||
@HttpCode(HttpStatus.NO_CONTENT)
|
@HttpCode(HttpStatus.NO_CONTENT)
|
||||||
emptyTrash(@Auth() auth: AuthDto): Promise<void> {
|
emptyTrash(@Auth() auth: AuthDto): Promise<void> {
|
||||||
return this.service.empty(auth);
|
return this.service.empty(auth);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post('restore')
|
@Post('restore')
|
||||||
|
@Authenticated(Permission.ASSET_DELETE)
|
||||||
@HttpCode(HttpStatus.NO_CONTENT)
|
@HttpCode(HttpStatus.NO_CONTENT)
|
||||||
restoreTrash(@Auth() auth: AuthDto): Promise<void> {
|
restoreTrash(@Auth() auth: AuthDto): Promise<void> {
|
||||||
return this.service.restore(auth);
|
return this.service.restore(auth);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post('restore/assets')
|
@Post('restore/assets')
|
||||||
|
@Authenticated(Permission.ASSET_DELETE)
|
||||||
@HttpCode(HttpStatus.NO_CONTENT)
|
@HttpCode(HttpStatus.NO_CONTENT)
|
||||||
restoreAssets(@Auth() auth: AuthDto, @Body() dto: BulkIdsDto): Promise<void> {
|
restoreAssets(@Auth() auth: AuthDto, @Body() dto: BulkIdsDto): Promise<void> {
|
||||||
return this.service.restoreAssets(auth, dto);
|
return this.service.restoreAssets(auth, dto);
|
||||||
|
|||||||
@@ -16,10 +16,10 @@ import {
|
|||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import { ApiBody, ApiConsumes, ApiTags } from '@nestjs/swagger';
|
import { ApiBody, ApiConsumes, ApiTags } from '@nestjs/swagger';
|
||||||
import { NextFunction, Response } from 'express';
|
import { NextFunction, Response } from 'express';
|
||||||
import { AuthDto } from 'src/dtos/auth.dto';
|
import { AuthDto, Permission } from 'src/dtos/auth.dto';
|
||||||
import { CreateProfileImageDto, CreateProfileImageResponseDto } from 'src/dtos/user-profile.dto';
|
import { CreateProfileImageDto, CreateProfileImageResponseDto } from 'src/dtos/user-profile.dto';
|
||||||
import { CreateUserDto, DeleteUserDto, UpdateUserDto, UserResponseDto } from 'src/dtos/user.dto';
|
import { CreateUserDto, DeleteUserDto, UpdateUserDto, UserResponseDto } from 'src/dtos/user.dto';
|
||||||
import { AdminRoute, Auth, Authenticated, FileResponse } from 'src/middleware/auth.guard';
|
import { Auth, Authenticated, FileResponse } from 'src/middleware/auth.guard';
|
||||||
import { FileUploadInterceptor, Route } from 'src/middleware/file-upload.interceptor';
|
import { FileUploadInterceptor, Route } from 'src/middleware/file-upload.interceptor';
|
||||||
import { UserService } from 'src/services/user.service';
|
import { UserService } from 'src/services/user.service';
|
||||||
import { sendFile } from 'src/utils/file';
|
import { sendFile } from 'src/utils/file';
|
||||||
@@ -27,39 +27,42 @@ import { UUIDParamDto } from 'src/validation';
|
|||||||
|
|
||||||
@ApiTags('User')
|
@ApiTags('User')
|
||||||
@Controller(Route.USER)
|
@Controller(Route.USER)
|
||||||
@Authenticated()
|
|
||||||
export class UserController {
|
export class UserController {
|
||||||
constructor(private service: UserService) {}
|
constructor(private service: UserService) {}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
|
@Authenticated(Permission.USER_READ)
|
||||||
getAllUsers(@Auth() auth: AuthDto, @Query('isAll') isAll: boolean): Promise<UserResponseDto[]> {
|
getAllUsers(@Auth() auth: AuthDto, @Query('isAll') isAll: boolean): Promise<UserResponseDto[]> {
|
||||||
return this.service.getAll(auth, isAll);
|
return this.service.getAll(auth, isAll);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get('info/:id')
|
@Get('info/:id')
|
||||||
|
@Authenticated(Permission.USER_READ)
|
||||||
getUserById(@Param() { id }: UUIDParamDto): Promise<UserResponseDto> {
|
getUserById(@Param() { id }: UUIDParamDto): Promise<UserResponseDto> {
|
||||||
return this.service.get(id);
|
return this.service.get(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get('me')
|
@Get('me')
|
||||||
|
@Authenticated(Permission.USER_READ)
|
||||||
getMyUserInfo(@Auth() auth: AuthDto): Promise<UserResponseDto> {
|
getMyUserInfo(@Auth() auth: AuthDto): Promise<UserResponseDto> {
|
||||||
return this.service.getMe(auth);
|
return this.service.getMe(auth);
|
||||||
}
|
}
|
||||||
|
|
||||||
@AdminRoute()
|
|
||||||
@Post()
|
@Post()
|
||||||
|
@Authenticated(Permission.USER_CREATE)
|
||||||
createUser(@Body() createUserDto: CreateUserDto): Promise<UserResponseDto> {
|
createUser(@Body() createUserDto: CreateUserDto): Promise<UserResponseDto> {
|
||||||
return this.service.create(createUserDto);
|
return this.service.create(createUserDto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Delete('profile-image')
|
@Delete('profile-image')
|
||||||
|
@Authenticated(Permission.USER_UPDATE)
|
||||||
@HttpCode(HttpStatus.NO_CONTENT)
|
@HttpCode(HttpStatus.NO_CONTENT)
|
||||||
deleteProfileImage(@Auth() auth: AuthDto): Promise<void> {
|
deleteProfileImage(@Auth() auth: AuthDto): Promise<void> {
|
||||||
return this.service.deleteProfileImage(auth);
|
return this.service.deleteProfileImage(auth);
|
||||||
}
|
}
|
||||||
|
|
||||||
@AdminRoute()
|
|
||||||
@Delete(':id')
|
@Delete(':id')
|
||||||
|
@Authenticated(Permission.USER_DELETE)
|
||||||
deleteUser(
|
deleteUser(
|
||||||
@Auth() auth: AuthDto,
|
@Auth() auth: AuthDto,
|
||||||
@Param() { id }: UUIDParamDto,
|
@Param() { id }: UUIDParamDto,
|
||||||
@@ -68,14 +71,15 @@ export class UserController {
|
|||||||
return this.service.delete(auth, id, dto);
|
return this.service.delete(auth, id, dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@AdminRoute()
|
|
||||||
@Post(':id/restore')
|
@Post(':id/restore')
|
||||||
|
@Authenticated(Permission.USER_DELETE)
|
||||||
restoreUser(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<UserResponseDto> {
|
restoreUser(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<UserResponseDto> {
|
||||||
return this.service.restore(auth, id);
|
return this.service.restore(auth, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: replace with @Put(':id')
|
// TODO: replace with @Put(':id')
|
||||||
@Put()
|
@Put()
|
||||||
|
@Authenticated(Permission.USER_UPDATE)
|
||||||
updateUser(@Auth() auth: AuthDto, @Body() updateUserDto: UpdateUserDto): Promise<UserResponseDto> {
|
updateUser(@Auth() auth: AuthDto, @Body() updateUserDto: UpdateUserDto): Promise<UserResponseDto> {
|
||||||
return this.service.update(auth, updateUserDto);
|
return this.service.update(auth, updateUserDto);
|
||||||
}
|
}
|
||||||
@@ -84,6 +88,7 @@ export class UserController {
|
|||||||
@ApiConsumes('multipart/form-data')
|
@ApiConsumes('multipart/form-data')
|
||||||
@ApiBody({ description: 'A new avatar for the user', type: CreateProfileImageDto })
|
@ApiBody({ description: 'A new avatar for the user', type: CreateProfileImageDto })
|
||||||
@Post('profile-image')
|
@Post('profile-image')
|
||||||
|
@Authenticated(Permission.USER_UPDATE)
|
||||||
createProfileImage(
|
createProfileImage(
|
||||||
@Auth() auth: AuthDto,
|
@Auth() auth: AuthDto,
|
||||||
@UploadedFile() fileInfo: Express.Multer.File,
|
@UploadedFile() fileInfo: Express.Multer.File,
|
||||||
@@ -92,6 +97,7 @@ export class UserController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Get('profile-image/:id')
|
@Get('profile-image/:id')
|
||||||
|
@Authenticated(Permission.USER_READ)
|
||||||
@FileResponse()
|
@FileResponse()
|
||||||
async getProfileImage(@Res() res: Response, @Next() next: NextFunction, @Param() { id }: UUIDParamDto) {
|
async getProfileImage(@Res() res: Response, @Next() next: NextFunction, @Param() { id }: UUIDParamDto) {
|
||||||
await sendFile(res, next, () => this.service.getProfileImage(id));
|
await sendFile(res, next, () => this.service.getProfileImage(id));
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { SharedLinkEntity } from 'src/entities/shared-link.entity';
|
|||||||
import { IAccessRepository } from 'src/interfaces/access.interface';
|
import { IAccessRepository } from 'src/interfaces/access.interface';
|
||||||
import { setDifference, setIsEqual, setUnion } from 'src/utils/set';
|
import { setDifference, setIsEqual, setUnion } from 'src/utils/set';
|
||||||
|
|
||||||
export enum Permission {
|
export enum AccessPermission {
|
||||||
ACTIVITY_CREATE = 'activity.create',
|
ACTIVITY_CREATE = 'activity.create',
|
||||||
ACTIVITY_DELETE = 'activity.delete',
|
ACTIVITY_DELETE = 'activity.delete',
|
||||||
|
|
||||||
@@ -74,7 +74,7 @@ export class AccessCore {
|
|||||||
* Check if user has access to all ids, for the given permission.
|
* Check if user has access to all ids, for the given permission.
|
||||||
* Throws error if user does not have access to any of the ids.
|
* Throws error if user does not have access to any of the ids.
|
||||||
*/
|
*/
|
||||||
async requirePermission(auth: AuthDto, permission: Permission, ids: string[] | string) {
|
async requirePermission(auth: AuthDto, permission: AccessPermission, ids: string[] | string) {
|
||||||
ids = Array.isArray(ids) ? ids : [ids];
|
ids = Array.isArray(ids) ? ids : [ids];
|
||||||
const allowedIds = await this.checkAccess(auth, permission, ids);
|
const allowedIds = await this.checkAccess(auth, permission, ids);
|
||||||
if (!setIsEqual(new Set(ids), allowedIds)) {
|
if (!setIsEqual(new Set(ids), allowedIds)) {
|
||||||
@@ -88,7 +88,7 @@ export class AccessCore {
|
|||||||
*
|
*
|
||||||
* @returns Set<string>
|
* @returns Set<string>
|
||||||
*/
|
*/
|
||||||
async checkAccess(auth: AuthDto, permission: Permission, ids: Set<string> | string[]): Promise<Set<string>> {
|
async checkAccess(auth: AuthDto, permission: AccessPermission, ids: Set<string> | string[]): Promise<Set<string>> {
|
||||||
const idSet = Array.isArray(ids) ? new Set(ids) : ids;
|
const idSet = Array.isArray(ids) ? new Set(ids) : ids;
|
||||||
if (idSet.size === 0) {
|
if (idSet.size === 0) {
|
||||||
return new Set();
|
return new Set();
|
||||||
@@ -103,40 +103,40 @@ export class AccessCore {
|
|||||||
|
|
||||||
private async checkAccessSharedLink(
|
private async checkAccessSharedLink(
|
||||||
sharedLink: SharedLinkEntity,
|
sharedLink: SharedLinkEntity,
|
||||||
permission: Permission,
|
permission: AccessPermission,
|
||||||
ids: Set<string>,
|
ids: Set<string>,
|
||||||
): Promise<Set<string>> {
|
): Promise<Set<string>> {
|
||||||
const sharedLinkId = sharedLink.id;
|
const sharedLinkId = sharedLink.id;
|
||||||
|
|
||||||
switch (permission) {
|
switch (permission) {
|
||||||
case Permission.ASSET_READ: {
|
case AccessPermission.ASSET_READ: {
|
||||||
return await this.repository.asset.checkSharedLinkAccess(sharedLinkId, ids);
|
return await this.repository.asset.checkSharedLinkAccess(sharedLinkId, ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Permission.ASSET_VIEW: {
|
case AccessPermission.ASSET_VIEW: {
|
||||||
return await this.repository.asset.checkSharedLinkAccess(sharedLinkId, ids);
|
return await this.repository.asset.checkSharedLinkAccess(sharedLinkId, ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Permission.ASSET_DOWNLOAD: {
|
case AccessPermission.ASSET_DOWNLOAD: {
|
||||||
return sharedLink.allowDownload
|
return sharedLink.allowDownload
|
||||||
? await this.repository.asset.checkSharedLinkAccess(sharedLinkId, ids)
|
? await this.repository.asset.checkSharedLinkAccess(sharedLinkId, ids)
|
||||||
: new Set();
|
: new Set();
|
||||||
}
|
}
|
||||||
|
|
||||||
case Permission.ASSET_UPLOAD: {
|
case AccessPermission.ASSET_UPLOAD: {
|
||||||
return sharedLink.allowUpload ? ids : new Set();
|
return sharedLink.allowUpload ? ids : new Set();
|
||||||
}
|
}
|
||||||
|
|
||||||
case Permission.ASSET_SHARE: {
|
case AccessPermission.ASSET_SHARE: {
|
||||||
// TODO: fix this to not use sharedLink.userId for access control
|
// TODO: fix this to not use sharedLink.userId for access control
|
||||||
return await this.repository.asset.checkOwnerAccess(sharedLink.userId, ids);
|
return await this.repository.asset.checkOwnerAccess(sharedLink.userId, ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Permission.ALBUM_READ: {
|
case AccessPermission.ALBUM_READ: {
|
||||||
return await this.repository.album.checkSharedLinkAccess(sharedLinkId, ids);
|
return await this.repository.album.checkSharedLinkAccess(sharedLinkId, ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Permission.ALBUM_DOWNLOAD: {
|
case AccessPermission.ALBUM_DOWNLOAD: {
|
||||||
return sharedLink.allowDownload
|
return sharedLink.allowDownload
|
||||||
? await this.repository.album.checkSharedLinkAccess(sharedLinkId, ids)
|
? await this.repository.album.checkSharedLinkAccess(sharedLinkId, ids)
|
||||||
: new Set();
|
: new Set();
|
||||||
@@ -148,15 +148,15 @@ export class AccessCore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async checkAccessOther(auth: AuthDto, permission: Permission, ids: Set<string>): Promise<Set<string>> {
|
private async checkAccessOther(auth: AuthDto, permission: AccessPermission, ids: Set<string>): Promise<Set<string>> {
|
||||||
switch (permission) {
|
switch (permission) {
|
||||||
// uses album id
|
// uses album id
|
||||||
case Permission.ACTIVITY_CREATE: {
|
case AccessPermission.ACTIVITY_CREATE: {
|
||||||
return await this.repository.activity.checkCreateAccess(auth.user.id, ids);
|
return await this.repository.activity.checkCreateAccess(auth.user.id, ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
// uses activity id
|
// uses activity id
|
||||||
case Permission.ACTIVITY_DELETE: {
|
case AccessPermission.ACTIVITY_DELETE: {
|
||||||
const isOwner = await this.repository.activity.checkOwnerAccess(auth.user.id, ids);
|
const isOwner = await this.repository.activity.checkOwnerAccess(auth.user.id, ids);
|
||||||
const isAlbumOwner = await this.repository.activity.checkAlbumOwnerAccess(
|
const isAlbumOwner = await this.repository.activity.checkAlbumOwnerAccess(
|
||||||
auth.user.id,
|
auth.user.id,
|
||||||
@@ -165,7 +165,7 @@ export class AccessCore {
|
|||||||
return setUnion(isOwner, isAlbumOwner);
|
return setUnion(isOwner, isAlbumOwner);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Permission.ASSET_READ: {
|
case AccessPermission.ASSET_READ: {
|
||||||
const isOwner = await this.repository.asset.checkOwnerAccess(auth.user.id, ids);
|
const isOwner = await this.repository.asset.checkOwnerAccess(auth.user.id, ids);
|
||||||
const isAlbum = await this.repository.asset.checkAlbumAccess(auth.user.id, setDifference(ids, isOwner));
|
const isAlbum = await this.repository.asset.checkAlbumAccess(auth.user.id, setDifference(ids, isOwner));
|
||||||
const isPartner = await this.repository.asset.checkPartnerAccess(
|
const isPartner = await this.repository.asset.checkPartnerAccess(
|
||||||
@@ -175,13 +175,13 @@ export class AccessCore {
|
|||||||
return setUnion(isOwner, isAlbum, isPartner);
|
return setUnion(isOwner, isAlbum, isPartner);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Permission.ASSET_SHARE: {
|
case AccessPermission.ASSET_SHARE: {
|
||||||
const isOwner = await this.repository.asset.checkOwnerAccess(auth.user.id, ids);
|
const isOwner = await this.repository.asset.checkOwnerAccess(auth.user.id, ids);
|
||||||
const isPartner = await this.repository.asset.checkPartnerAccess(auth.user.id, setDifference(ids, isOwner));
|
const isPartner = await this.repository.asset.checkPartnerAccess(auth.user.id, setDifference(ids, isOwner));
|
||||||
return setUnion(isOwner, isPartner);
|
return setUnion(isOwner, isPartner);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Permission.ASSET_VIEW: {
|
case AccessPermission.ASSET_VIEW: {
|
||||||
const isOwner = await this.repository.asset.checkOwnerAccess(auth.user.id, ids);
|
const isOwner = await this.repository.asset.checkOwnerAccess(auth.user.id, ids);
|
||||||
const isAlbum = await this.repository.asset.checkAlbumAccess(auth.user.id, setDifference(ids, isOwner));
|
const isAlbum = await this.repository.asset.checkAlbumAccess(auth.user.id, setDifference(ids, isOwner));
|
||||||
const isPartner = await this.repository.asset.checkPartnerAccess(
|
const isPartner = await this.repository.asset.checkPartnerAccess(
|
||||||
@@ -191,7 +191,7 @@ export class AccessCore {
|
|||||||
return setUnion(isOwner, isAlbum, isPartner);
|
return setUnion(isOwner, isAlbum, isPartner);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Permission.ASSET_DOWNLOAD: {
|
case AccessPermission.ASSET_DOWNLOAD: {
|
||||||
const isOwner = await this.repository.asset.checkOwnerAccess(auth.user.id, ids);
|
const isOwner = await this.repository.asset.checkOwnerAccess(auth.user.id, ids);
|
||||||
const isAlbum = await this.repository.asset.checkAlbumAccess(auth.user.id, setDifference(ids, isOwner));
|
const isAlbum = await this.repository.asset.checkAlbumAccess(auth.user.id, setDifference(ids, isOwner));
|
||||||
const isPartner = await this.repository.asset.checkPartnerAccess(
|
const isPartner = await this.repository.asset.checkPartnerAccess(
|
||||||
@@ -201,101 +201,101 @@ export class AccessCore {
|
|||||||
return setUnion(isOwner, isAlbum, isPartner);
|
return setUnion(isOwner, isAlbum, isPartner);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Permission.ASSET_UPDATE: {
|
case AccessPermission.ASSET_UPDATE: {
|
||||||
return await this.repository.asset.checkOwnerAccess(auth.user.id, ids);
|
return await this.repository.asset.checkOwnerAccess(auth.user.id, ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Permission.ASSET_DELETE: {
|
case AccessPermission.ASSET_DELETE: {
|
||||||
return await this.repository.asset.checkOwnerAccess(auth.user.id, ids);
|
return await this.repository.asset.checkOwnerAccess(auth.user.id, ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Permission.ASSET_RESTORE: {
|
case AccessPermission.ASSET_RESTORE: {
|
||||||
return await this.repository.asset.checkOwnerAccess(auth.user.id, ids);
|
return await this.repository.asset.checkOwnerAccess(auth.user.id, ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Permission.ALBUM_READ: {
|
case AccessPermission.ALBUM_READ: {
|
||||||
const isOwner = await this.repository.album.checkOwnerAccess(auth.user.id, ids);
|
const isOwner = await this.repository.album.checkOwnerAccess(auth.user.id, ids);
|
||||||
const isShared = await this.repository.album.checkSharedAlbumAccess(auth.user.id, setDifference(ids, isOwner));
|
const isShared = await this.repository.album.checkSharedAlbumAccess(auth.user.id, setDifference(ids, isOwner));
|
||||||
return setUnion(isOwner, isShared);
|
return setUnion(isOwner, isShared);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Permission.ALBUM_UPDATE: {
|
case AccessPermission.ALBUM_UPDATE: {
|
||||||
return await this.repository.album.checkOwnerAccess(auth.user.id, ids);
|
return await this.repository.album.checkOwnerAccess(auth.user.id, ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Permission.ALBUM_DELETE: {
|
case AccessPermission.ALBUM_DELETE: {
|
||||||
return await this.repository.album.checkOwnerAccess(auth.user.id, ids);
|
return await this.repository.album.checkOwnerAccess(auth.user.id, ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Permission.ALBUM_SHARE: {
|
case AccessPermission.ALBUM_SHARE: {
|
||||||
return await this.repository.album.checkOwnerAccess(auth.user.id, ids);
|
return await this.repository.album.checkOwnerAccess(auth.user.id, ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Permission.ALBUM_DOWNLOAD: {
|
case AccessPermission.ALBUM_DOWNLOAD: {
|
||||||
const isOwner = await this.repository.album.checkOwnerAccess(auth.user.id, ids);
|
const isOwner = await this.repository.album.checkOwnerAccess(auth.user.id, ids);
|
||||||
const isShared = await this.repository.album.checkSharedAlbumAccess(auth.user.id, setDifference(ids, isOwner));
|
const isShared = await this.repository.album.checkSharedAlbumAccess(auth.user.id, setDifference(ids, isOwner));
|
||||||
return setUnion(isOwner, isShared);
|
return setUnion(isOwner, isShared);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Permission.ALBUM_REMOVE_ASSET: {
|
case AccessPermission.ALBUM_REMOVE_ASSET: {
|
||||||
return await this.repository.album.checkOwnerAccess(auth.user.id, ids);
|
return await this.repository.album.checkOwnerAccess(auth.user.id, ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Permission.ASSET_UPLOAD: {
|
case AccessPermission.ASSET_UPLOAD: {
|
||||||
return await this.repository.library.checkOwnerAccess(auth.user.id, ids);
|
return await this.repository.library.checkOwnerAccess(auth.user.id, ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Permission.ARCHIVE_READ: {
|
case AccessPermission.ARCHIVE_READ: {
|
||||||
return ids.has(auth.user.id) ? new Set([auth.user.id]) : new Set();
|
return ids.has(auth.user.id) ? new Set([auth.user.id]) : new Set();
|
||||||
}
|
}
|
||||||
|
|
||||||
case Permission.AUTH_DEVICE_DELETE: {
|
case AccessPermission.AUTH_DEVICE_DELETE: {
|
||||||
return await this.repository.authDevice.checkOwnerAccess(auth.user.id, ids);
|
return await this.repository.authDevice.checkOwnerAccess(auth.user.id, ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Permission.TIMELINE_READ: {
|
case AccessPermission.TIMELINE_READ: {
|
||||||
const isOwner = ids.has(auth.user.id) ? new Set([auth.user.id]) : new Set<string>();
|
const isOwner = ids.has(auth.user.id) ? new Set([auth.user.id]) : new Set<string>();
|
||||||
const isPartner = await this.repository.timeline.checkPartnerAccess(auth.user.id, setDifference(ids, isOwner));
|
const isPartner = await this.repository.timeline.checkPartnerAccess(auth.user.id, setDifference(ids, isOwner));
|
||||||
return setUnion(isOwner, isPartner);
|
return setUnion(isOwner, isPartner);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Permission.TIMELINE_DOWNLOAD: {
|
case AccessPermission.TIMELINE_DOWNLOAD: {
|
||||||
return ids.has(auth.user.id) ? new Set([auth.user.id]) : new Set();
|
return ids.has(auth.user.id) ? new Set([auth.user.id]) : new Set();
|
||||||
}
|
}
|
||||||
|
|
||||||
case Permission.MEMORY_READ: {
|
case AccessPermission.MEMORY_READ: {
|
||||||
return this.repository.memory.checkOwnerAccess(auth.user.id, ids);
|
return this.repository.memory.checkOwnerAccess(auth.user.id, ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Permission.MEMORY_WRITE: {
|
case AccessPermission.MEMORY_WRITE: {
|
||||||
return this.repository.memory.checkOwnerAccess(auth.user.id, ids);
|
return this.repository.memory.checkOwnerAccess(auth.user.id, ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Permission.MEMORY_DELETE: {
|
case AccessPermission.MEMORY_DELETE: {
|
||||||
return this.repository.memory.checkOwnerAccess(auth.user.id, ids);
|
return this.repository.memory.checkOwnerAccess(auth.user.id, ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Permission.PERSON_READ: {
|
case AccessPermission.PERSON_READ: {
|
||||||
return await this.repository.person.checkOwnerAccess(auth.user.id, ids);
|
return await this.repository.person.checkOwnerAccess(auth.user.id, ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Permission.PERSON_WRITE: {
|
case AccessPermission.PERSON_WRITE: {
|
||||||
return await this.repository.person.checkOwnerAccess(auth.user.id, ids);
|
return await this.repository.person.checkOwnerAccess(auth.user.id, ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Permission.PERSON_MERGE: {
|
case AccessPermission.PERSON_MERGE: {
|
||||||
return await this.repository.person.checkOwnerAccess(auth.user.id, ids);
|
return await this.repository.person.checkOwnerAccess(auth.user.id, ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Permission.PERSON_CREATE: {
|
case AccessPermission.PERSON_CREATE: {
|
||||||
return this.repository.person.checkFaceOwnerAccess(auth.user.id, ids);
|
return this.repository.person.checkFaceOwnerAccess(auth.user.id, ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Permission.PERSON_REASSIGN: {
|
case AccessPermission.PERSON_REASSIGN: {
|
||||||
return this.repository.person.checkFaceOwnerAccess(auth.user.id, ids);
|
return this.repository.person.checkFaceOwnerAccess(auth.user.id, ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Permission.PARTNER_UPDATE: {
|
case AccessPermission.PARTNER_UPDATE: {
|
||||||
return await this.repository.partner.checkUpdateAccess(auth.user.id, ids);
|
return await this.repository.partner.checkUpdateAccess(auth.user.id, ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,10 @@ export class UserCore {
|
|||||||
throw new BadRequestException('The server already has an admin');
|
throw new BadRequestException('The server already has an admin');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dto.permissions) {
|
||||||
|
// TODO validate granted permissions
|
||||||
|
}
|
||||||
|
|
||||||
if (dto.email) {
|
if (dto.email) {
|
||||||
const duplicate = await this.userRepository.getByEmail(dto.email);
|
const duplicate = await this.userRepository.getByEmail(dto.email);
|
||||||
if (duplicate && duplicate.id !== id) {
|
if (duplicate && duplicate.id !== id) {
|
||||||
@@ -93,6 +97,11 @@ export class UserCore {
|
|||||||
if (payload.storageLabel) {
|
if (payload.storageLabel) {
|
||||||
payload.storageLabel = sanitize(payload.storageLabel.replaceAll('.', ''));
|
payload.storageLabel = sanitize(payload.storageLabel.replaceAll('.', ''));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (payload.permissions) {
|
||||||
|
// TODO validate permissions
|
||||||
|
}
|
||||||
|
|
||||||
const userEntity = await this.userRepository.create(payload);
|
const userEntity = await this.userRepository.create(payload);
|
||||||
await this.libraryRepository.create({
|
await this.libraryRepository.create({
|
||||||
owner: { id: userEntity.id } as UserEntity,
|
owner: { id: userEntity.id } as UserEntity,
|
||||||
|
|||||||
@@ -25,6 +25,195 @@ export type CookieResponse = {
|
|||||||
values: Array<{ key: ImmichCookie; value: string }>;
|
values: Array<{ key: ImmichCookie; value: string }>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export enum PermissionPreset {
|
||||||
|
USER = 'user',
|
||||||
|
ADMIN = 'admin',
|
||||||
|
CUSTOM = 'custom',
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum Permission {
|
||||||
|
ACTIVITY_CREATE = 'activity.create',
|
||||||
|
ACTIVITY_READ = 'activity.read',
|
||||||
|
ACTIVITY_UPDATE = 'activity.update',
|
||||||
|
ACTIVITY_DELETE = 'activity.delete',
|
||||||
|
|
||||||
|
ALBUM_CREATE = 'album.create',
|
||||||
|
ALBUM_READ = 'album.read',
|
||||||
|
ALBUM_UPDATE = 'album.update',
|
||||||
|
ALBUM_DELETE = 'album.delete',
|
||||||
|
|
||||||
|
ASSET_CREATE = 'asset.create',
|
||||||
|
ASSET_READ = 'asset.read',
|
||||||
|
ASSET_UPDATE = 'asset.update',
|
||||||
|
ASSET_DELETE = 'asset.delete',
|
||||||
|
|
||||||
|
API_KEY_CREATE = 'apiKey.create',
|
||||||
|
API_KEY_READ = 'apiKey.read',
|
||||||
|
API_KEY_UPDATE = 'apiKey.update',
|
||||||
|
API_KEY_DELETE = 'apiKey.delete',
|
||||||
|
|
||||||
|
AUTH_DEVICE_CREATE = 'authDevice.create',
|
||||||
|
AUTH_DEVICE_READ = 'authDevice.read',
|
||||||
|
AUTH_DEVICE_UPDATE = 'authDevice.update',
|
||||||
|
AUTH_DEVICE_DELETE = 'authDevice.delete',
|
||||||
|
|
||||||
|
FACE_CREATE = 'face.create',
|
||||||
|
FACE_READ = 'face.read',
|
||||||
|
FACE_UPDATE = 'face.update',
|
||||||
|
FACE_DELETE = 'face.delete',
|
||||||
|
|
||||||
|
LIBRARY_CREATE = 'library.create',
|
||||||
|
LIBRARY_READ = 'library.read',
|
||||||
|
LIBRARY_UPDATE = 'library.update',
|
||||||
|
LIBRARY_DELETE = 'library.delete',
|
||||||
|
|
||||||
|
MEMORY_CREATE = 'memory.create',
|
||||||
|
MEMORY_READ = 'memory.read',
|
||||||
|
MEMORY_UPDATE = 'memory.update',
|
||||||
|
MEMORY_DELETE = 'memory.delete',
|
||||||
|
MEMORY_ADD_ASSET = 'memory.addAsset',
|
||||||
|
MEMORY_REMOVE_ASSET = 'memory.removeAsset',
|
||||||
|
|
||||||
|
PARTNER_CREATE = 'partner.create',
|
||||||
|
PARTNER_READ = 'partner.read',
|
||||||
|
PARTNER_UPDATE = 'partner.update',
|
||||||
|
PARTNER_DELETE = 'partner.delete',
|
||||||
|
|
||||||
|
PERSON_CREATE = 'person.create',
|
||||||
|
PERSON_READ = 'person.read',
|
||||||
|
PERSON_UPDATE = 'person.update',
|
||||||
|
PERSON_DELETE = 'person.delete',
|
||||||
|
|
||||||
|
REPORT_CREATE = 'report.create',
|
||||||
|
REPORT_READ = 'report.read',
|
||||||
|
REPORT_UPDATE = 'report.update',
|
||||||
|
REPORT_DELETE = 'report.delete',
|
||||||
|
|
||||||
|
SESSION_CREATE = 'session.create',
|
||||||
|
SESSION_READ = 'session.read',
|
||||||
|
SESSION_UPDATE = 'session.update',
|
||||||
|
SESSION_DELETE = 'session.delete',
|
||||||
|
|
||||||
|
SHARED_LINK_CREATE = 'sharedLink.create',
|
||||||
|
SHARED_LINK_READ = 'sharedLink.read',
|
||||||
|
SHARED_LINK_UPDATE = 'sharedLink.update',
|
||||||
|
SHARED_LINK_DELETE = 'sharedLink.delete',
|
||||||
|
|
||||||
|
SYSTEM_CONFIG_CREATE = 'systemConfig.create',
|
||||||
|
SYSTEM_CONFIG_READ = 'systemConfig.read',
|
||||||
|
SYSTEM_CONFIG_UPDATE = 'systemConfig.update',
|
||||||
|
SYSTEM_CONFIG_DELETE = 'systemConfig.delete',
|
||||||
|
|
||||||
|
SYSTEM_METADATA_CREATE = 'systemMetadata.create',
|
||||||
|
SYSTEM_METADATA_READ = 'systemMetadata.read',
|
||||||
|
SYSTEM_METADATA_UPDATE = 'systemMetadata.update',
|
||||||
|
SYSTEM_METADATA_DELETE = 'systemMetadata.delete',
|
||||||
|
|
||||||
|
STACK_CREATE = 'stack.create',
|
||||||
|
STACK_READ = 'stack.read',
|
||||||
|
STACK_UPDATE = 'stack.update',
|
||||||
|
STACK_DELETE = 'stack.delete',
|
||||||
|
|
||||||
|
TAG_CREATE = 'tag.create',
|
||||||
|
TAG_READ = 'tag.read',
|
||||||
|
TAG_UPDATE = 'tag.update',
|
||||||
|
TAG_DELETE = 'tag.delete',
|
||||||
|
|
||||||
|
USER_CREATE = 'user.create',
|
||||||
|
USER_READ = 'user.read',
|
||||||
|
USER_UPDATE = 'user.update',
|
||||||
|
USER_DELETE = 'user.delete',
|
||||||
|
|
||||||
|
// other
|
||||||
|
AUTH_CHANGE_PASSWORD = 'auth.changePassword',
|
||||||
|
AUTH_OAUTH = 'auth.oauth',
|
||||||
|
|
||||||
|
ALBUM_ADD_ASSET = 'album.addAsset',
|
||||||
|
ALBUM_REMOVE_ASSET = 'album.removeAsset',
|
||||||
|
ALBUM_ADD_USER = 'album.addUser',
|
||||||
|
ALBUM_REMOVE_USER = 'album.removeUser',
|
||||||
|
|
||||||
|
ASSET_VIEW_THUMB = 'asset.viewThumb',
|
||||||
|
ASSET_VIEW_PREVIEW = 'asset.viewPreview',
|
||||||
|
ASSET_VIEW_ORIGINAL = 'asset.viewOriginal',
|
||||||
|
ASSET_UPLOAD = 'asset.upload',
|
||||||
|
ASSET_DOWNLOAD = 'asset.download',
|
||||||
|
|
||||||
|
JOB_READ = 'job.read',
|
||||||
|
JOB_RUN = 'job.run',
|
||||||
|
|
||||||
|
MAP_READ = 'map.read',
|
||||||
|
|
||||||
|
USER_READ_SIMPLE = 'user.readSimple',
|
||||||
|
USER_CHANGE_PASSWORD = 'user.changePassword',
|
||||||
|
|
||||||
|
SERVER_READ = 'server.read',
|
||||||
|
SERVER_SETUP = 'server.setup',
|
||||||
|
}
|
||||||
|
|
||||||
|
export const presetToPermissions = ({
|
||||||
|
permissionPreset: preset,
|
||||||
|
permissions,
|
||||||
|
}: {
|
||||||
|
permissionPreset?: PermissionPreset;
|
||||||
|
permissions?: Permission[];
|
||||||
|
}) => {
|
||||||
|
switch (preset) {
|
||||||
|
case PermissionPreset.ADMIN: {
|
||||||
|
return ALL_PERMISSIONS;
|
||||||
|
}
|
||||||
|
|
||||||
|
case PermissionPreset.USER: {
|
||||||
|
return USER_PERMISSIONS;
|
||||||
|
}
|
||||||
|
|
||||||
|
case PermissionPreset.CUSTOM: {
|
||||||
|
return permissions ?? [];
|
||||||
|
}
|
||||||
|
|
||||||
|
default: {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ALL_PERMISSIONS = Object.values(Permission);
|
||||||
|
export const USER_PERMISSIONS = ALL_PERMISSIONS.filter((permission) => {
|
||||||
|
switch (permission) {
|
||||||
|
case Permission.JOB_READ:
|
||||||
|
case Permission.JOB_RUN:
|
||||||
|
|
||||||
|
case Permission.LIBRARY_READ:
|
||||||
|
case Permission.LIBRARY_CREATE:
|
||||||
|
case Permission.LIBRARY_UPDATE:
|
||||||
|
case Permission.LIBRARY_DELETE:
|
||||||
|
|
||||||
|
// TODO this can't be an admin permission yet because non-admins still use it
|
||||||
|
case Permission.USER_READ:
|
||||||
|
case Permission.USER_CREATE:
|
||||||
|
case Permission.USER_UPDATE:
|
||||||
|
case Permission.USER_DELETE:
|
||||||
|
|
||||||
|
case Permission.SYSTEM_CONFIG_CREATE:
|
||||||
|
case Permission.SYSTEM_CONFIG_READ:
|
||||||
|
case Permission.SYSTEM_CONFIG_UPDATE:
|
||||||
|
case Permission.SYSTEM_CONFIG_DELETE:
|
||||||
|
|
||||||
|
case Permission.SYSTEM_METADATA_CREATE:
|
||||||
|
case Permission.SYSTEM_METADATA_READ:
|
||||||
|
case Permission.SYSTEM_METADATA_UPDATE:
|
||||||
|
case Permission.SYSTEM_METADATA_DELETE: {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export type AuthorizationPermissions = Set<Permission>;
|
||||||
|
|
||||||
export class AuthDto {
|
export class AuthDto {
|
||||||
user!: UserEntity;
|
user!: UserEntity;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { IsBoolean } from 'class-validator';
|
||||||
|
|
||||||
|
export class AdminOnboardingUpdateDto {
|
||||||
|
@IsBoolean()
|
||||||
|
isOnboarded!: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class AdminOnboardingResponseDto {
|
||||||
|
isOnboarded!: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ReverseGeocodingStateResponseDto {
|
||||||
|
lastUpdate!: string | null;
|
||||||
|
lastImportFileName!: string | null;
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import { plainToInstance } from 'class-transformer';
|
import { plainToInstance } from 'class-transformer';
|
||||||
import { validate } from 'class-validator';
|
import { validate } from 'class-validator';
|
||||||
|
import { PermissionPreset } from 'src/dtos/auth.dto';
|
||||||
import { CreateAdminDto, CreateUserDto, CreateUserOAuthDto, UpdateUserDto } from 'src/dtos/user.dto';
|
import { CreateAdminDto, CreateUserDto, CreateUserOAuthDto, UpdateUserDto } from 'src/dtos/user.dto';
|
||||||
|
|
||||||
describe('update user DTO', () => {
|
describe('update user DTO', () => {
|
||||||
@@ -22,6 +23,7 @@ describe('create user DTO', () => {
|
|||||||
email: undefined,
|
email: undefined,
|
||||||
password: 'password',
|
password: 'password',
|
||||||
name: 'name',
|
name: 'name',
|
||||||
|
permissionPreset: PermissionPreset.USER,
|
||||||
};
|
};
|
||||||
let dto: CreateUserDto = plainToInstance(CreateUserDto, params);
|
let dto: CreateUserDto = plainToInstance(CreateUserDto, params);
|
||||||
let errors = await validate(dto);
|
let errors = await validate(dto);
|
||||||
@@ -45,6 +47,7 @@ describe('create user DTO', () => {
|
|||||||
email: someEmail,
|
email: someEmail,
|
||||||
password: 'some password',
|
password: 'some password',
|
||||||
name: 'some name',
|
name: 'some name',
|
||||||
|
permissionPreset: 'user',
|
||||||
});
|
});
|
||||||
const errors = await validate(dto);
|
const errors = await validate(dto);
|
||||||
expect(errors).toHaveLength(0);
|
expect(errors).toHaveLength(0);
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
|
||||||
import { Transform } from 'class-transformer';
|
import { Transform } from 'class-transformer';
|
||||||
import { IsEmail, IsEnum, IsNotEmpty, IsNumber, IsPositive, IsString, IsUUID } from 'class-validator';
|
import { IsEmail, IsEnum, IsNotEmpty, IsNumber, IsPositive, IsString, IsUUID, ValidateIf } from 'class-validator';
|
||||||
|
import { Permission, PermissionPreset } from 'src/dtos/auth.dto';
|
||||||
import { getRandomAvatarColor } from 'src/dtos/user-profile.dto';
|
import { getRandomAvatarColor } from 'src/dtos/user-profile.dto';
|
||||||
import { UserAvatarColor, UserEntity, UserStatus } from 'src/entities/user.entity';
|
import { UserAvatarColor, UserEntity, UserStatus } from 'src/entities/user.entity';
|
||||||
import { Optional, ValidateBoolean, toEmail, toSanitized } from 'src/validation';
|
import { Optional, ValidateBoolean, toEmail, toSanitized } from 'src/validation';
|
||||||
|
|
||||||
|
const isCustomPreset = ({ permissionPreset }: CreateUserDto) =>
|
||||||
|
permissionPreset && permissionPreset === PermissionPreset.CUSTOM;
|
||||||
|
|
||||||
export class CreateUserDto {
|
export class CreateUserDto {
|
||||||
@IsEmail({ require_tld: false })
|
@IsEmail({ require_tld: false })
|
||||||
@Transform(toEmail)
|
@Transform(toEmail)
|
||||||
@@ -34,6 +38,15 @@ export class CreateUserDto {
|
|||||||
|
|
||||||
@ValidateBoolean({ optional: true })
|
@ValidateBoolean({ optional: true })
|
||||||
shouldChangePassword?: boolean;
|
shouldChangePassword?: boolean;
|
||||||
|
|
||||||
|
@IsEnum(PermissionPreset)
|
||||||
|
@ApiProperty({ enum: PermissionPreset, enumName: 'PermissionPreset' })
|
||||||
|
permissionPreset!: PermissionPreset;
|
||||||
|
|
||||||
|
@ValidateIf(isCustomPreset)
|
||||||
|
@IsEnum(Permission, { each: true })
|
||||||
|
@ApiPropertyOptional({ enum: Permission, enumName: 'AuthorizationPermission' })
|
||||||
|
permissions?: Permission[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export class CreateAdminDto {
|
export class CreateAdminDto {
|
||||||
@@ -112,6 +125,16 @@ export class UpdateUserDto {
|
|||||||
@IsPositive()
|
@IsPositive()
|
||||||
@ApiProperty({ type: 'integer', format: 'int64' })
|
@ApiProperty({ type: 'integer', format: 'int64' })
|
||||||
quotaSizeInBytes?: number | null;
|
quotaSizeInBytes?: number | null;
|
||||||
|
|
||||||
|
@Optional()
|
||||||
|
@IsEnum(PermissionPreset)
|
||||||
|
@ApiProperty({ enum: PermissionPreset, enumName: 'PermissionPreset' })
|
||||||
|
permissionPreset?: PermissionPreset;
|
||||||
|
|
||||||
|
@ValidateIf(isCustomPreset)
|
||||||
|
@IsEnum(Permission, { each: true })
|
||||||
|
@ApiPropertyOptional({ enum: Permission, enumName: 'AuthorizationPermission' })
|
||||||
|
permissions?: Permission[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export class UserDto {
|
export class UserDto {
|
||||||
@@ -139,6 +162,7 @@ export class UserResponseDto extends UserDto {
|
|||||||
quotaUsageInBytes!: number | null;
|
quotaUsageInBytes!: number | null;
|
||||||
@ApiProperty({ enumName: 'UserStatus', enum: UserStatus })
|
@ApiProperty({ enumName: 'UserStatus', enum: UserStatus })
|
||||||
status!: string;
|
status!: string;
|
||||||
|
permissions?: Permission[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const mapSimpleUser = (entity: UserEntity): UserDto => {
|
export const mapSimpleUser = (entity: UserEntity): UserDto => {
|
||||||
@@ -165,5 +189,6 @@ export function mapUser(entity: UserEntity): UserResponseDto {
|
|||||||
quotaSizeInBytes: entity.quotaSizeInBytes,
|
quotaSizeInBytes: entity.quotaSizeInBytes,
|
||||||
quotaUsageInBytes: entity.quotaUsageInBytes,
|
quotaUsageInBytes: entity.quotaUsageInBytes,
|
||||||
status: entity.status,
|
status: entity.status,
|
||||||
|
permissions: entity.permissions,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { Permission } from 'src/dtos/auth.dto';
|
||||||
import { AssetEntity } from 'src/entities/asset.entity';
|
import { AssetEntity } from 'src/entities/asset.entity';
|
||||||
import { TagEntity } from 'src/entities/tag.entity';
|
import { TagEntity } from 'src/entities/tag.entity';
|
||||||
import {
|
import {
|
||||||
@@ -87,4 +88,7 @@ export class UserEntity {
|
|||||||
|
|
||||||
@Column({ type: 'bigint', default: 0 })
|
@Column({ type: 'bigint', default: 0 })
|
||||||
quotaUsageInBytes!: number;
|
quotaUsageInBytes!: number;
|
||||||
|
|
||||||
|
@Column({ type: 'varchar', array: true })
|
||||||
|
permissions!: Permission[];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,12 @@ import { SessionEntity } from 'src/entities/session.entity';
|
|||||||
|
|
||||||
export const ISessionRepository = 'ISessionRepository';
|
export const ISessionRepository = 'ISessionRepository';
|
||||||
|
|
||||||
|
type E = SessionEntity;
|
||||||
|
|
||||||
export interface ISessionRepository {
|
export interface ISessionRepository {
|
||||||
create(dto: Partial<SessionEntity>): Promise<SessionEntity>;
|
create<T extends Partial<E>>(dto: T): Promise<T>;
|
||||||
update(dto: Partial<SessionEntity>): Promise<SessionEntity>;
|
update<T extends Partial<E>>(dto: T): Promise<T>;
|
||||||
delete(id: string): Promise<void>;
|
delete(id: string): Promise<void>;
|
||||||
getByToken(token: string): Promise<SessionEntity | null>;
|
getByToken(token: string): Promise<E | null>;
|
||||||
getByUserId(userId: string): Promise<SessionEntity[]>;
|
getByUserId(userId: string): Promise<E[]>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,49 +10,40 @@ import {
|
|||||||
import { Reflector } from '@nestjs/core';
|
import { Reflector } from '@nestjs/core';
|
||||||
import { ApiBearerAuth, ApiCookieAuth, ApiOkResponse, ApiQuery, ApiSecurity } from '@nestjs/swagger';
|
import { ApiBearerAuth, ApiCookieAuth, ApiOkResponse, ApiQuery, ApiSecurity } from '@nestjs/swagger';
|
||||||
import { Request } from 'express';
|
import { Request } from 'express';
|
||||||
import { AuthDto } from 'src/dtos/auth.dto';
|
import { AuthDto, Permission } from 'src/dtos/auth.dto';
|
||||||
import { ILoggerRepository } from 'src/interfaces/logger.interface';
|
import { ILoggerRepository } from 'src/interfaces/logger.interface';
|
||||||
import { AuthService, LoginDetails } from 'src/services/auth.service';
|
import { AuthService, LoginDetails } from 'src/services/auth.service';
|
||||||
import { UAParser } from 'ua-parser-js';
|
import { UAParser } from 'ua-parser-js';
|
||||||
|
|
||||||
export enum Metadata {
|
export enum Metadata {
|
||||||
AUTH_ROUTE = 'auth_route',
|
|
||||||
ADMIN_ROUTE = 'admin_route',
|
|
||||||
SHARED_ROUTE = 'shared_route',
|
SHARED_ROUTE = 'shared_route',
|
||||||
PUBLIC_SECURITY = 'public_security',
|
PUBLIC_SECURITY = 'public_security',
|
||||||
API_KEY_SECURITY = 'api_key',
|
API_KEY_SECURITY = 'api_key',
|
||||||
|
PERMISSION = 'auth_permission',
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AuthenticatedOptions {
|
type AuthenticatedOptions = {
|
||||||
admin?: true;
|
sharedLink?: true;
|
||||||
isShared?: true;
|
/** skip permission check when param id matches calling user */
|
||||||
}
|
bypassParamId?: string;
|
||||||
|
};
|
||||||
|
|
||||||
export const Authenticated = (options: AuthenticatedOptions = {}) => {
|
export const Authenticated = (permission: Permission, options?: AuthenticatedOptions) => {
|
||||||
const decorators: MethodDecorator[] = [
|
const { sharedLink } = { sharedLink: false, ...options };
|
||||||
|
|
||||||
|
const decorators = sharedLink
|
||||||
|
? [SetMetadata(Metadata.SHARED_ROUTE, true), ApiQuery({ name: 'key', type: String, required: false })]
|
||||||
|
: [];
|
||||||
|
|
||||||
|
return applyDecorators(
|
||||||
ApiBearerAuth(),
|
ApiBearerAuth(),
|
||||||
ApiCookieAuth(),
|
ApiCookieAuth(),
|
||||||
ApiSecurity(Metadata.API_KEY_SECURITY),
|
ApiSecurity(Metadata.API_KEY_SECURITY),
|
||||||
SetMetadata(Metadata.AUTH_ROUTE, true),
|
SetMetadata(Metadata.PERMISSION, permission),
|
||||||
];
|
...decorators,
|
||||||
|
);
|
||||||
if (options.admin) {
|
|
||||||
decorators.push(AdminRoute());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.isShared) {
|
|
||||||
decorators.push(SharedLinkRoute());
|
|
||||||
}
|
|
||||||
|
|
||||||
return applyDecorators(...decorators);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const PublicRoute = () =>
|
|
||||||
applyDecorators(SetMetadata(Metadata.AUTH_ROUTE, false), ApiSecurity(Metadata.PUBLIC_SECURITY));
|
|
||||||
export const SharedLinkRoute = () =>
|
|
||||||
applyDecorators(SetMetadata(Metadata.SHARED_ROUTE, true), ApiQuery({ name: 'key', type: String, required: false }));
|
|
||||||
export const AdminRoute = (value = true) => SetMetadata(Metadata.ADMIN_ROUTE, value);
|
|
||||||
|
|
||||||
export const Auth = createParamDecorator((data, context: ExecutionContext): AuthDto => {
|
export const Auth = createParamDecorator((data, context: ExecutionContext): AuthDto => {
|
||||||
return context.switchToHttp().getRequest<{ user: AuthDto }>().user;
|
return context.switchToHttp().getRequest<{ user: AuthDto }>().user;
|
||||||
});
|
});
|
||||||
@@ -89,26 +80,29 @@ export class AuthGuard implements CanActivate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async canActivate(context: ExecutionContext): Promise<boolean> {
|
async canActivate(context: ExecutionContext): Promise<boolean> {
|
||||||
const targets = [context.getHandler(), context.getClass()];
|
const method = context.getHandler();
|
||||||
|
|
||||||
const isAuthRoute = this.reflector.getAllAndOverride(Metadata.AUTH_ROUTE, targets);
|
const permission = this.reflector.get<Permission>(Metadata.PERMISSION, method);
|
||||||
const isAdminRoute = this.reflector.getAllAndOverride(Metadata.ADMIN_ROUTE, targets);
|
const isSharedRoute = this.reflector.get<boolean>(Metadata.SHARED_ROUTE, method);
|
||||||
const isSharedRoute = this.reflector.getAllAndOverride(Metadata.SHARED_ROUTE, targets);
|
|
||||||
|
|
||||||
if (!isAuthRoute) {
|
// public
|
||||||
|
if (!permission) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const request = context.switchToHttp().getRequest<AuthRequest>();
|
const request = context.switchToHttp().getRequest<AuthRequest>();
|
||||||
|
|
||||||
const authDto = await this.authService.validate(request.headers, request.query as Record<string, string>);
|
const authDto = await this.authService.validate(request.headers, request.query as Record<string, string>);
|
||||||
|
const isApiKey = !!authDto.apiKey;
|
||||||
|
const isUserToken = !!authDto.session;
|
||||||
|
|
||||||
if (authDto.sharedLink && !isSharedRoute) {
|
if (authDto.sharedLink && !isSharedRoute) {
|
||||||
this.logger.warn(`Denied access to non-shared route: ${request.path}`);
|
this.logger.warn(`Denied access to non-shared route: ${request.path}`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isAdminRoute && !authDto.user.isAdmin) {
|
if ((isApiKey || isUserToken) && !authDto.user.permissions.includes(permission)) {
|
||||||
this.logger.warn(`Denied access to admin only route: ${request.path}`);
|
this.logger.warn(`Denied access to route: no ${permission} permission: ${request.path}. `);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||||
|
|
||||||
|
export class AddUserPermissions1713389653857 implements MigrationInterface {
|
||||||
|
name = 'AddUserPermissions1713389653857'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "users" ADD "permissions" character varying array NOT NULL`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "users" DROP COLUMN "permissions"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user