Compare commits

..

1 Commits

Author SHA1 Message Date
Jason Rasmussen
3fd5a32a7d WIP 2024-04-16 21:08:36 -04:00
184 changed files with 2735 additions and 3680 deletions

View File

@@ -1,4 +1,4 @@
FROM node:20-alpine3.19@sha256:ec0c413b1d84f3f7f67ec986ba885930c57b5318d2eb3abc6960ee05d4f2eb28 as core
FROM node:20-alpine3.19@sha256:7e227295e96f5b00aa79555ae166f50610940d888fc2e321cf36304cbd17d7d6 as core
WORKDIR /usr/src/open-api/typescript-sdk
COPY open-api/typescript-sdk/package*.json open-api/typescript-sdk/tsconfig*.json ./

6
cli/package-lock.json generated
View File

@@ -47,15 +47,15 @@
},
"../open-api/typescript-sdk": {
"name": "@immich/sdk",
"version": "1.102.1",
"version": "1.101.0",
"dev": true,
"license": "GNU Affero General Public License version 3",
"dependencies": {
"@oazapfts/runtime": "^1.0.2"
},
"devDependencies": {
"@types/node": "^20.11.0",
"typescript": "^5.3.3"
"@types/node": "^20.12.7",
"typescript": "^5.4.5"
}
},
"node_modules/@aashutoshrathi/word-wrap": {

View File

@@ -97,7 +97,7 @@ services:
redis:
container_name: immich_redis
image: redis:6.2-alpine@sha256:84882e87b54734154586e5f8abd4dce69fe7311315e2fc6d67c29614c8de2672
image: redis:6.2-alpine@sha256:3fcb624d83a9c478357f16dc173c58ded325ccc5fd2a4375f3916c04cc579f70
database:
container_name: immich_postgres

View File

@@ -54,7 +54,7 @@ services:
redis:
container_name: immich_redis
image: redis:6.2-alpine@sha256:84882e87b54734154586e5f8abd4dce69fe7311315e2fc6d67c29614c8de2672
image: redis:6.2-alpine@sha256:3fcb624d83a9c478357f16dc173c58ded325ccc5fd2a4375f3916c04cc579f70
restart: always
database:

View File

@@ -58,7 +58,7 @@ services:
redis:
container_name: immich_redis
image: registry.hub.docker.com/library/redis:6.2-alpine@sha256:84882e87b54734154586e5f8abd4dce69fe7311315e2fc6d67c29614c8de2672
image: registry.hub.docker.com/library/redis:6.2-alpine@sha256:51d6c56749a4243096327e3fb964a48ed92254357108449cb6e23999c37773c5
restart: always
database:

View File

@@ -52,8 +52,8 @@ Before enabling OAuth in Immich, a new client application needs to be configured
Hostname
- `https://immich.example.com/auth/login`
- `https://immich.example.com/user-settings`
- `https://immich.example.com/auth/login`)
- `https://immich.example.com/user-settings`)
## Enable OAuth

View File

@@ -56,7 +56,8 @@ ALTER DATABASE <immichdatabasename> OWNER TO <immichdbusername>;
CREATE EXTENSION vectors;
CREATE EXTENSION earthdistance CASCADE;
ALTER DATABASE <immichdatabasename> SET search_path TO "$user", public, vectors;
ALTER SCHEMA vectors OWNER TO <immichdbusername>;
GRANT USAGE ON SCHEMA vectors TO <immichdbusername>;
ALTER DEFAULT PRIVILEGES IN SCHEMA vectors GRANT SELECT ON TABLES TO <immichdbusername>;
COMMIT;
```

View File

@@ -120,8 +120,7 @@ The default configuration looks like this:
"previewFormat": "jpeg",
"previewSize": 1440,
"quality": 80,
"colorspace": "p3",
"extractEmbedded": false
"colorspace": "p3"
},
"newVersionCheck": {
"enabled": true

View File

@@ -1,4 +1,4 @@
Immich allows the admin user to set the uploaded filename pattern at the directory and filename level as well as the [storage label for a user](/docs/administration/user-management/#set-storage-label-for-user).
Immich allows the admin user to set the uploaded filename pattern. Both at the directory and filename level.
:::note new version
On new machines running version 1.92.0 storage template engine is off by default, for [more info](https://github.com/immich-app/immich/releases/tag/v1.92.0#:~:text=the%20partner%E2%80%99s%20assets.-,Hardening%20storage%20template,-We%20have%20further).

View File

@@ -36,7 +36,7 @@ services:
<<: *server-common
redis:
image: redis:6.2-alpine@sha256:84882e87b54734154586e5f8abd4dce69fe7311315e2fc6d67c29614c8de2672
image: redis:6.2-alpine@sha256:3fcb624d83a9c478357f16dc173c58ded325ccc5fd2a4375f3916c04cc579f70
database:
image: tensorchord/pgvecto-rs:pg14-v0.2.0@sha256:90724186f0a3517cf6914295b5ab410db9ce23190a2d9d0b9dd6463e3fa298f0

10
e2e/package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "immich-e2e",
"version": "1.102.1",
"version": "1.101.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "immich-e2e",
"version": "1.102.1",
"version": "1.101.0",
"license": "GNU Affero General Public License version 3",
"devDependencies": {
"@immich/cli": "file:../cli",
@@ -81,15 +81,15 @@
},
"../open-api/typescript-sdk": {
"name": "@immich/sdk",
"version": "1.102.1",
"version": "1.101.0",
"dev": true,
"license": "GNU Affero General Public License version 3",
"dependencies": {
"@oazapfts/runtime": "^1.0.2"
},
"devDependencies": {
"@types/node": "^20.11.0",
"typescript": "^5.3.3"
"@types/node": "^20.12.7",
"typescript": "^5.4.5"
}
},
"node_modules/@aashutoshrathi/word-wrap": {

View File

@@ -1,6 +1,6 @@
{
"name": "immich-e2e",
"version": "1.102.1",
"version": "1.101.0",
"description": "",
"main": "index.js",
"type": "module",

View File

@@ -1,7 +1,7 @@
import { LoginResponseDto, login, signUpAdmin } from '@immich/sdk';
import { loginDto, signupDto } from 'src/fixtures';
import { errorDto, loginResponseDto, signupResponseDto } from 'src/responses';
import { app, utils } from 'src/utils';
import { LoginResponseDto, getAuthDevices, login, signUpAdmin } from '@immich/sdk';
import { loginDto, signupDto, uuidDto } from 'src/fixtures';
import { deviceDto, errorDto, loginResponseDto, signupResponseDto } from 'src/responses';
import { app, asBearerAuth, utils } from 'src/utils';
import request from 'supertest';
import { beforeEach, describe, expect, it } from 'vitest';
@@ -112,29 +112,70 @@ describe('/auth/*', () => {
const cookies = headers['set-cookie'];
expect(cookies).toHaveLength(3);
expect(cookies[0].split(';').map((item) => item.trim())).toEqual([
`immich_access_token=${token}`,
'Max-Age=34560000',
'Path=/',
expect.stringContaining('Expires='),
'HttpOnly',
'SameSite=Lax',
]);
expect(cookies[1].split(';').map((item) => item.trim())).toEqual([
'immich_auth_type=password',
'Max-Age=34560000',
'Path=/',
expect.stringContaining('Expires='),
'HttpOnly',
'SameSite=Lax',
]);
expect(cookies[2].split(';').map((item) => item.trim())).toEqual([
'immich_is_authenticated=true',
'Max-Age=34560000',
'Path=/',
expect.stringContaining('Expires='),
'SameSite=Lax',
]);
expect(cookies[0]).toEqual(`immich_access_token=${token}; HttpOnly; Path=/; Max-Age=34560000; SameSite=Lax;`);
expect(cookies[1]).toEqual('immich_auth_type=password; HttpOnly; Path=/; Max-Age=34560000; SameSite=Lax;');
expect(cookies[2]).toEqual('immich_is_authenticated=true; Path=/; Max-Age=34560000; SameSite=Lax;');
});
});
describe('GET /auth/devices', () => {
it('should require authentication', async () => {
const { status, body } = await request(app).get('/auth/devices');
expect(status).toBe(401);
expect(body).toEqual(errorDto.unauthorized);
});
it('should get a list of authorized devices', async () => {
const { status, body } = await request(app)
.get('/auth/devices')
.set('Authorization', `Bearer ${admin.accessToken}`);
expect(status).toBe(200);
expect(body).toEqual([deviceDto.current]);
});
});
describe('DELETE /auth/devices', () => {
it('should require authentication', async () => {
const { status, body } = await request(app).delete(`/auth/devices`);
expect(status).toBe(401);
expect(body).toEqual(errorDto.unauthorized);
});
it('should logout all devices (except the current one)', async () => {
for (let i = 0; i < 5; i++) {
await login({ loginCredentialDto: loginDto.admin });
}
await expect(getAuthDevices({ headers: asBearerAuth(admin.accessToken) })).resolves.toHaveLength(6);
const { status } = await request(app).delete(`/auth/devices`).set('Authorization', `Bearer ${admin.accessToken}`);
expect(status).toBe(204);
await expect(getAuthDevices({ headers: asBearerAuth(admin.accessToken) })).resolves.toHaveLength(1);
});
it('should throw an error for a non-existent device id', async () => {
const { status, body } = await request(app)
.delete(`/auth/devices/${uuidDto.notFound}`)
.set('Authorization', `Bearer ${admin.accessToken}`);
expect(status).toBe(400);
expect(body).toEqual(errorDto.badRequest('Not found or no authDevice.delete access'));
});
it('should logout a device', async () => {
const [device] = await getAuthDevices({
headers: asBearerAuth(admin.accessToken),
});
const { status } = await request(app)
.delete(`/auth/devices/${device.id}`)
.set('Authorization', `Bearer ${admin.accessToken}`);
expect(status).toBe(204);
const response = await request(app)
.post('/auth/validateToken')
.set('Authorization', `Bearer ${admin.accessToken}`);
expect(response.body).toEqual(errorDto.invalidToken);
expect(response.status).toBe(401);
});
});

View File

@@ -1,4 +1,4 @@
import { AssetFileUploadResponseDto, LoginResponseDto, deleteAssets, getMapMarkers, updateAsset } from '@immich/sdk';
import { AssetFileUploadResponseDto, LoginResponseDto, deleteAssets, updateAsset } from '@immich/sdk';
import { DateTime } from 'luxon';
import { readFile } from 'node:fs/promises';
import { join } from 'node:path';
@@ -32,9 +32,6 @@ describe('/search', () => {
let assetGlarus: AssetFileUploadResponseDto;
let assetSprings: AssetFileUploadResponseDto;
let assetLast: AssetFileUploadResponseDto;
let cities: string[];
let states: string[];
let countries: string[];
beforeAll(async () => {
await utils.resetDatabase();
@@ -82,7 +79,7 @@ describe('/search', () => {
}
// note: the coordinates here are not the actual coordinates of the images and are random for most of them
const coordinates = [
const cities = [
{ latitude: 48.853_41, longitude: 2.3488 }, // paris
{ latitude: 63.0695, longitude: -151.0074 }, // denali
{ latitude: 52.524_37, longitude: 13.410_53 }, // berlin
@@ -104,7 +101,7 @@ describe('/search', () => {
];
const updates = assets.map((asset, i) =>
updateAsset({ id: asset.id, updateAssetDto: coordinates[i] }, { headers: asBearerAuth(admin.accessToken) }),
updateAsset({ id: asset.id, updateAssetDto: cities[i] }, { headers: asBearerAuth(admin.accessToken) }),
);
await Promise.all(updates);
@@ -136,12 +133,6 @@ describe('/search', () => {
assetLast = assets.at(-1) as AssetFileUploadResponseDto;
await deleteAssets({ assetBulkDeleteDto: { ids: [assetSilver.id] } }, { headers: asBearerAuth(admin.accessToken) });
const mapMarkers = await getMapMarkers({}, { headers: asBearerAuth(admin.accessToken) });
const nonTrashed = mapMarkers.filter((mark) => mark.id !== assetSilver.id);
cities = [...new Set(nonTrashed.map((mark) => mark.city).filter((entry): entry is string => !!entry))].sort();
states = [...new Set(nonTrashed.map((mark) => mark.state).filter((entry): entry is string => !!entry))].sort();
countries = [...new Set(nonTrashed.map((mark) => mark.country).filter((entry): entry is string => !!entry))].sort();
}, 30_000);
afterAll(async () => {
@@ -461,7 +452,21 @@ describe('/search', () => {
const { status, body } = await request(app)
.get('/search/suggestions?type=country')
.set('Authorization', `Bearer ${admin.accessToken}`);
expect(body).toEqual(countries);
expect(body).toEqual([
'Cuba',
'France',
'Georgia',
'Germany',
'Ghana',
'Japan',
'Morocco',
"People's Republic of China",
'Russian Federation',
'Singapore',
'Spain',
'Switzerland',
'United States of America',
]);
expect(status).toBe(200);
});
@@ -469,7 +474,23 @@ describe('/search', () => {
const { status, body } = await request(app)
.get('/search/suggestions?type=state')
.set('Authorization', `Bearer ${admin.accessToken}`);
expect(body).toEqual(states);
expect(body).toEqual([
'Accra, Greater Accra',
'Berlin',
'Glarus, Glarus',
'Havana',
'Marrakech, Marrakesh-Safi',
'Mesa County, Colorado',
'Neshoba County, Mississippi',
'New York',
'Page County, Virginia',
'Paris, Île-de-France',
'Province of Córdoba, Andalusia',
'Shanghai Municipality, Shanghai',
'St.-Petersburg',
'Tbilisi',
'Tokyo',
]);
expect(status).toBe(200);
});
@@ -477,7 +498,24 @@ describe('/search', () => {
const { status, body } = await request(app)
.get('/search/suggestions?type=city')
.set('Authorization', `Bearer ${admin.accessToken}`);
expect(body).toEqual(cities);
expect(body).toEqual([
'Accra',
'Berlin',
'Glarus',
'Havana',
'Marrakesh',
'Montalbán de Córdoba',
'New York City',
'Palisade',
'Paris',
'Philadelphia',
'Saint Petersburg',
'Shanghai',
'Singapore',
'Stanley',
'Tbilisi',
'Tokyo',
]);
expect(status).toBe(200);
});

View File

@@ -1,4 +1,4 @@
import { LoginResponseDto } from '@immich/sdk';
import { LoginResponseDto, getServerConfig } from '@immich/sdk';
import { createUserDto } from 'src/fixtures';
import { errorDto } from 'src/responses';
import { app, utils } from 'src/utils';
@@ -162,4 +162,19 @@ 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);
});
});
});

View File

@@ -1,75 +0,0 @@
import { LoginResponseDto, getSessions, login, signUpAdmin } from '@immich/sdk';
import { loginDto, signupDto, uuidDto } from 'src/fixtures';
import { deviceDto, errorDto } from 'src/responses';
import { app, asBearerAuth, utils } from 'src/utils';
import request from 'supertest';
import { beforeEach, describe, expect, it } from 'vitest';
describe('/sessions', () => {
let admin: LoginResponseDto;
beforeEach(async () => {
await utils.resetDatabase();
await signUpAdmin({ signUpDto: signupDto.admin });
admin = await login({ loginCredentialDto: loginDto.admin });
});
describe('GET /sessions', () => {
it('should require authentication', async () => {
const { status, body } = await request(app).get('/sessions');
expect(status).toBe(401);
expect(body).toEqual(errorDto.unauthorized);
});
it('should get a list of authorized devices', async () => {
const { status, body } = await request(app).get('/sessions').set('Authorization', `Bearer ${admin.accessToken}`);
expect(status).toBe(200);
expect(body).toEqual([deviceDto.current]);
});
});
describe('DELETE /sessions', () => {
it('should require authentication', async () => {
const { status, body } = await request(app).delete(`/sessions`);
expect(status).toBe(401);
expect(body).toEqual(errorDto.unauthorized);
});
it('should logout all devices (except the current one)', async () => {
for (let i = 0; i < 5; i++) {
await login({ loginCredentialDto: loginDto.admin });
}
await expect(getSessions({ headers: asBearerAuth(admin.accessToken) })).resolves.toHaveLength(6);
const { status } = await request(app).delete(`/sessions`).set('Authorization', `Bearer ${admin.accessToken}`);
expect(status).toBe(204);
await expect(getSessions({ headers: asBearerAuth(admin.accessToken) })).resolves.toHaveLength(1);
});
it('should throw an error for a non-existent device id', async () => {
const { status, body } = await request(app)
.delete(`/sessions/${uuidDto.notFound}`)
.set('Authorization', `Bearer ${admin.accessToken}`);
expect(status).toBe(400);
expect(body).toEqual(errorDto.badRequest('Not found or no authDevice.delete access'));
});
it('should logout a device', async () => {
const [device] = await getSessions({
headers: asBearerAuth(admin.accessToken),
});
const { status } = await request(app)
.delete(`/sessions/${device.id}`)
.set('Authorization', `Bearer ${admin.accessToken}`);
expect(status).toBe(204);
const response = await request(app)
.post('/auth/validateToken')
.set('Authorization', `Bearer ${admin.accessToken}`);
expect(response.body).toEqual(errorDto.invalidToken);
expect(response.status).toBe(401);
});
});
});

View File

@@ -1,76 +0,0 @@
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',
});
});
});
});

View File

@@ -1,19 +0,0 @@
import { immichAdmin, utils } from 'src/utils';
import { beforeAll, describe, expect, it } from 'vitest';
describe(`immich-admin`, () => {
beforeAll(async () => {
await utils.resetDatabase();
await utils.adminSetup();
});
describe('list-users', () => {
it('should list the admin user', async () => {
const { stdout, stderr, exitCode } = await immichAdmin(['list-users']);
expect(exitCode).toBe(0);
expect(stderr).toBe('');
expect(stdout).toContain("email: 'admin@immich.cloud'");
expect(stdout).toContain("name: 'Immich Admin'");
});
});
});

View File

@@ -24,8 +24,8 @@ import {
getConfigDefaults,
login,
searchMetadata,
setAdminOnboarding,
signUpAdmin,
updateAdminOnboarding,
updateConfig,
validate,
} from '@immich/sdk';
@@ -43,7 +43,7 @@ import { loginDto, signupDto } from 'src/fixtures';
import { makeRandomImage } from 'src/generators';
import request from 'supertest';
type CommandResponse = { stdout: string; stderr: string; exitCode: number | null };
type CliResponse = { stdout: string; stderr: string; exitCode: number | null };
type EventType = 'assetUpload' | 'assetUpdate' | 'assetDelete' | 'userDelete';
type WaitOptions = { event: EventType; id?: string; total?: number; timeout?: number };
type AdminSetupOptions = { onboarding?: boolean };
@@ -59,15 +59,13 @@ export const testAssetDirInternal = '/data/assets';
export const tempDir = tmpdir();
export const asBearerAuth = (accessToken: string) => ({ Authorization: `Bearer ${accessToken}` });
export const asKeyAuth = (key: string) => ({ 'x-api-key': key });
export const immichCli = (args: string[]) =>
executeCommand('node', ['node_modules/.bin/immich', '-d', `/${tempDir}/immich/`, ...args]);
export const immichAdmin = (args: string[]) =>
executeCommand('docker', ['exec', '-i', 'immich-e2e-server', '/bin/bash', '-c', `immich-admin ${args.join(' ')}`]);
const executeCommand = (command: string, args: string[]) => {
let _resolve: (value: CommandResponse) => void;
const deferred = new Promise<CommandResponse>((resolve) => (_resolve = resolve));
const child = spawn(command, args, { stdio: 'pipe' });
export const immichCli = async (args: string[]) => {
let _resolve: (value: CliResponse) => void;
const deferred = new Promise<CliResponse>((resolve) => (_resolve = resolve));
const _args = ['node_modules/.bin/immich', '-d', `/${tempDir}/immich/`, ...args];
const child = spawn('node', _args, {
stdio: 'pipe',
});
let stdout = '';
let stderr = '';
@@ -140,7 +138,7 @@ export const utils = {
'asset_faces',
'activity',
'api_keys',
'sessions',
'user_token',
'users',
'system_metadata',
'system_config',
@@ -264,10 +262,7 @@ export const utils = {
await signUpAdmin({ signUpDto: signupDto.admin });
const response = await login({ loginCredentialDto: loginDto.admin });
if (options.onboarding) {
await updateAdminOnboarding(
{ adminOnboardingUpdateDto: { isOnboarded: true } },
{ headers: asBearerAuth(response.accessToken) },
);
await setAdminOnboarding({ headers: asBearerAuth(response.accessToken) });
}
return response;
},

View File

@@ -10,7 +10,7 @@ try {
export default defineConfig({
test: {
include: ['src/{api,cli,immich-admin}/specs/*.e2e-spec.ts'],
include: ['src/{api,cli}/specs/*.e2e-spec.ts'],
globalSetup,
testTimeout: 15_000,
poolOptions: {

View File

@@ -1150,23 +1150,22 @@ test = ["objgraph", "psutil"]
[[package]]
name = "gunicorn"
version = "22.0.0"
version = "21.2.0"
description = "WSGI HTTP Server for UNIX"
optional = false
python-versions = ">=3.7"
python-versions = ">=3.5"
files = [
{file = "gunicorn-22.0.0-py3-none-any.whl", hash = "sha256:350679f91b24062c86e386e198a15438d53a7a8207235a78ba1b53df4c4378d9"},
{file = "gunicorn-22.0.0.tar.gz", hash = "sha256:4a0b436239ff76fb33f11c07a16482c521a7e09c1ce3cc293c2330afe01bec63"},
{file = "gunicorn-21.2.0-py3-none-any.whl", hash = "sha256:3213aa5e8c24949e792bcacfc176fef362e7aac80b76c56f6b5122bf350722f0"},
{file = "gunicorn-21.2.0.tar.gz", hash = "sha256:88ec8bff1d634f98e61b9f65bc4bf3cd918a90806c6f5c48bc5603849ec81033"},
]
[package.dependencies]
packaging = "*"
[package.extras]
eventlet = ["eventlet (>=0.24.1,!=0.36.0)"]
eventlet = ["eventlet (>=0.24.1)"]
gevent = ["gevent (>=1.4.0)"]
setproctitle = ["setproctitle"]
testing = ["coverage", "eventlet", "gevent", "pytest", "pytest-cov"]
tornado = ["tornado (>=0.2)"]
[[package]]

View File

@@ -1,6 +1,6 @@
[tool.poetry]
name = "machine-learning"
version = "1.102.1"
version = "1.101.0"
description = ""
authors = ["Hau Tran <alex.tran1502@gmail.com>"]
readme = "README.md"

View File

@@ -90,7 +90,7 @@ flutter {
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"
implementation "androidx.work:work-runtime:$work_version"
implementation "androidx.work:work-runtime-ktx:$work_version"
implementation "androidx.concurrent:concurrent-futures:$concurrent_version"
implementation "com.google.guava:guava:$guava_version"
implementation "com.github.bumptech.glide:glide:$glide_version"

View File

@@ -52,7 +52,6 @@ class BackgroundServicePlugin : FlutterPlugin, MethodChannel.MethodCallHandler {
.putBoolean(ContentObserverWorker.SHARED_PREF_SERVICE_ENABLED, true)
.putLong(BackupWorker.SHARED_PREF_CALLBACK_KEY, args.get(0) as Long)
.putString(BackupWorker.SHARED_PREF_NOTIFICATION_TITLE, args.get(1) as String)
.putString(BackupWorker.SHARED_PREF_SERVER_URL, args.get(3) as String)
.apply()
ContentObserverWorker.enable(ctx, immediate = args.get(2) as Boolean)
result.success(true)

View File

@@ -11,8 +11,8 @@ import android.os.PowerManager
import android.os.SystemClock
import android.util.Log
import androidx.annotation.RequiresApi
import androidx.concurrent.futures.CallbackToFutureAdapter
import androidx.core.app.NotificationCompat
import androidx.concurrent.futures.ResolvableFuture
import androidx.work.BackoffPolicy
import androidx.work.Constraints
import androidx.work.ForegroundInfo
@@ -30,16 +30,6 @@ import io.flutter.embedding.engine.loader.FlutterLoader
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.view.FlutterCallbackInformation
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.coroutines.withTimeoutOrNull
import java.io.IOException
import java.net.HttpURLConnection
import java.net.InetAddress
import java.net.URL
import java.util.concurrent.TimeUnit
/**
@@ -52,6 +42,7 @@ import java.util.concurrent.TimeUnit
*/
class BackupWorker(ctx: Context, params: WorkerParameters) : ListenableWorker(ctx, params), MethodChannel.MethodCallHandler {
private val resolvableFuture = ResolvableFuture.create<Result>()
private var engine: FlutterEngine? = null
private lateinit var backgroundChannel: MethodChannel
private val notificationManager = ctx.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
@@ -61,80 +52,35 @@ class BackupWorker(ctx: Context, params: WorkerParameters) : ListenableWorker(ct
private var notificationDetailBuilder: NotificationCompat.Builder? = null
private var fgFuture: ListenableFuture<Void>? = null
private val job = Job()
private lateinit var completer: CallbackToFutureAdapter.Completer<Result>
private val resolvableFuture = CallbackToFutureAdapter.getFuture { completer ->
this.completer = completer
null
}
init {
resolvableFuture.addListener(
Runnable {
if (resolvableFuture.isCancelled) {
job.cancel()
}
},
taskExecutor.serialTaskExecutor
)
}
override fun startWork(): ListenableFuture<ListenableWorker.Result> {
Log.d(TAG, "startWork")
val ctx = applicationContext
val prefs = ctx.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE)
prefs.getString(SHARED_PREF_SERVER_URL, null)
?.takeIf { it.isNotEmpty() }
?.let { serverUrl -> doCoroutineWork(serverUrl) }
?: doWork()
return resolvableFuture
}
/**
* This function is used to check if server URL is reachable before starting the backup work.
* Check must be done in a background to avoid blocking the main thread.
*/
private fun doCoroutineWork(serverUrl : String) {
CoroutineScope(Dispatchers.Default + job).launch {
val isReachable = isUrlReachableHttp(serverUrl)
withContext(Dispatchers.Main) {
if (isReachable) {
doWork()
} else {
// Fail when the URL is not reachable
completer.set(Result.failure())
}
}
if (!flutterLoader.initialized()) {
flutterLoader.startInitialization(ctx)
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Create a Notification channel if necessary
createChannel()
}
if (isIgnoringBatteryOptimizations) {
// normal background services can only up to 10 minutes
// foreground services are allowed to run indefinitely
// requires battery optimizations to be disabled (either manually by the user
// or by the system learning that immich is important to the user)
val title = ctx.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE)
.getString(SHARED_PREF_NOTIFICATION_TITLE, NOTIFICATION_DEFAULT_TITLE)!!
showInfo(getInfoBuilder(title, indeterminate=true).build())
}
engine = FlutterEngine(ctx)
private fun doWork() {
Log.d(TAG, "doWork")
val ctx = applicationContext
flutterLoader.ensureInitializationCompleteAsync(ctx, null, Handler(Looper.getMainLooper())) {
runDart()
}
if (!flutterLoader.initialized()) {
flutterLoader.startInitialization(ctx)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Create a Notification channel if necessary
createChannel()
}
if (isIgnoringBatteryOptimizations) {
// normal background services can only up to 10 minutes
// foreground services are allowed to run indefinitely
// requires battery optimizations to be disabled (either manually by the user
// or by the system learning that immich is important to the user)
val title = ctx.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE)
.getString(SHARED_PREF_NOTIFICATION_TITLE, NOTIFICATION_DEFAULT_TITLE)!!
showInfo(getInfoBuilder(title, indeterminate=true).build())
}
engine = FlutterEngine(ctx)
flutterLoader.ensureInitializationCompleteAsync(ctx, null, Handler(Looper.getMainLooper())) {
runDart()
}
return resolvableFuture
}
/**
@@ -193,7 +139,7 @@ class BackupWorker(ctx: Context, params: WorkerParameters) : ListenableWorker(ct
engine = null
if (result != null) {
Log.d(TAG, "stopEngine result=${result}")
this.completer.set(result)
resolvableFuture.set(result)
}
waitOnSetForegroundAsync()
}
@@ -324,14 +270,13 @@ class BackupWorker(ctx: Context, params: WorkerParameters) : ListenableWorker(ct
const val SHARED_PREF_CALLBACK_KEY = "callbackDispatcherHandle"
const val SHARED_PREF_NOTIFICATION_TITLE = "notificationTitle"
const val SHARED_PREF_LAST_CHANGE = "lastChange"
const val SHARED_PREF_SERVER_URL = "serverUrl"
private const val TASK_NAME_BACKUP = "immich/BackupWorker"
private const val NOTIFICATION_CHANNEL_ID = "immich/backgroundService"
private const val NOTIFICATION_CHANNEL_ERROR_ID = "immich/backgroundServiceError"
private const val NOTIFICATION_DEFAULT_TITLE = "Immich"
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 ONE_MINUTE = 60000L
@@ -359,7 +304,7 @@ class BackupWorker(ctx: Context, params: WorkerParameters) : ListenableWorker(ct
val workInfoList = workInfoFuture.get(1000, TimeUnit.MILLISECONDS)
if (workInfoList != null) {
for (workInfo in workInfoList) {
if (workInfo.state == WorkInfo.State.ENQUEUED) {
if (workInfo.getState() == WorkInfo.State.ENQUEUED) {
val workRequest = buildWorkRequest(requireWifi, requireCharging)
wm.enqueueUniqueWork(TASK_NAME_BACKUP, ExistingWorkPolicy.REPLACE, workRequest)
Log.d(TAG, "updateBackupWorker updated BackupWorker constraints")
@@ -414,27 +359,4 @@ class BackupWorker(ctx: Context, params: WorkerParameters) : ListenableWorker(ct
}
}
private const val TAG = "BackupWorker"
/**
* Check if the given URL is reachable via HTTP
*/
suspend fun isUrlReachableHttp(url: String, timeoutMillis: Long = 5000L): Boolean {
return withTimeoutOrNull(timeoutMillis) {
var httpURLConnection: HttpURLConnection? = null
try {
httpURLConnection = (URL(url).openConnection() as HttpURLConnection).apply {
requestMethod = "HEAD"
connectTimeout = timeoutMillis.toInt()
readTimeout = timeoutMillis.toInt()
}
httpURLConnection.connect()
httpURLConnection.responseCode == HttpURLConnection.HTTP_OK
} catch (e: Exception) {
Log.e(TAG, "Failed to reach server URL: $e")
false
} finally {
httpURLConnection?.disconnect()
}
} == true
}
private const val TAG = "BackupWorker"

View File

@@ -1,7 +1,7 @@
buildscript {
ext.kotlin_version = '1.8.22'
ext.kotlin_version = '1.8.20'
ext.kotlin_coroutines_version = '1.7.1'
ext.work_version = '2.9.0'
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'

View File

@@ -35,8 +35,8 @@ platform :android do
task: 'bundle',
build_type: 'Release',
properties: {
"android.injected.version.code" => 133,
"android.injected.version.name" => "1.102.1",
"android.injected.version.code" => 131,
"android.injected.version.name" => "1.101.0",
}
)
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')

View File

@@ -5,17 +5,17 @@
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000256">
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000219">
</testcase>
<testcase classname="fastlane.lanes" name="1: bundleRelease" time="73.93743">
<testcase classname="fastlane.lanes" name="1: bundleRelease" time="67.515419">
</testcase>
<testcase classname="fastlane.lanes" name="2: upload_to_play_store" time="34.73691">
<testcase classname="fastlane.lanes" name="2: upload_to_play_store" time="35.431743">
</testcase>

Binary file not shown.

View File

@@ -383,7 +383,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/RunnerProfile.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 148;
CURRENT_PROJECT_VERSION = 147;
DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
@@ -525,7 +525,7 @@
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 148;
CURRENT_PROJECT_VERSION = 147;
DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
@@ -553,7 +553,7 @@
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 148;
CURRENT_PROJECT_VERSION = 147;
DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;

View File

@@ -58,11 +58,11 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.102.0</string>
<string>1.101.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>148</string>
<string>147</string>
<key>FLTEnableImpeller</key>
<true />
<key>ITSAppUsesNonExemptEncryption</key>

View File

@@ -19,7 +19,7 @@ platform :ios do
desc "iOS Beta"
lane :beta do
increment_version_number(
version_number: "1.102.1"
version_number: "1.101.0"
)
increment_build_number(
build_number: latest_testflight_build_number + 1,

View File

@@ -5,32 +5,32 @@
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000399">
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000242">
</testcase>
<testcase classname="fastlane.lanes" name="1: increment_version_number" time="0.247535">
<testcase classname="fastlane.lanes" name="1: increment_version_number" time="0.761829">
</testcase>
<testcase classname="fastlane.lanes" name="2: latest_testflight_build_number" time="8.325258">
<testcase classname="fastlane.lanes" name="2: latest_testflight_build_number" time="4.47461">
</testcase>
<testcase classname="fastlane.lanes" name="3: increment_build_number" time="0.180002">
<testcase classname="fastlane.lanes" name="3: increment_build_number" time="0.179512">
</testcase>
<testcase classname="fastlane.lanes" name="4: build_app" time="199.335284">
<testcase classname="fastlane.lanes" name="4: build_app" time="165.636347">
</testcase>
<testcase classname="fastlane.lanes" name="5: upload_to_testflight" time="90.564254">
<testcase classname="fastlane.lanes" name="5: upload_to_testflight" time="77.651963">
</testcase>

View File

@@ -20,7 +20,6 @@ import 'package:immich_mobile/shared/models/store.dart';
import 'package:immich_mobile/shared/services/api.service.dart';
import 'package:immich_mobile/utils/backup_progress.dart';
import 'package:immich_mobile/utils/diff.dart';
import 'package:immich_mobile/utils/url_helper.dart';
import 'package:isar/isar.dart';
import 'package:path_provider_ios/path_provider_ios.dart';
import 'package:photo_manager/photo_manager.dart';
@@ -69,10 +68,8 @@ class BackgroundService {
final callback = PluginUtilities.getCallbackHandle(_nativeEntry)!;
final String title =
"backup_background_service_default_notification".tr();
final bool ok = await _foregroundChannel.invokeMethod(
'enable',
[callback.toRawHandle(), title, immediate, getServerUrl()],
);
final bool ok = await _foregroundChannel
.invokeMethod('enable', [callback.toRawHandle(), title, immediate]);
return ok;
} catch (error) {
return false;

View File

@@ -39,24 +39,27 @@ class ImmichAppBarDialog extends HookConsumerWidget {
);
buildTopRow() {
return Stack(
return Row(
children: [
Align(
alignment: Alignment.topLeft,
child: InkWell(
onTap: () => context.pop(),
child: const Icon(
Icons.close,
size: 20,
),
InkWell(
onTap: () => context.pop(),
child: const Icon(
Icons.close,
size: 20,
),
),
Center(
child: Image.asset(
context.isDarkTheme
? 'assets/immich-text-dark.png'
: 'assets/immich-text-light.png',
height: 16,
Expanded(
child: Align(
alignment: Alignment.center,
child: Text(
'IMMICH',
style: TextStyle(
fontFamily: 'SnowburstOne',
fontWeight: FontWeight.bold,
color: context.primaryColor,
fontSize: 16,
),
),
),
),
],

View File

@@ -13,7 +13,6 @@ doc/ActivityCreateDto.md
doc/ActivityResponseDto.md
doc/ActivityStatisticsResponseDto.md
doc/AddUsersDto.md
doc/AdminOnboardingUpdateDto.md
doc/AlbumApi.md
doc/AlbumCountResponseDto.md
doc/AlbumResponseDto.md
@@ -42,6 +41,7 @@ doc/AssetTypeEnum.md
doc/AudioCodec.md
doc/AuditApi.md
doc/AuditDeletesResponseDto.md
doc/AuthDeviceResponseDto.md
doc/AuthenticationApi.md
doc/BulkIdResponseDto.md
doc/BulkIdsDto.md
@@ -70,7 +70,6 @@ doc/FaceApi.md
doc/FaceDto.md
doc/FileChecksumDto.md
doc/FileChecksumResponseDto.md
doc/FileReportApi.md
doc/FileReportDto.md
doc/FileReportFixDto.md
doc/FileReportItemDto.md
@@ -124,7 +123,6 @@ doc/QueueStatusDto.md
doc/ReactionLevel.md
doc/ReactionType.md
doc/RecognitionConfig.md
doc/ReverseGeocodingStateResponseDto.md
doc/ScanLibraryDto.md
doc/SearchAlbumResponseDto.md
doc/SearchApi.md
@@ -144,8 +142,6 @@ doc/ServerPingResponse.md
doc/ServerStatsResponseDto.md
doc/ServerThemeDto.md
doc/ServerVersionResponseDto.md
doc/SessionResponseDto.md
doc/SessionsApi.md
doc/SharedLinkApi.md
doc/SharedLinkCreateDto.md
doc/SharedLinkEditDto.md
@@ -176,7 +172,6 @@ doc/SystemConfigTemplateStorageOptionDto.md
doc/SystemConfigThemeDto.md
doc/SystemConfigTrashDto.md
doc/SystemConfigUserDto.md
doc/SystemMetadataApi.md
doc/TagApi.md
doc/TagResponseDto.md
doc/TagTypeEnum.md
@@ -216,7 +211,6 @@ lib/api/audit_api.dart
lib/api/authentication_api.dart
lib/api/download_api.dart
lib/api/face_api.dart
lib/api/file_report_api.dart
lib/api/job_api.dart
lib/api/library_api.dart
lib/api/memory_api.dart
@@ -225,11 +219,9 @@ lib/api/partner_api.dart
lib/api/person_api.dart
lib/api/search_api.dart
lib/api/server_info_api.dart
lib/api/sessions_api.dart
lib/api/shared_link_api.dart
lib/api/sync_api.dart
lib/api/system_config_api.dart
lib/api/system_metadata_api.dart
lib/api/tag_api.dart
lib/api/timeline_api.dart
lib/api/trash_api.dart
@@ -246,7 +238,6 @@ lib/model/activity_create_dto.dart
lib/model/activity_response_dto.dart
lib/model/activity_statistics_response_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_response_dto.dart
lib/model/all_job_status_response_dto.dart
@@ -276,6 +267,7 @@ lib/model/asset_stats_response_dto.dart
lib/model/asset_type_enum.dart
lib/model/audio_codec.dart
lib/model/audit_deletes_response_dto.dart
lib/model/auth_device_response_dto.dart
lib/model/bulk_id_response_dto.dart
lib/model/bulk_ids_dto.dart
lib/model/change_password_dto.dart
@@ -348,7 +340,6 @@ lib/model/queue_status_dto.dart
lib/model/reaction_level.dart
lib/model/reaction_type.dart
lib/model/recognition_config.dart
lib/model/reverse_geocoding_state_response_dto.dart
lib/model/scan_library_dto.dart
lib/model/search_album_response_dto.dart
lib/model/search_asset_response_dto.dart
@@ -366,7 +357,6 @@ lib/model/server_ping_response.dart
lib/model/server_stats_response_dto.dart
lib/model/server_theme_dto.dart
lib/model/server_version_response_dto.dart
lib/model/session_response_dto.dart
lib/model/shared_link_create_dto.dart
lib/model/shared_link_edit_dto.dart
lib/model/shared_link_response_dto.dart
@@ -425,7 +415,6 @@ test/activity_create_dto_test.dart
test/activity_response_dto_test.dart
test/activity_statistics_response_dto_test.dart
test/add_users_dto_test.dart
test/admin_onboarding_update_dto_test.dart
test/album_api_test.dart
test/album_count_response_dto_test.dart
test/album_response_dto_test.dart
@@ -459,6 +448,7 @@ test/asset_type_enum_test.dart
test/audio_codec_test.dart
test/audit_api_test.dart
test/audit_deletes_response_dto_test.dart
test/auth_device_response_dto_test.dart
test/authentication_api_test.dart
test/bulk_id_response_dto_test.dart
test/bulk_ids_dto_test.dart
@@ -487,7 +477,6 @@ test/face_api_test.dart
test/face_dto_test.dart
test/file_checksum_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_fix_dto_test.dart
test/file_report_item_dto_test.dart
@@ -541,7 +530,6 @@ test/queue_status_dto_test.dart
test/reaction_level_test.dart
test/reaction_type_test.dart
test/recognition_config_test.dart
test/reverse_geocoding_state_response_dto_test.dart
test/scan_library_dto_test.dart
test/search_album_response_dto_test.dart
test/search_api_test.dart
@@ -561,8 +549,6 @@ test/server_ping_response_test.dart
test/server_stats_response_dto_test.dart
test/server_theme_dto_test.dart
test/server_version_response_dto_test.dart
test/session_response_dto_test.dart
test/sessions_api_test.dart
test/shared_link_api_test.dart
test/shared_link_create_dto_test.dart
test/shared_link_edit_dto_test.dart
@@ -593,7 +579,6 @@ test/system_config_template_storage_option_dto_test.dart
test/system_config_theme_dto_test.dart
test/system_config_trash_dto_test.dart
test/system_config_user_dto_test.dart
test/system_metadata_api_test.dart
test/tag_api_test.dart
test/tag_response_dto_test.dart
test/tag_type_enum_test.dart

View File

@@ -3,7 +3,7 @@ Immich API
This Dart package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
- API version: 1.102.1
- API version: 1.101.0
- Build package: org.openapitools.codegen.languages.DartClientCodegen
## Requirements
@@ -112,10 +112,16 @@ Class | Method | HTTP request | Description
*AssetApi* | [**updateAssets**](doc//AssetApi.md#updateassets) | **PUT** /asset |
*AssetApi* | [**updateStackParent**](doc//AssetApi.md#updatestackparent) | **PUT** /asset/stack/parent |
*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* | [**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* | [**getAuthDevices**](doc//AuthenticationApi.md#getauthdevices) | **GET** /auth/devices |
*AuthenticationApi* | [**login**](doc//AuthenticationApi.md#login) | **POST** /auth/login |
*AuthenticationApi* | [**logout**](doc//AuthenticationApi.md#logout) | **POST** /auth/logout |
*AuthenticationApi* | [**logoutAuthDevice**](doc//AuthenticationApi.md#logoutauthdevice) | **DELETE** /auth/devices/{id} |
*AuthenticationApi* | [**logoutAuthDevices**](doc//AuthenticationApi.md#logoutauthdevices) | **DELETE** /auth/devices |
*AuthenticationApi* | [**signUpAdmin**](doc//AuthenticationApi.md#signupadmin) | **POST** /auth/admin-sign-up |
*AuthenticationApi* | [**validateAccessToken**](doc//AuthenticationApi.md#validateaccesstoken) | **POST** /auth/validateToken |
*DownloadApi* | [**downloadArchive**](doc//DownloadApi.md#downloadarchive) | **POST** /download/archive |
@@ -123,9 +129,6 @@ Class | Method | HTTP request | Description
*DownloadApi* | [**getDownloadInfo**](doc//DownloadApi.md#getdownloadinfo) | **POST** /download/info |
*FaceApi* | [**getFaces**](doc//FaceApi.md#getfaces) | **GET** /face |
*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* | [**sendJobCommand**](doc//JobApi.md#sendjobcommand) | **PUT** /jobs/{id} |
*LibraryApi* | [**createLibrary**](doc//LibraryApi.md#createlibrary) | **POST** /library |
@@ -179,9 +182,7 @@ Class | Method | HTTP request | Description
*ServerInfoApi* | [**getSupportedMediaTypes**](doc//ServerInfoApi.md#getsupportedmediatypes) | **GET** /server-info/media-types |
*ServerInfoApi* | [**getTheme**](doc//ServerInfoApi.md#gettheme) | **GET** /server-info/theme |
*ServerInfoApi* | [**pingServer**](doc//ServerInfoApi.md#pingserver) | **GET** /server-info/ping |
*SessionsApi* | [**deleteAllSessions**](doc//SessionsApi.md#deleteallsessions) | **DELETE** /sessions |
*SessionsApi* | [**deleteSession**](doc//SessionsApi.md#deletesession) | **DELETE** /sessions/{id} |
*SessionsApi* | [**getSessions**](doc//SessionsApi.md#getsessions) | **GET** /sessions |
*ServerInfoApi* | [**setAdminOnboarding**](doc//ServerInfoApi.md#setadminonboarding) | **POST** /server-info/admin-onboarding |
*SharedLinkApi* | [**addSharedLinkAssets**](doc//SharedLinkApi.md#addsharedlinkassets) | **PUT** /shared-link/{id}/assets |
*SharedLinkApi* | [**createSharedLink**](doc//SharedLinkApi.md#createsharedlink) | **POST** /shared-link |
*SharedLinkApi* | [**getAllSharedLinks**](doc//SharedLinkApi.md#getallsharedlinks) | **GET** /shared-link |
@@ -197,9 +198,6 @@ Class | Method | HTTP request | Description
*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* | [**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* | [**deleteTag**](doc//TagApi.md#deletetag) | **DELETE** /tag/{id} |
*TagApi* | [**getAllTags**](doc//TagApi.md#getalltags) | **GET** /tag |
@@ -235,7 +233,6 @@ Class | Method | HTTP request | Description
- [ActivityResponseDto](doc//ActivityResponseDto.md)
- [ActivityStatisticsResponseDto](doc//ActivityStatisticsResponseDto.md)
- [AddUsersDto](doc//AddUsersDto.md)
- [AdminOnboardingUpdateDto](doc//AdminOnboardingUpdateDto.md)
- [AlbumCountResponseDto](doc//AlbumCountResponseDto.md)
- [AlbumResponseDto](doc//AlbumResponseDto.md)
- [AllJobStatusResponseDto](doc//AllJobStatusResponseDto.md)
@@ -261,6 +258,7 @@ Class | Method | HTTP request | Description
- [AssetTypeEnum](doc//AssetTypeEnum.md)
- [AudioCodec](doc//AudioCodec.md)
- [AuditDeletesResponseDto](doc//AuditDeletesResponseDto.md)
- [AuthDeviceResponseDto](doc//AuthDeviceResponseDto.md)
- [BulkIdResponseDto](doc//BulkIdResponseDto.md)
- [BulkIdsDto](doc//BulkIdsDto.md)
- [CLIPConfig](doc//CLIPConfig.md)
@@ -333,7 +331,6 @@ Class | Method | HTTP request | Description
- [ReactionLevel](doc//ReactionLevel.md)
- [ReactionType](doc//ReactionType.md)
- [RecognitionConfig](doc//RecognitionConfig.md)
- [ReverseGeocodingStateResponseDto](doc//ReverseGeocodingStateResponseDto.md)
- [ScanLibraryDto](doc//ScanLibraryDto.md)
- [SearchAlbumResponseDto](doc//SearchAlbumResponseDto.md)
- [SearchAssetResponseDto](doc//SearchAssetResponseDto.md)
@@ -351,7 +348,6 @@ Class | Method | HTTP request | Description
- [ServerStatsResponseDto](doc//ServerStatsResponseDto.md)
- [ServerThemeDto](doc//ServerThemeDto.md)
- [ServerVersionResponseDto](doc//ServerVersionResponseDto.md)
- [SessionResponseDto](doc//SessionResponseDto.md)
- [SharedLinkCreateDto](doc//SharedLinkCreateDto.md)
- [SharedLinkEditDto](doc//SharedLinkEditDto.md)
- [SharedLinkResponseDto](doc//SharedLinkResponseDto.md)

View File

@@ -1,15 +0,0 @@
# 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)

View File

@@ -9,9 +9,66 @@ All URIs are relative to */api*
Method | HTTP request | Description
------------- | ------------- | -------------
[**fixAuditFiles**](AuditApi.md#fixauditfiles) | **POST** /audit/file-report/fix |
[**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**
> AuditDeletesResponseDto getAuditDeletes(after, entityType, userId)
@@ -71,3 +128,109 @@ 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)
# **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)

View File

@@ -1,4 +1,4 @@
# openapi.model.SessionResponseDto
# openapi.model.AuthDeviceResponseDto
## Load the model package
```dart

View File

@@ -10,8 +10,11 @@ All URIs are relative to */api*
Method | HTTP request | Description
------------- | ------------- | -------------
[**changePassword**](AuthenticationApi.md#changepassword) | **POST** /auth/change-password |
[**getAuthDevices**](AuthenticationApi.md#getauthdevices) | **GET** /auth/devices |
[**login**](AuthenticationApi.md#login) | **POST** /auth/login |
[**logout**](AuthenticationApi.md#logout) | **POST** /auth/logout |
[**logoutAuthDevice**](AuthenticationApi.md#logoutauthdevice) | **DELETE** /auth/devices/{id} |
[**logoutAuthDevices**](AuthenticationApi.md#logoutauthdevices) | **DELETE** /auth/devices |
[**signUpAdmin**](AuthenticationApi.md#signupadmin) | **POST** /auth/admin-sign-up |
[**validateAccessToken**](AuthenticationApi.md#validateaccesstoken) | **POST** /auth/validateToken |
@@ -71,6 +74,57 @@ 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)
# **getAuthDevices**
> List<AuthDeviceResponseDto> getAuthDevices()
### 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 = AuthenticationApi();
try {
final result = api_instance.getAuthDevices();
print(result);
} catch (e) {
print('Exception when calling AuthenticationApi->getAuthDevices: $e\n');
}
```
### Parameters
This endpoint does not need any parameter.
### Return type
[**List<AuthDeviceResponseDto>**](AuthDeviceResponseDto.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)
# **login**
> LoginResponseDto login(loginCredentialDto)
@@ -163,6 +217,110 @@ This endpoint does not need any parameter.
[[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)
# **logoutAuthDevice**
> logoutAuthDevice(id)
### 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 = AuthenticationApi();
final id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
try {
api_instance.logoutAuthDevice(id);
} catch (e) {
print('Exception when calling AuthenticationApi->logoutAuthDevice: $e\n');
}
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**id** | **String**| |
### 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)
# **logoutAuthDevices**
> logoutAuthDevices()
### 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 = AuthenticationApi();
try {
api_instance.logoutAuthDevices();
} catch (e) {
print('Exception when calling AuthenticationApi->logoutAuthDevices: $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)
# **signUpAdmin**
> UserResponseDto signUpAdmin(signUpDto)

View File

@@ -1,176 +0,0 @@
# 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)

View File

@@ -1,16 +0,0 @@
# 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)

View File

@@ -17,6 +17,7 @@ Method | HTTP request | Description
[**getSupportedMediaTypes**](ServerInfoApi.md#getsupportedmediatypes) | **GET** /server-info/media-types |
[**getTheme**](ServerInfoApi.md#gettheme) | **GET** /server-info/theme |
[**pingServer**](ServerInfoApi.md#pingserver) | **GET** /server-info/ping |
[**setAdminOnboarding**](ServerInfoApi.md#setadminonboarding) | **POST** /server-info/admin-onboarding |
# **getServerConfig**
@@ -343,3 +344,53 @@ 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)
# **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)

View File

@@ -1,171 +0,0 @@
# openapi.api.SessionsApi
## Load the API package
```dart
import 'package:openapi/api.dart';
```
All URIs are relative to */api*
Method | HTTP request | Description
------------- | ------------- | -------------
[**deleteAllSessions**](SessionsApi.md#deleteallsessions) | **DELETE** /sessions |
[**deleteSession**](SessionsApi.md#deletesession) | **DELETE** /sessions/{id} |
[**getSessions**](SessionsApi.md#getsessions) | **GET** /sessions |
# **deleteAllSessions**
> deleteAllSessions()
### 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 = SessionsApi();
try {
api_instance.deleteAllSessions();
} catch (e) {
print('Exception when calling SessionsApi->deleteAllSessions: $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)
# **deleteSession**
> deleteSession(id)
### 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 = SessionsApi();
final id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
try {
api_instance.deleteSession(id);
} catch (e) {
print('Exception when calling SessionsApi->deleteSession: $e\n');
}
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**id** | **String**| |
### 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)
# **getSessions**
> List<SessionResponseDto> getSessions()
### 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 = SessionsApi();
try {
final result = api_instance.getSessions();
print(result);
} catch (e) {
print('Exception when calling SessionsApi->getSessions: $e\n');
}
```
### Parameters
This endpoint does not need any parameter.
### Return type
[**List<SessionResponseDto>**](SessionResponseDto.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)

View File

@@ -9,7 +9,6 @@ import 'package:openapi/api.dart';
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**colorspace** | [**Colorspace**](Colorspace.md) | |
**extractEmbedded** | **bool** | |
**previewFormat** | [**ImageFormat**](ImageFormat.md) | |
**previewSize** | **int** | |
**quality** | **int** | |

View File

@@ -1,172 +0,0 @@
# 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)

View File

@@ -37,7 +37,6 @@ part 'api/audit_api.dart';
part 'api/authentication_api.dart';
part 'api/download_api.dart';
part 'api/face_api.dart';
part 'api/file_report_api.dart';
part 'api/job_api.dart';
part 'api/library_api.dart';
part 'api/memory_api.dart';
@@ -46,11 +45,9 @@ part 'api/partner_api.dart';
part 'api/person_api.dart';
part 'api/search_api.dart';
part 'api/server_info_api.dart';
part 'api/sessions_api.dart';
part 'api/shared_link_api.dart';
part 'api/sync_api.dart';
part 'api/system_config_api.dart';
part 'api/system_metadata_api.dart';
part 'api/tag_api.dart';
part 'api/timeline_api.dart';
part 'api/trash_api.dart';
@@ -64,7 +61,6 @@ part 'model/activity_create_dto.dart';
part 'model/activity_response_dto.dart';
part 'model/activity_statistics_response_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_response_dto.dart';
part 'model/all_job_status_response_dto.dart';
@@ -90,6 +86,7 @@ part 'model/asset_stats_response_dto.dart';
part 'model/asset_type_enum.dart';
part 'model/audio_codec.dart';
part 'model/audit_deletes_response_dto.dart';
part 'model/auth_device_response_dto.dart';
part 'model/bulk_id_response_dto.dart';
part 'model/bulk_ids_dto.dart';
part 'model/clip_config.dart';
@@ -162,7 +159,6 @@ part 'model/queue_status_dto.dart';
part 'model/reaction_level.dart';
part 'model/reaction_type.dart';
part 'model/recognition_config.dart';
part 'model/reverse_geocoding_state_response_dto.dart';
part 'model/scan_library_dto.dart';
part 'model/search_album_response_dto.dart';
part 'model/search_asset_response_dto.dart';
@@ -180,7 +176,6 @@ part 'model/server_ping_response.dart';
part 'model/server_stats_response_dto.dart';
part 'model/server_theme_dto.dart';
part 'model/server_version_response_dto.dart';
part 'model/session_response_dto.dart';
part 'model/shared_link_create_dto.dart';
part 'model/shared_link_edit_dto.dart';
part 'model/shared_link_response_dto.dart';

View File

@@ -16,6 +16,45 @@ class AuditApi {
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].
/// Parameters:
///
@@ -76,4 +115,95 @@ class AuditApi {
}
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;
}
}

View File

@@ -63,6 +63,50 @@ class AuthenticationApi {
return null;
}
/// Performs an HTTP 'GET /auth/devices' operation and returns the [Response].
Future<Response> getAuthDevicesWithHttpInfo() async {
// ignore: prefer_const_declarations
final path = r'/auth/devices';
// 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<List<AuthDeviceResponseDto>?> getAuthDevices() async {
final response = await getAuthDevicesWithHttpInfo();
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<AuthDeviceResponseDto>') as List)
.cast<AuthDeviceResponseDto>()
.toList(growable: false);
}
return null;
}
/// Performs an HTTP 'POST /auth/login' operation and returns the [Response].
/// Parameters:
///
@@ -151,6 +195,79 @@ class AuthenticationApi {
return null;
}
/// Performs an HTTP 'DELETE /auth/devices/{id}' operation and returns the [Response].
/// Parameters:
///
/// * [String] id (required):
Future<Response> logoutAuthDeviceWithHttpInfo(String id,) async {
// ignore: prefer_const_declarations
final path = r'/auth/devices/{id}'
.replaceAll('{id}', id);
// ignore: prefer_final_locals
Object? postBody;
final queryParams = <QueryParam>[];
final headerParams = <String, String>{};
final formParams = <String, String>{};
const contentTypes = <String>[];
return apiClient.invokeAPI(
path,
'DELETE',
queryParams,
postBody,
headerParams,
formParams,
contentTypes.isEmpty ? null : contentTypes.first,
);
}
/// Parameters:
///
/// * [String] id (required):
Future<void> logoutAuthDevice(String id,) async {
final response = await logoutAuthDeviceWithHttpInfo(id,);
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
}
/// Performs an HTTP 'DELETE /auth/devices' operation and returns the [Response].
Future<Response> logoutAuthDevicesWithHttpInfo() async {
// ignore: prefer_const_declarations
final path = r'/auth/devices';
// ignore: prefer_final_locals
Object? postBody;
final queryParams = <QueryParam>[];
final headerParams = <String, String>{};
final formParams = <String, String>{};
const contentTypes = <String>[];
return apiClient.invokeAPI(
path,
'DELETE',
queryParams,
postBody,
headerParams,
formParams,
contentTypes.isEmpty ? null : contentTypes.first,
);
}
Future<void> logoutAuthDevices() async {
final response = await logoutAuthDevicesWithHttpInfo();
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
}
/// Performs an HTTP 'POST /auth/admin-sign-up' operation and returns the [Response].
/// Parameters:
///

View File

@@ -1,148 +0,0 @@
//
// 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;
}
}

View File

@@ -343,4 +343,37 @@ class ServerInfoApi {
}
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));
}
}
}

View File

@@ -1,135 +0,0 @@
//
// 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 SessionsApi {
SessionsApi([ApiClient? apiClient]) : apiClient = apiClient ?? defaultApiClient;
final ApiClient apiClient;
/// Performs an HTTP 'DELETE /sessions' operation and returns the [Response].
Future<Response> deleteAllSessionsWithHttpInfo() async {
// ignore: prefer_const_declarations
final path = r'/sessions';
// ignore: prefer_final_locals
Object? postBody;
final queryParams = <QueryParam>[];
final headerParams = <String, String>{};
final formParams = <String, String>{};
const contentTypes = <String>[];
return apiClient.invokeAPI(
path,
'DELETE',
queryParams,
postBody,
headerParams,
formParams,
contentTypes.isEmpty ? null : contentTypes.first,
);
}
Future<void> deleteAllSessions() async {
final response = await deleteAllSessionsWithHttpInfo();
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
}
/// Performs an HTTP 'DELETE /sessions/{id}' operation and returns the [Response].
/// Parameters:
///
/// * [String] id (required):
Future<Response> deleteSessionWithHttpInfo(String id,) async {
// ignore: prefer_const_declarations
final path = r'/sessions/{id}'
.replaceAll('{id}', id);
// ignore: prefer_final_locals
Object? postBody;
final queryParams = <QueryParam>[];
final headerParams = <String, String>{};
final formParams = <String, String>{};
const contentTypes = <String>[];
return apiClient.invokeAPI(
path,
'DELETE',
queryParams,
postBody,
headerParams,
formParams,
contentTypes.isEmpty ? null : contentTypes.first,
);
}
/// Parameters:
///
/// * [String] id (required):
Future<void> deleteSession(String id,) async {
final response = await deleteSessionWithHttpInfo(id,);
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
}
/// Performs an HTTP 'GET /sessions' operation and returns the [Response].
Future<Response> getSessionsWithHttpInfo() async {
// ignore: prefer_const_declarations
final path = r'/sessions';
// 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<List<SessionResponseDto>?> getSessions() async {
final response = await getSessionsWithHttpInfo();
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<SessionResponseDto>') as List)
.cast<SessionResponseDto>()
.toList(growable: false);
}
return null;
}
}

View File

@@ -1,139 +0,0 @@
//
// 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));
}
}
}

View File

@@ -198,8 +198,6 @@ class ApiClient {
return ActivityStatisticsResponseDto.fromJson(value);
case 'AddUsersDto':
return AddUsersDto.fromJson(value);
case 'AdminOnboardingUpdateDto':
return AdminOnboardingUpdateDto.fromJson(value);
case 'AlbumCountResponseDto':
return AlbumCountResponseDto.fromJson(value);
case 'AlbumResponseDto':
@@ -250,6 +248,8 @@ class ApiClient {
return AudioCodecTypeTransformer().decode(value);
case 'AuditDeletesResponseDto':
return AuditDeletesResponseDto.fromJson(value);
case 'AuthDeviceResponseDto':
return AuthDeviceResponseDto.fromJson(value);
case 'BulkIdResponseDto':
return BulkIdResponseDto.fromJson(value);
case 'BulkIdsDto':
@@ -394,8 +394,6 @@ class ApiClient {
return ReactionTypeTypeTransformer().decode(value);
case 'RecognitionConfig':
return RecognitionConfig.fromJson(value);
case 'ReverseGeocodingStateResponseDto':
return ReverseGeocodingStateResponseDto.fromJson(value);
case 'ScanLibraryDto':
return ScanLibraryDto.fromJson(value);
case 'SearchAlbumResponseDto':
@@ -430,8 +428,6 @@ class ApiClient {
return ServerThemeDto.fromJson(value);
case 'ServerVersionResponseDto':
return ServerVersionResponseDto.fromJson(value);
case 'SessionResponseDto':
return SessionResponseDto.fromJson(value);
case 'SharedLinkCreateDto':
return SharedLinkCreateDto.fromJson(value);
case 'SharedLinkEditDto':

View File

@@ -1,98 +0,0 @@
//
// 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',
};
}

View File

@@ -10,9 +10,9 @@
part of openapi.api;
class SessionResponseDto {
/// Returns a new [SessionResponseDto] instance.
SessionResponseDto({
class AuthDeviceResponseDto {
/// Returns a new [AuthDeviceResponseDto] instance.
AuthDeviceResponseDto({
required this.createdAt,
required this.current,
required this.deviceOS,
@@ -34,7 +34,7 @@ class SessionResponseDto {
String updatedAt;
@override
bool operator ==(Object other) => identical(this, other) || other is SessionResponseDto &&
bool operator ==(Object other) => identical(this, other) || other is AuthDeviceResponseDto &&
other.createdAt == createdAt &&
other.current == current &&
other.deviceOS == deviceOS &&
@@ -53,7 +53,7 @@ class SessionResponseDto {
(updatedAt.hashCode);
@override
String toString() => 'SessionResponseDto[createdAt=$createdAt, current=$current, deviceOS=$deviceOS, deviceType=$deviceType, id=$id, updatedAt=$updatedAt]';
String toString() => 'AuthDeviceResponseDto[createdAt=$createdAt, current=$current, deviceOS=$deviceOS, deviceType=$deviceType, id=$id, updatedAt=$updatedAt]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
@@ -66,14 +66,14 @@ class SessionResponseDto {
return json;
}
/// Returns a new [SessionResponseDto] instance and imports its values from
/// Returns a new [AuthDeviceResponseDto] instance and imports its values from
/// [value] if it's a [Map], null otherwise.
// ignore: prefer_constructors_over_static_methods
static SessionResponseDto? fromJson(dynamic value) {
static AuthDeviceResponseDto? fromJson(dynamic value) {
if (value is Map) {
final json = value.cast<String, dynamic>();
return SessionResponseDto(
return AuthDeviceResponseDto(
createdAt: mapValueOfType<String>(json, r'createdAt')!,
current: mapValueOfType<bool>(json, r'current')!,
deviceOS: mapValueOfType<String>(json, r'deviceOS')!,
@@ -85,11 +85,11 @@ class SessionResponseDto {
return null;
}
static List<SessionResponseDto> listFromJson(dynamic json, {bool growable = false,}) {
final result = <SessionResponseDto>[];
static List<AuthDeviceResponseDto> listFromJson(dynamic json, {bool growable = false,}) {
final result = <AuthDeviceResponseDto>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = SessionResponseDto.fromJson(row);
final value = AuthDeviceResponseDto.fromJson(row);
if (value != null) {
result.add(value);
}
@@ -98,12 +98,12 @@ class SessionResponseDto {
return result.toList(growable: growable);
}
static Map<String, SessionResponseDto> mapFromJson(dynamic json) {
final map = <String, SessionResponseDto>{};
static Map<String, AuthDeviceResponseDto> mapFromJson(dynamic json) {
final map = <String, AuthDeviceResponseDto>{};
if (json is Map && json.isNotEmpty) {
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
for (final entry in json.entries) {
final value = SessionResponseDto.fromJson(entry.value);
final value = AuthDeviceResponseDto.fromJson(entry.value);
if (value != null) {
map[entry.key] = value;
}
@@ -112,14 +112,14 @@ class SessionResponseDto {
return map;
}
// maps a json object with a list of SessionResponseDto-objects as value to a dart map
static Map<String, List<SessionResponseDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
final map = <String, List<SessionResponseDto>>{};
// maps a json object with a list of AuthDeviceResponseDto-objects as value to a dart map
static Map<String, List<AuthDeviceResponseDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
final map = <String, List<AuthDeviceResponseDto>>{};
if (json is Map && json.isNotEmpty) {
// ignore: parameter_assignments
json = json.cast<String, dynamic>();
for (final entry in json.entries) {
map[entry.key] = SessionResponseDto.listFromJson(entry.value, growable: growable,);
map[entry.key] = AuthDeviceResponseDto.listFromJson(entry.value, growable: growable,);
}
}
return map;

View File

@@ -1,114 +0,0 @@
//
// 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',
};
}

View File

@@ -14,7 +14,6 @@ class SystemConfigImageDto {
/// Returns a new [SystemConfigImageDto] instance.
SystemConfigImageDto({
required this.colorspace,
required this.extractEmbedded,
required this.previewFormat,
required this.previewSize,
required this.quality,
@@ -24,8 +23,6 @@ class SystemConfigImageDto {
Colorspace colorspace;
bool extractEmbedded;
ImageFormat previewFormat;
int previewSize;
@@ -39,7 +36,6 @@ class SystemConfigImageDto {
@override
bool operator ==(Object other) => identical(this, other) || other is SystemConfigImageDto &&
other.colorspace == colorspace &&
other.extractEmbedded == extractEmbedded &&
other.previewFormat == previewFormat &&
other.previewSize == previewSize &&
other.quality == quality &&
@@ -50,7 +46,6 @@ class SystemConfigImageDto {
int get hashCode =>
// ignore: unnecessary_parenthesis
(colorspace.hashCode) +
(extractEmbedded.hashCode) +
(previewFormat.hashCode) +
(previewSize.hashCode) +
(quality.hashCode) +
@@ -58,12 +53,11 @@ class SystemConfigImageDto {
(thumbnailSize.hashCode);
@override
String toString() => 'SystemConfigImageDto[colorspace=$colorspace, extractEmbedded=$extractEmbedded, previewFormat=$previewFormat, previewSize=$previewSize, quality=$quality, thumbnailFormat=$thumbnailFormat, thumbnailSize=$thumbnailSize]';
String toString() => 'SystemConfigImageDto[colorspace=$colorspace, previewFormat=$previewFormat, previewSize=$previewSize, quality=$quality, thumbnailFormat=$thumbnailFormat, thumbnailSize=$thumbnailSize]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
json[r'colorspace'] = this.colorspace;
json[r'extractEmbedded'] = this.extractEmbedded;
json[r'previewFormat'] = this.previewFormat;
json[r'previewSize'] = this.previewSize;
json[r'quality'] = this.quality;
@@ -81,7 +75,6 @@ class SystemConfigImageDto {
return SystemConfigImageDto(
colorspace: Colorspace.fromJson(json[r'colorspace'])!,
extractEmbedded: mapValueOfType<bool>(json, r'extractEmbedded')!,
previewFormat: ImageFormat.fromJson(json[r'previewFormat'])!,
previewSize: mapValueOfType<int>(json, r'previewSize')!,
quality: mapValueOfType<int>(json, r'quality')!,
@@ -135,7 +128,6 @@ class SystemConfigImageDto {
/// The list of required keys that must be present in a JSON.
static const requiredKeys = <String>{
'colorspace',
'extractEmbedded',
'previewFormat',
'previewSize',
'quality',

View File

@@ -1,27 +0,0 @@
//
// 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
});
});
}

View File

@@ -17,10 +17,25 @@ void main() {
// final instance = 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
test('test getAuditDeletes', () async {
// TODO
});
//Future<FileReportDto> getAuditFiles() async
test('test getAuditFiles', () async {
// TODO
});
//Future<List<FileChecksumResponseDto>> getFileChecksums(FileChecksumDto fileChecksumDto) async
test('test getFileChecksums', () async {
// TODO
});
});
}

View File

@@ -11,11 +11,11 @@
import 'package:openapi/api.dart';
import 'package:test/test.dart';
// tests for SessionResponseDto
// tests for AuthDeviceResponseDto
void main() {
// final instance = SessionResponseDto();
// final instance = AuthDeviceResponseDto();
group('test SessionResponseDto', () {
group('test AuthDeviceResponseDto', () {
// String createdAt
test('to test the property `createdAt`', () async {
// TODO

View File

@@ -22,6 +22,11 @@ void main() {
// TODO
});
//Future<List<AuthDeviceResponseDto>> getAuthDevices() async
test('test getAuthDevices', () async {
// TODO
});
//Future<LoginResponseDto> login(LoginCredentialDto loginCredentialDto) async
test('test login', () async {
// TODO
@@ -32,6 +37,16 @@ void main() {
// TODO
});
//Future logoutAuthDevice(String id) async
test('test logoutAuthDevice', () async {
// TODO
});
//Future logoutAuthDevices() async
test('test logoutAuthDevices', () async {
// TODO
});
//Future<UserResponseDto> signUpAdmin(SignUpDto signUpDto) async
test('test signUpAdmin', () async {
// TODO

View File

@@ -1,36 +0,0 @@
//
// 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
});
});
}

View File

@@ -1,32 +0,0 @@
//
// 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
});
});
}

View File

@@ -57,5 +57,10 @@ void main() {
// TODO
});
//Future setAdminOnboarding() async
test('test setAdminOnboarding', () async {
// TODO
});
});
}

View File

@@ -1,36 +0,0 @@
//
// 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 SessionsApi
void main() {
// final instance = SessionsApi();
group('tests for SessionsApi', () {
//Future deleteAllSessions() async
test('test deleteAllSessions', () async {
// TODO
});
//Future deleteSession(String id) async
test('test deleteSession', () async {
// TODO
});
//Future<List<SessionResponseDto>> getSessions() async
test('test getSessions', () async {
// TODO
});
});
}

View File

@@ -21,11 +21,6 @@ void main() {
// TODO
});
// bool extractEmbedded
test('to test the property `extractEmbedded`', () async {
// TODO
});
// ImageFormat previewFormat
test('to test the property `previewFormat`', () async {
// TODO

View File

@@ -1,36 +0,0 @@
//
// 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
});
});
}

View File

@@ -2,7 +2,7 @@ name: immich_mobile
description: Immich - selfhosted backup media file on mobile phone
publish_to: 'none'
version: 1.102.1+133
version: 1.101.0+131
environment:
sdk: '>=3.0.0 <4.0.0'
@@ -105,6 +105,9 @@ flutter:
- assets/
- assets/i18n/
fonts:
- family: SnowburstOne
fonts:
- asset: fonts/SnowburstOne.ttf
- family: Inconsolata
fonts:
- asset: fonts/Inconsolata-Regular.ttf

View File

@@ -2345,6 +2345,118 @@
]
}
},
"/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": {
"post": {
"operationId": "signUpAdmin",
@@ -2418,6 +2530,99 @@
]
}
},
"/auth/devices": {
"delete": {
"operationId": "logoutAuthDevices",
"parameters": [],
"responses": {
"204": {
"description": ""
}
},
"security": [
{
"bearer": []
},
{
"cookie": []
},
{
"api_key": []
}
],
"tags": [
"Authentication"
]
},
"get": {
"operationId": "getAuthDevices",
"parameters": [],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"items": {
"$ref": "#/components/schemas/AuthDeviceResponseDto"
},
"type": "array"
}
}
},
"description": ""
}
},
"security": [
{
"bearer": []
},
{
"cookie": []
},
{
"api_key": []
}
],
"tags": [
"Authentication"
]
}
},
"/auth/devices/{id}": {
"delete": {
"operationId": "logoutAuthDevice",
"parameters": [
{
"name": "id",
"required": true,
"in": "path",
"schema": {
"format": "uuid",
"type": "string"
}
}
],
"responses": {
"204": {
"description": ""
}
},
"security": [
{
"bearer": []
},
{
"cookie": []
},
{
"api_key": []
}
],
"tags": [
"Authentication"
]
}
},
"/auth/login": {
"post": {
"operationId": "login",
@@ -4317,118 +4522,6 @@
]
}
},
"/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": {
"get": {
"deprecated": true,
@@ -4908,6 +5001,31 @@
]
}
},
"/server-info/admin-onboarding": {
"post": {
"operationId": "setAdminOnboarding",
"parameters": [],
"responses": {
"204": {
"description": ""
}
},
"security": [
{
"bearer": []
},
{
"cookie": []
},
{
"api_key": []
}
],
"tags": [
"Server Info"
]
}
},
"/server-info/config": {
"get": {
"operationId": "getServerConfig",
@@ -5066,99 +5184,6 @@
]
}
},
"/sessions": {
"delete": {
"operationId": "deleteAllSessions",
"parameters": [],
"responses": {
"204": {
"description": ""
}
},
"security": [
{
"bearer": []
},
{
"cookie": []
},
{
"api_key": []
}
],
"tags": [
"Sessions"
]
},
"get": {
"operationId": "getSessions",
"parameters": [],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"items": {
"$ref": "#/components/schemas/SessionResponseDto"
},
"type": "array"
}
}
},
"description": ""
}
},
"security": [
{
"bearer": []
},
{
"cookie": []
},
{
"api_key": []
}
],
"tags": [
"Sessions"
]
}
},
"/sessions/{id}": {
"delete": {
"operationId": "deleteSession",
"parameters": [
{
"name": "id",
"required": true,
"in": "path",
"schema": {
"format": "uuid",
"type": "string"
}
}
],
"responses": {
"204": {
"description": ""
}
},
"security": [
{
"bearer": []
},
{
"cookie": []
},
{
"api_key": []
}
],
"tags": [
"Sessions"
]
}
},
"/shared-link": {
"get": {
"operationId": "getAllSharedLinks",
@@ -5860,103 +5885,6 @@
]
}
},
"/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": {
"get": {
"operationId": "getAllTags",
@@ -7078,7 +7006,7 @@
"info": {
"title": "Immich",
"description": "Immich API",
"version": "1.102.1",
"version": "1.101.0",
"contact": {}
},
"tags": [],
@@ -7252,17 +7180,6 @@
],
"type": "object"
},
"AdminOnboardingUpdateDto": {
"properties": {
"isOnboarded": {
"type": "boolean"
}
},
"required": [
"isOnboarded"
],
"type": "object"
},
"AlbumCountResponseDto": {
"properties": {
"notShared": {
@@ -7975,6 +7892,37 @@
],
"type": "object"
},
"AuthDeviceResponseDto": {
"properties": {
"createdAt": {
"type": "string"
},
"current": {
"type": "boolean"
},
"deviceOS": {
"type": "string"
},
"deviceType": {
"type": "string"
},
"id": {
"type": "string"
},
"updatedAt": {
"type": "string"
}
},
"required": [
"createdAt",
"current",
"deviceOS",
"deviceType",
"id",
"updatedAt"
],
"type": "object"
},
"BulkIdResponseDto": {
"properties": {
"error": {
@@ -9701,23 +9649,6 @@
],
"type": "object"
},
"ReverseGeocodingStateResponseDto": {
"properties": {
"lastImportFileName": {
"nullable": true,
"type": "string"
},
"lastUpdate": {
"nullable": true,
"type": "string"
}
},
"required": [
"lastImportFileName",
"lastUpdate"
],
"type": "object"
},
"ScanLibraryDto": {
"properties": {
"refreshAllFiles": {
@@ -10118,37 +10049,6 @@
],
"type": "object"
},
"SessionResponseDto": {
"properties": {
"createdAt": {
"type": "string"
},
"current": {
"type": "boolean"
},
"deviceOS": {
"type": "string"
},
"deviceType": {
"type": "string"
},
"id": {
"type": "string"
},
"updatedAt": {
"type": "string"
}
},
"required": [
"createdAt",
"current",
"deviceOS",
"deviceType",
"id",
"updatedAt"
],
"type": "object"
},
"SharedLinkCreateDto": {
"properties": {
"albumId": {
@@ -10631,9 +10531,6 @@
"colorspace": {
"$ref": "#/components/schemas/Colorspace"
},
"extractEmbedded": {
"type": "boolean"
},
"previewFormat": {
"$ref": "#/components/schemas/ImageFormat"
},
@@ -10652,7 +10549,6 @@
},
"required": [
"colorspace",
"extractEmbedded",
"previewFormat",
"previewSize",
"quality",

View File

@@ -1,12 +1,12 @@
{
"name": "@immich/sdk",
"version": "1.102.1",
"version": "1.101.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@immich/sdk",
"version": "1.102.1",
"version": "1.101.0",
"license": "GNU Affero General Public License version 3",
"dependencies": {
"@oazapfts/runtime": "^1.0.2"

View File

@@ -1,6 +1,6 @@
{
"name": "@immich/sdk",
"version": "1.102.1",
"version": "1.101.0",
"description": "Auto-generated TypeScript SDK for the Immich API",
"type": "module",
"main": "./build/index.js",

View File

@@ -1,6 +1,6 @@
/**
* Immich
* 1.102.1
* 1.101.0
* DO NOT MODIFY - This file has been generated using oazapfts.
* See https://www.npmjs.com/package/oazapfts
*/
@@ -316,6 +316,27 @@ export type AuditDeletesResponseDto = {
ids: string[];
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 = {
email: string;
name: string;
@@ -325,6 +346,14 @@ export type ChangePasswordDto = {
newPassword: string;
password: string;
};
export type AuthDeviceResponseDto = {
createdAt: string;
current: boolean;
deviceOS: string;
deviceType: string;
id: string;
updatedAt: string;
};
export type LoginCredentialDto = {
email: string;
password: string;
@@ -578,27 +607,6 @@ export type AssetFaceUpdateDto = {
export type PersonStatisticsResponseDto = {
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 = {
count: number;
value: string;
@@ -783,14 +791,6 @@ export type ServerVersionResponseDto = {
minor: number;
patch: number;
};
export type SessionResponseDto = {
createdAt: string;
current: boolean;
deviceOS: string;
deviceType: string;
id: string;
updatedAt: string;
};
export type SharedLinkResponseDto = {
album?: AlbumResponseDto;
allowDownload: boolean;
@@ -864,7 +864,6 @@ export type SystemConfigFFmpegDto = {
};
export type SystemConfigImageDto = {
colorspace: Colorspace;
extractEmbedded: boolean;
previewFormat: ImageFormat;
previewSize: number;
quality: number;
@@ -998,13 +997,6 @@ export type SystemConfigTemplateStorageOptionDto = {
weekOptions: string[];
yearOptions: string[];
};
export type AdminOnboardingUpdateDto = {
isOnboarded: boolean;
};
export type ReverseGeocodingStateResponseDto = {
lastImportFileName: string | null;
lastUpdate: string | null;
};
export type CreateTagDto = {
name: string;
"type": TagTypeEnum;
@@ -1658,6 +1650,35 @@ export function getAuditDeletes({ after, entityType, userId }: {
...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 }: {
signUpDto: SignUpDto;
}, opts?: Oazapfts.RequestOpts) {
@@ -1682,6 +1703,28 @@ export function changePassword({ changePasswordDto }: {
body: changePasswordDto
})));
}
export function logoutAuthDevices(opts?: Oazapfts.RequestOpts) {
return oazapfts.ok(oazapfts.fetchText("/auth/devices", {
...opts,
method: "DELETE"
}));
}
export function getAuthDevices(opts?: Oazapfts.RequestOpts) {
return oazapfts.ok(oazapfts.fetchJson<{
status: 200;
data: AuthDeviceResponseDto[];
}>("/auth/devices", {
...opts
}));
}
export function logoutAuthDevice({ id }: {
id: string;
}, opts?: Oazapfts.RequestOpts) {
return oazapfts.ok(oazapfts.fetchText(`/auth/devices/${encodeURIComponent(id)}`, {
...opts,
method: "DELETE"
}));
}
export function login({ loginCredentialDto }: {
loginCredentialDto: LoginCredentialDto;
}, opts?: Oazapfts.RequestOpts) {
@@ -2184,35 +2227,6 @@ export function getPersonThumbnail({ id }: {
...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 }: {
clip?: boolean;
motion?: boolean;
@@ -2337,6 +2351,12 @@ export function getServerInfo(opts?: Oazapfts.RequestOpts) {
...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) {
return oazapfts.ok(oazapfts.fetchJson<{
status: 200;
@@ -2393,28 +2413,6 @@ export function getServerVersion(opts?: Oazapfts.RequestOpts) {
...opts
}));
}
export function deleteAllSessions(opts?: Oazapfts.RequestOpts) {
return oazapfts.ok(oazapfts.fetchText("/sessions", {
...opts,
method: "DELETE"
}));
}
export function getSessions(opts?: Oazapfts.RequestOpts) {
return oazapfts.ok(oazapfts.fetchJson<{
status: 200;
data: SessionResponseDto[];
}>("/sessions", {
...opts
}));
}
export function deleteSession({ id }: {
id: string;
}, opts?: Oazapfts.RequestOpts) {
return oazapfts.ok(oazapfts.fetchText(`/sessions/${encodeURIComponent(id)}`, {
...opts,
method: "DELETE"
}));
}
export function getAllSharedLinks(opts?: Oazapfts.RequestOpts) {
return oazapfts.ok(oazapfts.fetchJson<{
status: 200;
@@ -2598,31 +2596,6 @@ export function getStorageTemplateOptions(opts?: Oazapfts.RequestOpts) {
...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) {
return oazapfts.ok(oazapfts.fetchJson<{
status: 200;
@@ -2974,6 +2947,20 @@ export enum EntityType {
Asset = "ASSET",
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 {
ThumbnailGeneration = "thumbnailGeneration",
MetadataExtraction = "metadataExtraction",
@@ -3005,20 +2992,6 @@ export enum Type2 {
export enum MemoryType {
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 {
Country = "country",
State = "state",

View File

@@ -1,5 +1,5 @@
# dev build
FROM ghcr.io/immich-app/base-server-dev:20240416@sha256:ff2aadf54298e8ceca94031c6fed143236d8d82640fbbf422e0a9d2978e45923 as dev
FROM ghcr.io/immich-app/base-server-dev:20240326@sha256:d945aba864051b30888617f36446f86b72c4bc7ad6476b9dd2aaa0c4c4e3c945 as dev
RUN apt-get install --no-install-recommends -yqq tini
WORKDIR /usr/src/app
@@ -25,7 +25,7 @@ COPY --from=dev /usr/src/app/node_modules/@img ./node_modules/@img
COPY --from=dev /usr/src/app/node_modules/exiftool-vendored.pl ./node_modules/exiftool-vendored.pl
# web build
FROM node:iron-alpine3.18@sha256:d328c7bc3305e1ab26491817936c8151a47a8861ad617c16c1eeaa9c8075c8f6 as web
FROM node:iron-alpine3.18@sha256:3fb85a68652064ab109ed9730f45a3ede11f064afdd3ad9f96ef7e8a3c55f47e as web
WORKDIR /usr/src/open-api/typescript-sdk
COPY open-api/typescript-sdk/package*.json open-api/typescript-sdk/tsconfig*.json ./
@@ -41,7 +41,7 @@ RUN npm run build
# prod build
FROM ghcr.io/immich-app/base-server-prod:20240416@sha256:138f4d6fb74b282256583070339eaba6f39fcffa3569ae05b6823d5c37098242
FROM ghcr.io/immich-app/base-server-prod:20240326@sha256:28ad98fed8d746b5f92de49ff776cfdff7399df163ebeda2f37a01f473965841
WORKDIR /usr/src/app
ENV NODE_ENV=production \

View File

@@ -1,12 +1,12 @@
{
"name": "immich",
"version": "1.102.1",
"version": "1.101.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "immich",
"version": "1.102.1",
"version": "1.101.0",
"license": "GNU Affero General Public License version 3",
"dependencies": {
"@nestjs/bullmq": "^10.0.1",

View File

@@ -1,6 +1,6 @@
{
"name": "immich",
"version": "1.102.1",
"version": "1.101.0",
"description": "",
"author": "",
"private": true,

View File

@@ -1,4 +1,5 @@
import { Command, CommandRunner } from 'nest-commander';
import { UserEntity } from 'src/entities/user.entity';
import { UserService } from 'src/services/user.service';
@Command({
@@ -12,7 +13,16 @@ export class ListUsersCommand extends CommandRunner {
async run(): Promise<void> {
try {
const users = await this.userService.listUsers();
const users = await this.userService.getAll(
{
user: {
id: 'cli',
email: 'cli@immich.app',
isAdmin: true,
} as UserEntity,
},
true,
);
console.dir(users);
} catch (error) {
console.error(error);

View File

@@ -26,7 +26,12 @@ export const geodataCities500Path = join(GEODATA_ROOT_PATH, citiesFile);
export const MOBILE_REDIRECT = 'app.immich:/';
export const LOGIN_URL = '/auth/login?autoLaunch=0';
export const IMMICH_ACCESS_COOKIE = 'immich_access_token';
export const IMMICH_IS_AUTHENTICATED = 'immich_is_authenticated';
export const IMMICH_AUTH_TYPE_COOKIE = 'immich_auth_type';
export const IMMICH_API_KEY_NAME = 'api_key';
export const IMMICH_API_KEY_HEADER = 'x-api-key';
export const IMMICH_SHARED_LINK_ACCESS_COOKIE = 'immich_shared_link_token';
export enum AuthType {
PASSWORD = 'password',
OAUTH = 'oauth',

View File

@@ -1,8 +1,15 @@
import { Controller, Get, Query } from '@nestjs/common';
import { Body, Controller, Get, Post, Query } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { AuditDeletesDto, AuditDeletesResponseDto } from 'src/dtos/audit.dto';
import {
AuditDeletesDto,
AuditDeletesResponseDto,
FileChecksumDto,
FileChecksumResponseDto,
FileReportDto,
FileReportFixDto,
} from 'src/dtos/audit.dto';
import { AuthDto } from 'src/dtos/auth.dto';
import { Auth, Authenticated } from 'src/middleware/auth.guard';
import { AdminRoute, Auth, Authenticated } from 'src/middleware/auth.guard';
import { AuditService } from 'src/services/audit.service';
@ApiTags('Audit')
@@ -15,4 +22,22 @@ export class AuditController {
getAuditDeletes(@Auth() auth: AuthDto, @Query() dto: AuditDeletesDto): Promise<AuditDeletesResponseDto> {
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);
}
}

View File

@@ -1,11 +1,11 @@
import { Body, Controller, HttpCode, HttpStatus, Post, Req, Res } from '@nestjs/common';
import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Post, Req, Res } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { Request, Response } from 'express';
import { AuthType } from 'src/constants';
import { IMMICH_ACCESS_COOKIE, IMMICH_AUTH_TYPE_COOKIE, IMMICH_IS_AUTHENTICATED } from 'src/constants';
import {
AuthDeviceResponseDto,
AuthDto,
ChangePasswordDto,
ImmichCookie,
LoginCredentialDto,
LoginResponseDto,
LogoutResponseDto,
@@ -15,7 +15,7 @@ import {
import { UserResponseDto, mapUser } from 'src/dtos/user.dto';
import { Auth, Authenticated, GetLoginDetails, PublicRoute } from 'src/middleware/auth.guard';
import { AuthService, LoginDetails } from 'src/services/auth.service';
import { respondWithCookie, respondWithoutCookie } from 'src/utils/response';
import { UUIDParamDto } from 'src/validation';
@ApiTags('Authentication')
@Controller('auth')
@@ -30,15 +30,9 @@ export class AuthController {
@Res({ passthrough: true }) res: Response,
@GetLoginDetails() loginDetails: LoginDetails,
): Promise<LoginResponseDto> {
const body = await this.service.login(loginCredential, loginDetails);
return respondWithCookie(res, body, {
isSecure: loginDetails.isSecure,
values: [
{ key: ImmichCookie.ACCESS_TOKEN, value: body.accessToken },
{ key: ImmichCookie.AUTH_TYPE, value: AuthType.PASSWORD },
{ key: ImmichCookie.IS_AUTHENTICATED, value: 'true' },
],
});
const { response, cookie } = await this.service.login(loginCredential, loginDetails);
res.header('Set-Cookie', cookie);
return response;
}
@PublicRoute()
@@ -47,6 +41,23 @@ export class AuthController {
return this.service.adminSignUp(dto);
}
@Get('devices')
getAuthDevices(@Auth() auth: AuthDto): Promise<AuthDeviceResponseDto[]> {
return this.service.getDevices(auth);
}
@Delete('devices')
@HttpCode(HttpStatus.NO_CONTENT)
logoutAuthDevices(@Auth() auth: AuthDto): Promise<void> {
return this.service.logoutDevices(auth);
}
@Delete('devices/:id')
@HttpCode(HttpStatus.NO_CONTENT)
logoutAuthDevice(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<void> {
return this.service.logoutDevice(auth, id);
}
@Post('validateToken')
@HttpCode(HttpStatus.OK)
validateAccessToken(): ValidateAccessTokenResponseDto {
@@ -61,18 +72,15 @@ export class AuthController {
@Post('logout')
@HttpCode(HttpStatus.OK)
async logout(
logout(
@Req() request: Request,
@Res({ passthrough: true }) res: Response,
@Auth() auth: AuthDto,
): Promise<LogoutResponseDto> {
const authType = (request.cookies || {})[ImmichCookie.AUTH_TYPE];
res.clearCookie(IMMICH_ACCESS_COOKIE);
res.clearCookie(IMMICH_AUTH_TYPE_COOKIE);
res.clearCookie(IMMICH_IS_AUTHENTICATED);
const body = await this.service.logout(auth, authType);
return respondWithoutCookie(res, body, [
ImmichCookie.ACCESS_TOKEN,
ImmichCookie.AUTH_TYPE,
ImmichCookie.IS_AUTHENTICATED,
]);
return this.service.logout(auth, (request.cookies || {})[IMMICH_AUTH_TYPE_COOKIE]);
}
}

View File

@@ -1,30 +0,0 @@
import { Body, Controller, Get, Post } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { FileChecksumDto, FileChecksumResponseDto, FileReportDto, FileReportFixDto } from 'src/dtos/audit.dto';
import { AdminRoute, Authenticated } from 'src/middleware/auth.guard';
import { AuditService } from 'src/services/audit.service';
@ApiTags('File Report')
@Controller('report')
@Authenticated()
export class ReportController {
constructor(private service: AuditService) {}
@AdminRoute()
@Get()
getAuditFiles(): Promise<FileReportDto> {
return this.service.getFileReport();
}
@AdminRoute()
@Post('/checksum')
getFileChecksums(@Body() dto: FileChecksumDto): Promise<FileChecksumResponseDto[]> {
return this.service.getChecksums(dto);
}
@AdminRoute()
@Post('/fix')
fixAuditFiles(@Body() dto: FileReportFixDto): Promise<void> {
return this.service.fixItems(dto.items);
}
}

View File

@@ -8,33 +8,31 @@ import { AuditController } from 'src/controllers/audit.controller';
import { AuthController } from 'src/controllers/auth.controller';
import { DownloadController } from 'src/controllers/download.controller';
import { FaceController } from 'src/controllers/face.controller';
import { ReportController } from 'src/controllers/file-report.controller';
import { JobController } from 'src/controllers/job.controller';
import { LibraryController } from 'src/controllers/library.controller';
import { MemoryController } from 'src/controllers/memory.controller';
import { OAuthController } from 'src/controllers/oauth.controller';
import { PartnerController } from 'src/controllers/partner.controller';
import { PersonController } from 'src/controllers/person.controller';
import { PluginController } from 'src/controllers/plugin.controller';
import { SearchController } from 'src/controllers/search.controller';
import { ServerInfoController } from 'src/controllers/server-info.controller';
import { SessionController } from 'src/controllers/session.controller';
import { SharedLinkController } from 'src/controllers/shared-link.controller';
import { SyncController } from 'src/controllers/sync.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 { TimelineController } from 'src/controllers/timeline.controller';
import { TrashController } from 'src/controllers/trash.controller';
import { UserController } from 'src/controllers/user.controller';
export const controllers = [
APIKeyController,
ActivityController,
AlbumController,
AppController,
AssetController,
AssetControllerV1,
AssetsController,
AssetControllerV1,
AssetController,
AppController,
AlbumController,
APIKeyController,
AuditController,
AuthController,
DownloadController,
@@ -44,17 +42,15 @@ export const controllers = [
MemoryController,
OAuthController,
PartnerController,
PersonController,
ReportController,
PluginController,
SearchController,
ServerInfoController,
SessionController,
SharedLinkController,
SyncController,
SystemConfigController,
SystemMetadataController,
TagController,
TimelineController,
TrashController,
UserController,
PersonController,
];

View File

@@ -1,10 +1,8 @@
import { Body, Controller, Get, HttpStatus, Post, Redirect, Req, Res } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { Request, Response } from 'express';
import { AuthType } from 'src/constants';
import {
AuthDto,
ImmichCookie,
LoginResponseDto,
OAuthAuthorizeResponseDto,
OAuthCallbackDto,
@@ -13,7 +11,6 @@ import {
import { UserResponseDto } from 'src/dtos/user.dto';
import { Auth, Authenticated, GetLoginDetails, PublicRoute } from 'src/middleware/auth.guard';
import { AuthService, LoginDetails } from 'src/services/auth.service';
import { respondWithCookie } from 'src/utils/response';
@ApiTags('OAuth')
@Controller('oauth')
@@ -44,15 +41,9 @@ export class OAuthController {
@Body() dto: OAuthCallbackDto,
@GetLoginDetails() loginDetails: LoginDetails,
): Promise<LoginResponseDto> {
const body = await this.service.callback(dto, loginDetails);
return respondWithCookie(res, body, {
isSecure: loginDetails.isSecure,
values: [
{ key: ImmichCookie.ACCESS_TOKEN, value: body.accessToken },
{ key: ImmichCookie.AUTH_TYPE, value: AuthType.OAUTH },
{ key: ImmichCookie.IS_AUTHENTICATED, value: 'true' },
],
});
const { response, cookie } = await this.service.callback(dto, loginDetails);
res.header('Set-Cookie', cookie);
return response;
}
@Post('link')

View File

@@ -0,0 +1,49 @@
import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Post, Put, Query } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { AuthDto } from 'src/dtos/auth.dto';
import { PluginImportDto, PluginResponseDto, PluginUpdateDto, SearchPluginDto } from 'src/dtos/plugin.dto';
import { Auth, Authenticated } from 'src/middleware/auth.guard';
import { PluginService } from 'src/services/plugin.service';
import { UUIDParamDto } from 'src/validation';
@ApiTags('Plugin')
@Controller('plugins')
@Authenticated()
export class PluginController {
constructor(private service: PluginService) {}
@Get()
searchPlugins(@Auth() auth: AuthDto, @Query() dto: SearchPluginDto): Promise<PluginResponseDto[]> {
return this.service.search(auth, dto);
}
@Post()
importPlugin(@Auth() auth: AuthDto, @Body() dto: PluginImportDto): Promise<PluginResponseDto> {
return this.service.import(auth, dto);
}
@Put(':id')
updatePlugin(
@Auth() auth: AuthDto,
@Param() { id }: UUIDParamDto,
@Body() dto: PluginUpdateDto,
): Promise<PluginResponseDto> {
return this.service.update(auth, id, dto);
}
@Post(':id/install')
installPlugin(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<PluginResponseDto> {
return this.service.install(auth, id);
}
@Post(':id/uninstall')
uninstallPlugin(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<PluginResponseDto> {
return this.service.uninstall(auth, id);
}
@Delete(':id')
@HttpCode(HttpStatus.NO_CONTENT)
deletePlugin(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<void> {
return this.service.delete(auth, id);
}
}

View File

@@ -1,4 +1,4 @@
import { Controller, Get } from '@nestjs/common';
import { Controller, Get, HttpCode, HttpStatus, Post } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import {
ServerConfigDto,
@@ -65,4 +65,11 @@ export class ServerInfoController {
getSupportedMediaTypes(): ServerMediaTypesResponseDto {
return this.service.getSupportedMediaTypes();
}
@AdminRoute()
@Post('admin-onboarding')
@HttpCode(HttpStatus.NO_CONTENT)
setAdminOnboarding(): Promise<void> {
return this.service.setAdminOnboarding();
}
}

View File

@@ -1,31 +0,0 @@
import { Controller, Delete, Get, HttpCode, HttpStatus, Param } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { AuthDto } from 'src/dtos/auth.dto';
import { SessionResponseDto } from 'src/dtos/session.dto';
import { Auth, Authenticated } from 'src/middleware/auth.guard';
import { SessionService } from 'src/services/session.service';
import { UUIDParamDto } from 'src/validation';
@ApiTags('Sessions')
@Controller('sessions')
@Authenticated()
export class SessionController {
constructor(private service: SessionService) {}
@Get()
getSessions(@Auth() auth: AuthDto): Promise<SessionResponseDto[]> {
return this.service.getAll(auth);
}
@Delete()
@HttpCode(HttpStatus.NO_CONTENT)
deleteAllSessions(@Auth() auth: AuthDto): Promise<void> {
return this.service.deleteAll(auth);
}
@Delete(':id')
@HttpCode(HttpStatus.NO_CONTENT)
deleteSession(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<void> {
return this.service.delete(auth, id);
}
}

View File

@@ -1,19 +1,18 @@
import { Body, Controller, Delete, Get, Param, Patch, Post, Put, Query, Req, Res } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { Request, Response } from 'express';
import { IMMICH_SHARED_LINK_ACCESS_COOKIE } from 'src/constants';
import { AssetIdsResponseDto } from 'src/dtos/asset-ids.response.dto';
import { AssetIdsDto } from 'src/dtos/asset.dto';
import { AuthDto, ImmichCookie } from 'src/dtos/auth.dto';
import { AuthDto } from 'src/dtos/auth.dto';
import {
SharedLinkCreateDto,
SharedLinkEditDto,
SharedLinkPasswordDto,
SharedLinkResponseDto,
} from 'src/dtos/shared-link.dto';
import { Auth, Authenticated, GetLoginDetails, SharedLinkRoute } from 'src/middleware/auth.guard';
import { LoginDetails } from 'src/services/auth.service';
import { Auth, Authenticated, SharedLinkRoute } from 'src/middleware/auth.guard';
import { SharedLinkService } from 'src/services/shared-link.service';
import { respondWithCookie } from 'src/utils/response';
import { UUIDParamDto } from 'src/validation';
@ApiTags('Shared Link')
@@ -34,17 +33,20 @@ export class SharedLinkController {
@Query() dto: SharedLinkPasswordDto,
@Req() request: Request,
@Res({ passthrough: true }) res: Response,
@GetLoginDetails() loginDetails: LoginDetails,
): Promise<SharedLinkResponseDto> {
const sharedLinkToken = request.cookies?.[ImmichCookie.SHARED_LINK_TOKEN];
const sharedLinkToken = request.cookies?.[IMMICH_SHARED_LINK_ACCESS_COOKIE];
if (sharedLinkToken) {
dto.token = sharedLinkToken;
}
const body = await this.service.getMine(auth, dto);
return respondWithCookie(res, body, {
isSecure: loginDetails.isSecure,
values: body.token ? [{ key: ImmichCookie.SHARED_LINK_TOKEN, value: body.token }] : [],
});
const response = await this.service.getMine(auth, dto);
if (response.token) {
res.cookie(IMMICH_SHARED_LINK_ACCESS_COOKIE, response.token, {
expires: new Date(Date.now() + 1000 * 60 * 60 * 24),
httpOnly: true,
sameSite: 'lax',
});
}
return response;
}
@Get(':id')

View File

@@ -1,28 +0,0 @@
import { Body, Controller, Get, HttpCode, HttpStatus, Post } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
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')
@Authenticated({ admin: true })
export class SystemMetadataController {
constructor(private service: SystemMetadataService) {}
@Get('admin-onboarding')
getAdminOnboarding(): Promise<AdminOnboardingUpdateDto> {
return this.service.getAdminOnboarding();
}
@Post('admin-onboarding')
@HttpCode(HttpStatus.NO_CONTENT)
updateAdminOnboarding(@Body() dto: AdminOnboardingUpdateDto): Promise<void> {
return this.service.updateAdminOnboarding(dto);
}
@Get('reverse-geocoding-state')
getReverseGeocodingState(): Promise<ReverseGeocodingStateResponseDto> {
return this.service.getReverseGeocodingState();
}
}

View File

@@ -43,6 +43,13 @@ export enum Permission {
PERSON_CREATE = 'person.create',
PERSON_REASSIGN = 'person.reassign',
PLUGIN_READ = 'plugin.read',
PLUGIN_WRITE = 'plugin.write',
PLUGIN_DELETE = 'plugin.delete',
PLUGIN_ADMIN = 'plugin.admin',
PLUGIN_INSTALL = 'plugin.install',
PLUGIN_UNINSTALL = 'plugin.uninstall',
PARTNER_UPDATE = 'partner.update',
}

View File

@@ -1,4 +1,3 @@
import { randomUUID } from 'node:crypto';
import { dirname, join, resolve } from 'node:path';
import { APP_MEDIA_LOCATION } from 'src/constants';
import { SystemConfigCore } from 'src/cores/system-config.core';
@@ -309,8 +308,4 @@ export class StorageCore {
static getNestedPath(folder: StorageFolder, ownerId: string, filename: string): string {
return join(this.getNestedFolder(folder, ownerId, filename), filename);
}
static getTempPathInDir(dir: string): string {
return join(dir, `${randomUUID()}.tmp`);
}
}

View File

@@ -120,7 +120,6 @@ export const defaults = Object.freeze<SystemConfig>({
previewSize: 1440,
quality: 80,
colorspace: Colorspace.P3,
extractEmbedded: false,
},
newVersionCheck: {
enabled: true,

View File

@@ -2,35 +2,16 @@ import { ApiProperty } from '@nestjs/swagger';
import { Transform } from 'class-transformer';
import { IsEmail, IsNotEmpty, IsString, MinLength } from 'class-validator';
import { APIKeyEntity } from 'src/entities/api-key.entity';
import { SessionEntity } from 'src/entities/session.entity';
import { SharedLinkEntity } from 'src/entities/shared-link.entity';
import { UserTokenEntity } from 'src/entities/user-token.entity';
import { UserEntity } from 'src/entities/user.entity';
export enum ImmichCookie {
ACCESS_TOKEN = 'immich_access_token',
AUTH_TYPE = 'immich_auth_type',
IS_AUTHENTICATED = 'immich_is_authenticated',
SHARED_LINK_TOKEN = 'immich_shared_link_token',
}
export enum ImmichHeader {
API_KEY = 'x-api-key',
USER_TOKEN = 'x-immich-user-token',
SESSION_TOKEN = 'x-immich-session-token',
SHARED_LINK_TOKEN = 'x-immich-share-key',
}
export type CookieResponse = {
isSecure: boolean;
values: Array<{ key: ImmichCookie; value: string }>;
};
export class AuthDto {
user!: UserEntity;
apiKey?: APIKeyEntity;
sharedLink?: SharedLinkEntity;
session?: SessionEntity;
userToken?: UserTokenEntity;
}
export class LoginCredentialDto {
@@ -58,7 +39,7 @@ export class LoginResponseDto {
export function mapLoginResponse(entity: UserEntity, accessToken: string): LoginResponseDto {
return {
accessToken,
accessToken: accessToken,
userId: entity.id,
userEmail: entity.email,
name: entity.name,
@@ -97,6 +78,24 @@ export class ValidateAccessTokenResponseDto {
authStatus!: boolean;
}
export class AuthDeviceResponseDto {
id!: string;
createdAt!: string;
updatedAt!: string;
current!: boolean;
deviceType!: string;
deviceOS!: string;
}
export const mapUserToken = (entity: UserTokenEntity, currentId?: string): AuthDeviceResponseDto => ({
id: entity.id,
createdAt: entity.createdAt.toISOString(),
updatedAt: entity.updatedAt.toISOString(),
current: currentId === entity.id,
deviceOS: entity.deviceOS,
deviceType: entity.deviceType,
});
export class OAuthCallbackDto {
@IsNotEmpty()
@IsString()

View File

@@ -0,0 +1,58 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsBoolean, IsString } from 'class-validator';
import { PluginEntity } from 'src/entities/plugin.entity';
import { Optional, ValidateBoolean } from 'src/validation';
export class SearchPluginDto {
@ValidateBoolean({ optional: true })
isEnabled?: boolean;
@ValidateBoolean({ optional: true })
isOfficial?: boolean;
@ValidateBoolean({ optional: true })
isInstalled?: boolean;
@IsString()
@Optional()
name?: string;
}
export class PluginImportDto {
url!: string;
install!: boolean;
isEnabled!: boolean;
isOfficial!: boolean;
}
export class PluginUpdateDto {
@IsBoolean()
isEnabled!: boolean;
}
export class PluginResponseDto {
id!: string;
createdAt!: Date;
updatedAt!: Date;
packageId!: string;
@ApiProperty({ type: 'integer' })
version!: number;
name!: string;
description!: string;
isEnabled!: boolean;
isInstalled!: boolean;
isTrusted!: boolean;
}
export const mapPlugin = (plugin: PluginEntity): PluginResponseDto => ({
id: plugin.id,
createdAt: plugin.createdAt,
updatedAt: plugin.updatedAt,
packageId: plugin.packageId,
version: plugin.version,
name: plugin.name,
description: plugin.description,
isEnabled: plugin.isEnabled,
isInstalled: plugin.isInstalled,
isTrusted: plugin.isTrusted,
});

View File

@@ -1,19 +0,0 @@
import { SessionEntity } from 'src/entities/session.entity';
export class SessionResponseDto {
id!: string;
createdAt!: string;
updatedAt!: string;
current!: boolean;
deviceType!: string;
deviceOS!: string;
}
export const mapSession = (entity: SessionEntity, currentId?: string): SessionResponseDto => ({
id: entity.id,
createdAt: entity.createdAt.toISOString(),
updatedAt: entity.updatedAt.toISOString(),
current: currentId === entity.id,
deviceOS: entity.deviceOS,
deviceType: entity.deviceType,
});

View File

@@ -417,9 +417,6 @@ class SystemConfigImageDto {
@IsEnum(Colorspace)
@ApiProperty({ enumName: 'Colorspace', enum: Colorspace })
colorspace!: Colorspace;
@ValidateBoolean()
extractEmbedded!: boolean;
}
class SystemConfigTrashDto {

View File

@@ -1,15 +0,0 @@
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;
}

View File

@@ -13,13 +13,14 @@ import { MemoryEntity } from 'src/entities/memory.entity';
import { MoveEntity } from 'src/entities/move.entity';
import { PartnerEntity } from 'src/entities/partner.entity';
import { PersonEntity } from 'src/entities/person.entity';
import { SessionEntity } from 'src/entities/session.entity';
import { PluginEntity } from 'src/entities/plugin.entity';
import { SharedLinkEntity } from 'src/entities/shared-link.entity';
import { SmartInfoEntity } from 'src/entities/smart-info.entity';
import { SmartSearchEntity } from 'src/entities/smart-search.entity';
import { SystemConfigEntity } from 'src/entities/system-config.entity';
import { SystemMetadataEntity } from 'src/entities/system-metadata.entity';
import { TagEntity } from 'src/entities/tag.entity';
import { UserTokenEntity } from 'src/entities/user-token.entity';
import { UserEntity } from 'src/entities/user.entity';
export const entities = [
@@ -37,6 +38,7 @@ export const entities = [
MoveEntity,
PartnerEntity,
PersonEntity,
PluginEntity,
SharedLinkEntity,
SmartInfoEntity,
SmartSearchEntity,
@@ -44,6 +46,6 @@ export const entities = [
SystemMetadataEntity,
TagEntity,
UserEntity,
SessionEntity,
UserTokenEntity,
LibraryEntity,
];

View File

@@ -0,0 +1,40 @@
import { Column, CreateDateColumn, DeleteDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm';
@Entity('plugins')
export class PluginEntity {
@PrimaryGeneratedColumn('uuid')
id!: string;
@CreateDateColumn({ type: 'timestamptz' })
createdAt!: Date;
@UpdateDateColumn({ type: 'timestamptz' })
updatedAt!: Date;
@DeleteDateColumn({ type: 'timestamptz', nullable: true })
deletedAt!: Date | null;
@Column({ unique: true })
packageId!: string;
@Column()
version!: number;
@Column()
name!: string;
@Column()
description!: string;
@Column({ type: 'boolean', default: true })
isEnabled!: boolean;
@Column({ type: 'boolean', default: false })
isInstalled!: boolean;
@Column({ type: 'boolean', default: false })
isTrusted!: boolean;
@Column({ nullable: true })
installPath!: string | null;
}

View File

@@ -114,7 +114,6 @@ export const SystemConfigKey = {
IMAGE_PREVIEW_SIZE: 'image.previewSize',
IMAGE_QUALITY: 'image.quality',
IMAGE_COLORSPACE: 'image.colorspace',
IMAGE_EXTRACT_EMBEDDED: 'image.extractEmbedded',
TRASH_ENABLED: 'trash.enabled',
TRASH_DAYS: 'trash.days',
@@ -285,7 +284,6 @@ export interface SystemConfig {
previewSize: number;
quality: number;
colorspace: Colorspace;
extractEmbedded: boolean;
};
newVersionCheck: {
enabled: boolean;

Some files were not shown because too many files have changed in this diff Show More