diff --git a/cli/src/api/open-api/api.ts b/cli/src/api/open-api/api.ts index 089b69c47..5d93a32b5 100644 --- a/cli/src/api/open-api/api.ts +++ b/cli/src/api/open-api/api.ts @@ -3019,6 +3019,12 @@ export interface ServerConfigDto { * @memberof ServerConfigDto */ 'isInitialized': boolean; + /** + * + * @type {boolean} + * @memberof ServerConfigDto + */ + 'isOnboarded': boolean; /** * * @type {string} @@ -15142,6 +15148,44 @@ export const ServerInfoApiAxiosParamCreator = function (configuration?: Configur + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + setAdminOnboarding: async (options: AxiosRequestConfig = {}): Promise => { + const localVarPath = `/server-info/admin-onboarding`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication cookie required + + // authentication api_key required + await setApiKeyToObject(localVarHeaderParameter, "x-api-key", configuration) + + // authentication bearer required + // http bearer authentication required + await setBearerAuthToObject(localVarHeaderParameter, configuration) + + + setSearchParams(localVarUrlObj, localVarQueryParameter); let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; @@ -15233,6 +15277,15 @@ export const ServerInfoApiFp = function(configuration?: Configuration) { const localVarAxiosArgs = await localVarAxiosParamCreator.pingServer(options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, + /** + * + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async setAdminOnboarding(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.setAdminOnboarding(options); + return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + }, } }; @@ -15307,6 +15360,14 @@ export const ServerInfoApiFactory = function (configuration?: Configuration, bas pingServer(options?: AxiosRequestConfig): AxiosPromise { return localVarFp.pingServer(options).then((request) => request(axios, basePath)); }, + /** + * + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + setAdminOnboarding(options?: AxiosRequestConfig): AxiosPromise { + return localVarFp.setAdminOnboarding(options).then((request) => request(axios, basePath)); + }, }; }; @@ -15396,6 +15457,16 @@ export class ServerInfoApi extends BaseAPI { public pingServer(options?: AxiosRequestConfig) { return ServerInfoApiFp(this.configuration).pingServer(options).then((request) => request(this.axios, this.basePath)); } + + /** + * + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ServerInfoApi + */ + public setAdminOnboarding(options?: AxiosRequestConfig) { + return ServerInfoApiFp(this.configuration).setAdminOnboarding(options).then((request) => request(this.axios, this.basePath)); + } } diff --git a/mobile/openapi/README.md b/mobile/openapi/README.md index 068aa8aa2..39cf9a74a 100644 --- a/mobile/openapi/README.md +++ b/mobile/openapi/README.md @@ -176,6 +176,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 | +*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 | diff --git a/mobile/openapi/doc/ServerConfigDto.md b/mobile/openapi/doc/ServerConfigDto.md index b2406daf7..317431b9b 100644 --- a/mobile/openapi/doc/ServerConfigDto.md +++ b/mobile/openapi/doc/ServerConfigDto.md @@ -10,6 +10,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **externalDomain** | **String** | | **isInitialized** | **bool** | | +**isOnboarded** | **bool** | | **loginPageMessage** | **String** | | **oauthButtonText** | **String** | | **trashDays** | **int** | | diff --git a/mobile/openapi/doc/ServerInfoApi.md b/mobile/openapi/doc/ServerInfoApi.md index e8121a800..cb5cf0fd3 100644 --- a/mobile/openapi/doc/ServerInfoApi.md +++ b/mobile/openapi/doc/ServerInfoApi.md @@ -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('cookie').apiKey = 'YOUR_API_KEY'; +// uncomment below to setup prefix (e.g. Bearer) for API key, if needed +//defaultApiClient.getAuthentication('cookie').apiKeyPrefix = 'Bearer'; +// TODO Configure API key authorization: api_key +//defaultApiClient.getAuthentication('api_key').apiKey = 'YOUR_API_KEY'; +// uncomment below to setup prefix (e.g. Bearer) for API key, if needed +//defaultApiClient.getAuthentication('api_key').apiKeyPrefix = 'Bearer'; +// TODO Configure HTTP Bearer authorization: bearer +// Case 1. Use String Token +//defaultApiClient.getAuthentication('bearer').setAccessToken('YOUR_ACCESS_TOKEN'); +// Case 2. Use Function which generate token. +// String yourTokenGeneratorFunction() { ... } +//defaultApiClient.getAuthentication('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) + diff --git a/mobile/openapi/lib/api/server_info_api.dart b/mobile/openapi/lib/api/server_info_api.dart index b67045add..77840acd1 100644 --- a/mobile/openapi/lib/api/server_info_api.dart +++ b/mobile/openapi/lib/api/server_info_api.dart @@ -343,4 +343,37 @@ class ServerInfoApi { } return null; } + + /// Performs an HTTP 'POST /server-info/admin-onboarding' operation and returns the [Response]. + Future setAdminOnboardingWithHttpInfo() async { + // ignore: prefer_const_declarations + final path = r'/server-info/admin-onboarding'; + + // ignore: prefer_final_locals + Object? postBody; + + final queryParams = []; + final headerParams = {}; + final formParams = {}; + + const contentTypes = []; + + + return apiClient.invokeAPI( + path, + 'POST', + queryParams, + postBody, + headerParams, + formParams, + contentTypes.isEmpty ? null : contentTypes.first, + ); + } + + Future setAdminOnboarding() async { + final response = await setAdminOnboardingWithHttpInfo(); + if (response.statusCode >= HttpStatus.badRequest) { + throw ApiException(response.statusCode, await _decodeBodyBytes(response)); + } + } } diff --git a/mobile/openapi/lib/model/server_config_dto.dart b/mobile/openapi/lib/model/server_config_dto.dart index abe598396..d93da96a2 100644 --- a/mobile/openapi/lib/model/server_config_dto.dart +++ b/mobile/openapi/lib/model/server_config_dto.dart @@ -15,6 +15,7 @@ class ServerConfigDto { ServerConfigDto({ required this.externalDomain, required this.isInitialized, + required this.isOnboarded, required this.loginPageMessage, required this.oauthButtonText, required this.trashDays, @@ -24,6 +25,8 @@ class ServerConfigDto { bool isInitialized; + bool isOnboarded; + String loginPageMessage; String oauthButtonText; @@ -34,6 +37,7 @@ class ServerConfigDto { bool operator ==(Object other) => identical(this, other) || other is ServerConfigDto && other.externalDomain == externalDomain && other.isInitialized == isInitialized && + other.isOnboarded == isOnboarded && other.loginPageMessage == loginPageMessage && other.oauthButtonText == oauthButtonText && other.trashDays == trashDays; @@ -43,17 +47,19 @@ class ServerConfigDto { // ignore: unnecessary_parenthesis (externalDomain.hashCode) + (isInitialized.hashCode) + + (isOnboarded.hashCode) + (loginPageMessage.hashCode) + (oauthButtonText.hashCode) + (trashDays.hashCode); @override - String toString() => 'ServerConfigDto[externalDomain=$externalDomain, isInitialized=$isInitialized, loginPageMessage=$loginPageMessage, oauthButtonText=$oauthButtonText, trashDays=$trashDays]'; + String toString() => 'ServerConfigDto[externalDomain=$externalDomain, isInitialized=$isInitialized, isOnboarded=$isOnboarded, loginPageMessage=$loginPageMessage, oauthButtonText=$oauthButtonText, trashDays=$trashDays]'; Map toJson() { final json = {}; json[r'externalDomain'] = this.externalDomain; json[r'isInitialized'] = this.isInitialized; + json[r'isOnboarded'] = this.isOnboarded; json[r'loginPageMessage'] = this.loginPageMessage; json[r'oauthButtonText'] = this.oauthButtonText; json[r'trashDays'] = this.trashDays; @@ -70,6 +76,7 @@ class ServerConfigDto { return ServerConfigDto( externalDomain: mapValueOfType(json, r'externalDomain')!, isInitialized: mapValueOfType(json, r'isInitialized')!, + isOnboarded: mapValueOfType(json, r'isOnboarded')!, loginPageMessage: mapValueOfType(json, r'loginPageMessage')!, oauthButtonText: mapValueOfType(json, r'oauthButtonText')!, trashDays: mapValueOfType(json, r'trashDays')!, @@ -122,6 +129,7 @@ class ServerConfigDto { static const requiredKeys = { 'externalDomain', 'isInitialized', + 'isOnboarded', 'loginPageMessage', 'oauthButtonText', 'trashDays', diff --git a/mobile/openapi/test/server_config_dto_test.dart b/mobile/openapi/test/server_config_dto_test.dart index ffd373bf2..813ac2565 100644 --- a/mobile/openapi/test/server_config_dto_test.dart +++ b/mobile/openapi/test/server_config_dto_test.dart @@ -26,6 +26,11 @@ void main() { // TODO }); + // bool isOnboarded + test('to test the property `isOnboarded`', () async { + // TODO + }); + // String loginPageMessage test('to test the property `loginPageMessage`', () async { // TODO diff --git a/mobile/openapi/test/server_info_api_test.dart b/mobile/openapi/test/server_info_api_test.dart index dac465116..68cd1c348 100644 --- a/mobile/openapi/test/server_info_api_test.dart +++ b/mobile/openapi/test/server_info_api_test.dart @@ -57,5 +57,10 @@ void main() { // TODO }); + //Future setAdminOnboarding() async + test('test setAdminOnboarding', () async { + // TODO + }); + }); } diff --git a/server/immich-openapi-specs.json b/server/immich-openapi-specs.json index 240a2d381..0cf34169b 100644 --- a/server/immich-openapi-specs.json +++ b/server/immich-openapi-specs.json @@ -4725,6 +4725,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", @@ -8599,6 +8624,9 @@ "isInitialized": { "type": "boolean" }, + "isOnboarded": { + "type": "boolean" + }, "loginPageMessage": { "type": "string" }, @@ -8614,6 +8642,7 @@ "oauthButtonText", "loginPageMessage", "isInitialized", + "isOnboarded", "externalDomain" ], "type": "object" diff --git a/server/src/domain/server-info/server-info.dto.ts b/server/src/domain/server-info/server-info.dto.ts index 32ac51aa4..ea0d03b88 100644 --- a/server/src/domain/server-info/server-info.dto.ts +++ b/server/src/domain/server-info/server-info.dto.ts @@ -86,6 +86,7 @@ export class ServerConfigDto { @ApiProperty({ type: 'integer' }) trashDays!: number; isInitialized!: boolean; + isOnboarded!: boolean; externalDomain!: string; } diff --git a/server/src/domain/server-info/server-info.service.spec.ts b/server/src/domain/server-info/server-info.service.spec.ts index d093399c7..a8cd82443 100644 --- a/server/src/domain/server-info/server-info.service.spec.ts +++ b/server/src/domain/server-info/server-info.service.spec.ts @@ -1,8 +1,10 @@ +import { SystemMetadataKey } from '@app/infra/entities'; import { newCommunicationRepositoryMock, newServerInfoRepositoryMock, newStorageRepositoryMock, newSystemConfigRepositoryMock, + newSystemMetadataRepositoryMock, newUserRepositoryMock, } from '@test'; import { serverVersion } from '../domain.constant'; @@ -11,6 +13,7 @@ import { IServerInfoRepository, IStorageRepository, ISystemConfigRepository, + ISystemMetadataRepository, IUserRepository, } from '../repositories'; import { ServerInfoService } from './server-info.service'; @@ -22,6 +25,7 @@ describe(ServerInfoService.name, () => { let serverInfoMock: jest.Mocked; let storageMock: jest.Mocked; let userMock: jest.Mocked; + let systemMetadataMock: jest.Mocked; beforeEach(() => { configMock = newSystemConfigRepositoryMock(); @@ -29,8 +33,16 @@ describe(ServerInfoService.name, () => { serverInfoMock = newServerInfoRepositoryMock(); storageMock = newStorageRepositoryMock(); userMock = newUserRepositoryMock(); + systemMetadataMock = newSystemMetadataRepositoryMock(); - sut = new ServerInfoService(communicationMock, configMock, userMock, serverInfoMock, storageMock); + sut = new ServerInfoService( + communicationMock, + configMock, + userMock, + serverInfoMock, + storageMock, + systemMetadataMock, + ); }); it('should work', () => { @@ -184,12 +196,21 @@ describe(ServerInfoService.name, () => { loginPageMessage: '', oauthButtonText: 'Login with OAuth', trashDays: 30, + isInitialized: undefined, + isOnboarded: false, externalDomain: '', }); expect(configMock.load).toHaveBeenCalled(); }); }); + describe('setAdminOnboarding', () => { + it('should set admin onboarding to true', async () => { + await sut.setAdminOnboarding(); + expect(systemMetadataMock.set).toHaveBeenCalledWith(SystemMetadataKey.ADMIN_ONBOARDING, { isOnboarded: true }); + }); + }); + describe('getStats', () => { it('should total up usage by user', async () => { userMock.getUserStats.mockResolvedValue([ diff --git a/server/src/domain/server-info/server-info.service.ts b/server/src/domain/server-info/server-info.service.ts index 7c3f70784..697e461de 100644 --- a/server/src/domain/server-info/server-info.service.ts +++ b/server/src/domain/server-info/server-info.service.ts @@ -1,3 +1,4 @@ +import { SystemMetadataKey } from '@app/infra/entities'; import { ImmichLogger } from '@app/infra/logger'; import { Inject, Injectable } from '@nestjs/common'; import { DateTime } from 'luxon'; @@ -9,6 +10,7 @@ import { IServerInfoRepository, IStorageRepository, ISystemConfigRepository, + ISystemMetadataRepository, IUserRepository, UserStatsQueryResponse, } from '../repositories'; @@ -37,6 +39,7 @@ export class ServerInfoService { @Inject(IUserRepository) private userRepository: IUserRepository, @Inject(IServerInfoRepository) private repository: IServerInfoRepository, @Inject(IStorageRepository) private storageRepository: IStorageRepository, + @Inject(ISystemMetadataRepository) private readonly systemMetadataRepository: ISystemMetadataRepository, ) { this.configCore = SystemConfigCore.create(configRepository); this.communicationRepository.on('connect', (userId) => this.handleConnect(userId)); @@ -79,16 +82,22 @@ export class ServerInfoService { async getConfig(): Promise { const config = await this.configCore.getConfig(); const isInitialized = await this.userRepository.hasAdmin(); + const onboarding = await this.systemMetadataRepository.get(SystemMetadataKey.ADMIN_ONBOARDING); return { loginPageMessage: config.server.loginPageMessage, trashDays: config.trash.days, oauthButtonText: config.oauth.buttonText, isInitialized, + isOnboarded: onboarding?.isOnboarded || false, externalDomain: config.server.externalDomain, }; } + setAdminOnboarding(): Promise { + return this.systemMetadataRepository.set(SystemMetadataKey.ADMIN_ONBOARDING, { isOnboarded: true }); + } + async getStatistics(): Promise { const userStats: UserStatsQueryResponse[] = await this.userRepository.getUserStats(); const serverStats = new ServerStatsResponseDto(); diff --git a/server/src/immich/controllers/server-info.controller.ts b/server/src/immich/controllers/server-info.controller.ts index 52e9ea8d2..66835501c 100644 --- a/server/src/immich/controllers/server-info.controller.ts +++ b/server/src/immich/controllers/server-info.controller.ts @@ -9,7 +9,7 @@ import { ServerThemeDto, ServerVersionResponseDto, } from '@app/domain'; -import { Controller, Get } from '@nestjs/common'; +import { Controller, Get, HttpCode, HttpStatus, Post } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; import { AdminRoute, Authenticated, PublicRoute } from '../app.guard'; import { UseValidation } from '../app.utils'; @@ -67,4 +67,11 @@ export class ServerInfoController { getSupportedMediaTypes(): ServerMediaTypesResponseDto { return this.service.getSupportedMediaTypes(); } + + @AdminRoute() + @Post('admin-onboarding') + @HttpCode(HttpStatus.NO_CONTENT) + setAdminOnboarding(): Promise { + return this.service.setAdminOnboarding(); + } } diff --git a/server/src/infra/entities/system-metadata.entity.ts b/server/src/infra/entities/system-metadata.entity.ts index 623806db7..24e9f83c7 100644 --- a/server/src/infra/entities/system-metadata.entity.ts +++ b/server/src/infra/entities/system-metadata.entity.ts @@ -11,8 +11,10 @@ export class SystemMetadataEntity { export enum SystemMetadataKey { REVERSE_GEOCODING_STATE = 'reverse-geocoding-state', + ADMIN_ONBOARDING = 'admin-onboarding', } export interface SystemMetadata extends Record { [SystemMetadataKey.REVERSE_GEOCODING_STATE]: { lastUpdate?: string; lastImportFileName?: string }; + [SystemMetadataKey.ADMIN_ONBOARDING]: { isOnboarded: boolean }; } diff --git a/server/test/api/index.ts b/server/test/api/index.ts index 21987c500..d13f2425e 100644 --- a/server/test/api/index.ts +++ b/server/test/api/index.ts @@ -5,6 +5,7 @@ import { assetApi } from './asset-api'; import { authApi } from './auth-api'; import { libraryApi } from './library-api'; import { partnerApi } from './partner-api'; +import { serverInfoApi } from './server-info-api'; import { sharedLinkApi } from './shared-link-api'; import { userApi } from './user-api'; @@ -14,6 +15,7 @@ export const api = { apiKeyApi, assetApi, libraryApi, + serverInfoApi, sharedLinkApi, albumApi, userApi, diff --git a/server/test/api/server-info-api.ts b/server/test/api/server-info-api.ts new file mode 100644 index 000000000..f885bc856 --- /dev/null +++ b/server/test/api/server-info-api.ts @@ -0,0 +1,10 @@ +import { ServerConfigDto } from '@app/domain'; +import request from 'supertest'; + +export const serverInfoApi = { + getConfig: async (server: any) => { + const res = await request(server).get('/server-info/config'); + expect(res.status).toBe(200); + return res.body as ServerConfigDto; + }, +}; diff --git a/server/test/e2e/server-info.e2e-spec.ts b/server/test/e2e/server-info.e2e-spec.ts index d2d54d079..fb0ad90c8 100644 --- a/server/test/e2e/server-info.e2e-spec.ts +++ b/server/test/e2e/server-info.e2e-spec.ts @@ -98,6 +98,7 @@ describe(`${ServerInfoController.name} (e2e)`, () => { trashDays: 30, isInitialized: true, externalDomain: '', + isOnboarded: false, }); }); }); @@ -167,4 +168,19 @@ describe(`${ServerInfoController.name} (e2e)`, () => { }); }); }); + + describe('POST /server-info/admin-onboarding', () => { + it('should set admin onboarding', async () => { + const config = await api.serverInfoApi.getConfig(server); + expect(config.isOnboarded).toBe(false); + + const { status } = await request(server) + .post('/server-info/admin-onboarding') + .set('Authorization', `Bearer ${admin.accessToken}`); + expect(status).toBe(204); + + const newConfig = await api.serverInfoApi.getConfig(server); + expect(newConfig.isOnboarded).toBe(true); + }); + }); }); diff --git a/server/test/repositories/index.ts b/server/test/repositories/index.ts index f625dc521..d7a7f3e0c 100644 --- a/server/test/repositories/index.ts +++ b/server/test/repositories/index.ts @@ -19,6 +19,7 @@ export * from './smart-info.repository.mock'; export * from './storage.repository.mock'; export * from './system-config.repository.mock'; export * from './system-info.repository.mock'; +export * from './system-metadata.repository.mock'; export * from './tag.repository.mock'; export * from './user-token.repository.mock'; export * from './user.repository.mock'; diff --git a/server/test/repositories/system-metadata.repository.mock.ts b/server/test/repositories/system-metadata.repository.mock.ts new file mode 100644 index 000000000..fc4207da6 --- /dev/null +++ b/server/test/repositories/system-metadata.repository.mock.ts @@ -0,0 +1,8 @@ +import { ISystemMetadataRepository } from '@app/domain'; + +export const newSystemMetadataRepositoryMock = (): jest.Mocked => { + return { + get: jest.fn(), + set: jest.fn(), + }; +}; diff --git a/web/src/api/open-api/api.ts b/web/src/api/open-api/api.ts index 089b69c47..5d93a32b5 100644 --- a/web/src/api/open-api/api.ts +++ b/web/src/api/open-api/api.ts @@ -3019,6 +3019,12 @@ export interface ServerConfigDto { * @memberof ServerConfigDto */ 'isInitialized': boolean; + /** + * + * @type {boolean} + * @memberof ServerConfigDto + */ + 'isOnboarded': boolean; /** * * @type {string} @@ -15142,6 +15148,44 @@ export const ServerInfoApiAxiosParamCreator = function (configuration?: Configur + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + setAdminOnboarding: async (options: AxiosRequestConfig = {}): Promise => { + const localVarPath = `/server-info/admin-onboarding`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication cookie required + + // authentication api_key required + await setApiKeyToObject(localVarHeaderParameter, "x-api-key", configuration) + + // authentication bearer required + // http bearer authentication required + await setBearerAuthToObject(localVarHeaderParameter, configuration) + + + setSearchParams(localVarUrlObj, localVarQueryParameter); let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; @@ -15233,6 +15277,15 @@ export const ServerInfoApiFp = function(configuration?: Configuration) { const localVarAxiosArgs = await localVarAxiosParamCreator.pingServer(options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, + /** + * + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async setAdminOnboarding(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.setAdminOnboarding(options); + return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + }, } }; @@ -15307,6 +15360,14 @@ export const ServerInfoApiFactory = function (configuration?: Configuration, bas pingServer(options?: AxiosRequestConfig): AxiosPromise { return localVarFp.pingServer(options).then((request) => request(axios, basePath)); }, + /** + * + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + setAdminOnboarding(options?: AxiosRequestConfig): AxiosPromise { + return localVarFp.setAdminOnboarding(options).then((request) => request(axios, basePath)); + }, }; }; @@ -15396,6 +15457,16 @@ export class ServerInfoApi extends BaseAPI { public pingServer(options?: AxiosRequestConfig) { return ServerInfoApiFp(this.configuration).pingServer(options).then((request) => request(this.axios, this.basePath)); } + + /** + * + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ServerInfoApi + */ + public setAdminOnboarding(options?: AxiosRequestConfig) { + return ServerInfoApiFp(this.configuration).setAdminOnboarding(options).then((request) => request(this.axios, this.basePath)); + } } diff --git a/web/src/lib/assets/settings-outline.svg b/web/src/lib/assets/settings-outline.svg new file mode 100644 index 000000000..725358941 --- /dev/null +++ b/web/src/lib/assets/settings-outline.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/src/lib/components/admin-page/settings/setting-switch.svelte b/web/src/lib/components/admin-page/settings/setting-switch.svelte index 302e1a88c..6797423a5 100644 --- a/web/src/lib/components/admin-page/settings/setting-switch.svelte +++ b/web/src/lib/components/admin-page/settings/setting-switch.svelte @@ -16,7 +16,7 @@
-