From 62e22100238f1b9dfb13b9f350fccf12184f728b Mon Sep 17 00:00:00 2001 From: Joachim Van Herwegen Date: Thu, 17 Feb 2022 10:59:10 +0100 Subject: [PATCH] feat: Warn users when they change the base URL --- config/app/init/base/init.json | 2 ++ config/app/init/initializers/base-url.json | 13 ++++++++ src/index.ts | 1 + src/init/BaseUrlVerifier.ts | 32 ++++++++++++++++++ test/unit/init/BaseUrlVerifier.test.ts | 38 ++++++++++++++++++++++ 5 files changed, 86 insertions(+) create mode 100644 config/app/init/initializers/base-url.json create mode 100644 src/init/BaseUrlVerifier.ts create mode 100644 test/unit/init/BaseUrlVerifier.test.ts diff --git a/config/app/init/base/init.json b/config/app/init/base/init.json index d794509f0..b19126bd6 100644 --- a/config/app/init/base/init.json +++ b/config/app/init/base/init.json @@ -1,6 +1,7 @@ { "@context": "https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^2.0.0/components/context.jsonld", "import": [ + "files-scs:config/app/init/initializers/base-url.json", "files-scs:config/app/init/initializers/logger.json", "files-scs:config/app/init/initializers/server.json" ], @@ -11,6 +12,7 @@ "@type": "SequenceHandler", "handlers": [ { "@id": "urn:solid-server:default:LoggerInitializer" }, + { "@id": "urn:solid-server:default:BaseUrlVerifier" }, { "@id": "urn:solid-server:default:ParallelInitializer" }, { "@id": "urn:solid-server:default:ServerInitializer" } ] diff --git a/config/app/init/initializers/base-url.json b/config/app/init/initializers/base-url.json new file mode 100644 index 000000000..0eb1176dd --- /dev/null +++ b/config/app/init/initializers/base-url.json @@ -0,0 +1,13 @@ +{ + "@context": "https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^2.0.0/components/context.jsonld", + "@graph": [ + { + "comment": "Logs a warning if the base URL changes.", + "@id": "urn:solid-server:default:BaseUrlVerifier", + "@type": "BaseUrlVerifier", + "baseUrl": { "@id": "urn:solid-server:default:variable:baseUrl" }, + "storageKey": "current-base-url", + "storage": { "@id": "urn:solid-server:default:SetupStorage" } + } + ] +} diff --git a/src/index.ts b/src/index.ts index 47587d80e..899275ed8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -201,6 +201,7 @@ export * from './init/variables/SettingsResolver'; // Init export * from './init/App'; export * from './init/AppRunner'; +export * from './init/BaseUrlVerifier'; export * from './init/CliResolver'; export * from './init/ConfigPodInitializer'; export * from './init/ContainerInitializer'; diff --git a/src/init/BaseUrlVerifier.ts b/src/init/BaseUrlVerifier.ts new file mode 100644 index 000000000..4b2b39b4d --- /dev/null +++ b/src/init/BaseUrlVerifier.ts @@ -0,0 +1,32 @@ +import { getLoggerFor } from '../logging/LogUtil'; +import type { KeyValueStorage } from '../storage/keyvalue/KeyValueStorage'; +import { Initializer } from './Initializer'; + +/** + * Stores the `baseUrl` value that was used to start the server + * and warns the user in case it differs from the previous one. + */ +export class BaseUrlVerifier extends Initializer { + private readonly baseUrl: string; + private readonly storageKey: string; + private readonly storage: KeyValueStorage; + + private readonly logger = getLoggerFor(this); + + public constructor(baseUrl: string, storageKey: string, storage: KeyValueStorage) { + super(); + this.baseUrl = baseUrl; + this.storageKey = storageKey; + this.storage = storage; + } + + public async handle(): Promise { + const previousValue = await this.storage.get(this.storageKey); + if (previousValue && this.baseUrl !== previousValue) { + this.logger.warn(`The server is being started with a base URL of ${this.baseUrl + } while it was previously started with ${previousValue + }. Resources generated with the previous server instance, such as a WebID, might no longer work correctly.`); + } + await this.storage.set(this.storageKey, this.baseUrl); + } +} diff --git a/test/unit/init/BaseUrlVerifier.test.ts b/test/unit/init/BaseUrlVerifier.test.ts new file mode 100644 index 000000000..a669caf6a --- /dev/null +++ b/test/unit/init/BaseUrlVerifier.test.ts @@ -0,0 +1,38 @@ +import { BaseUrlVerifier } from '../../../src/init/BaseUrlVerifier'; +import type { Logger } from '../../../src/logging/Logger'; +import { getLoggerFor } from '../../../src/logging/LogUtil'; +import type { KeyValueStorage } from '../../../src/storage/keyvalue/KeyValueStorage'; + +jest.mock('../../../src/logging/LogUtil', (): any => { + const logger: Logger = { warn: jest.fn() } as any; + return { getLoggerFor: (): Logger => logger }; +}); + +describe('A BaseUrlVerifier', (): void => { + const logger: jest.Mocked = getLoggerFor(BaseUrlVerifier) as any; + const baseUrl1 = 'http://base1.example.com/'; + const baseUrl2 = 'http://base2.example.com/'; + const storageKey = 'uniqueKey'; + let storage: KeyValueStorage; + + beforeEach(async(): Promise => { + storage = new Map() as any; + jest.clearAllMocks(); + }); + + it('stores the value if no value was stored yet.', async(): Promise => { + const initializer = new BaseUrlVerifier(baseUrl1, storageKey, storage); + await expect(initializer.handle()).resolves.toBeUndefined(); + expect(logger.warn).toHaveBeenCalledTimes(0); + }); + + it('logs a warning in case the value changes.', async(): Promise => { + let initializer = new BaseUrlVerifier(baseUrl1, storageKey, storage); + await expect(initializer.handle()).resolves.toBeUndefined(); + expect(logger.warn).toHaveBeenCalledTimes(0); + + initializer = new BaseUrlVerifier(baseUrl2, storageKey, storage); + await expect(initializer.handle()).resolves.toBeUndefined(); + expect(logger.warn).toHaveBeenCalledTimes(1); + }); +});