mirror of
https://github.com/CommunitySolidServer/CommunitySolidServer.git
synced 2024-10-03 14:55:10 +00:00
fix: Ensure setup values are migrated correctly
This commit is contained in:
parent
b65b72a25e
commit
7a44581406
@ -33,8 +33,8 @@
|
|||||||
"@type":"SequenceHandler",
|
"@type":"SequenceHandler",
|
||||||
"handlers": [
|
"handlers": [
|
||||||
{ "@id": "urn:solid-server:default:CleanupInitializer"},
|
{ "@id": "urn:solid-server:default:CleanupInitializer"},
|
||||||
{ "@id": "urn:solid-server:default:BaseUrlVerifier" },
|
|
||||||
{ "@id": "urn:solid-server:default:MigrationInitializer" },
|
{ "@id": "urn:solid-server:default:MigrationInitializer" },
|
||||||
|
{ "@id": "urn:solid-server:default:BaseUrlVerifier" },
|
||||||
{ "@id": "urn:solid-server:default:PrimaryParallelInitializer" },
|
{ "@id": "urn:solid-server:default:PrimaryParallelInitializer" },
|
||||||
{ "@id": "urn:solid-server:default:SeededAccountInitializer" },
|
{ "@id": "urn:solid-server:default:SeededAccountInitializer" },
|
||||||
{ "@id": "urn:solid-server:default:ModuleVersionVerifier" },
|
{ "@id": "urn:solid-server:default:ModuleVersionVerifier" },
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
"@context": "https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^6.0.0/components/context.jsonld",
|
"@context": "https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^6.0.0/components/context.jsonld",
|
||||||
"@graph": [
|
"@graph": [
|
||||||
{
|
{
|
||||||
"comment": "Handles migration of v6 account data.",
|
"comment": "Handles migration of v6 internal data. In a conditional handler to prevent issues if something fails between migration and writing the new version.",
|
||||||
"@id": "urn:solid-server:default:V6MigrationHandler",
|
"@id": "urn:solid-server:default:V6MigrationHandler",
|
||||||
"@type": "ConditionalHandler",
|
"@type": "ConditionalHandler",
|
||||||
"storageKey": "v6-migration",
|
"storageKey": "v6-migration",
|
||||||
@ -13,7 +13,7 @@
|
|||||||
"@id": "urn:solid-server:default:V6MigrationInitializer",
|
"@id": "urn:solid-server:default:V6MigrationInitializer",
|
||||||
"@type": "V6MigrationInitializer",
|
"@type": "V6MigrationInitializer",
|
||||||
"versionKey": "current-server-version",
|
"versionKey": "current-server-version",
|
||||||
"versionStorage": { "@id": "urn:solid-server:default:V6MigrationSetupStorage" },
|
"setupStorage": { "@id": "urn:solid-server:default:V6MigrationSetupStorage" },
|
||||||
"accountStorage": { "@id": "urn:solid-server:default:V6MigrationAccountStorage" },
|
"accountStorage": { "@id": "urn:solid-server:default:V6MigrationAccountStorage" },
|
||||||
"clientCredentialsStorage": { "@id": "urn:solid-server:default:V6MigrationClientCredentialsStorage" },
|
"clientCredentialsStorage": { "@id": "urn:solid-server:default:V6MigrationClientCredentialsStorage" },
|
||||||
"cleanupStorages": [
|
"cleanupStorages": [
|
||||||
@ -23,10 +23,10 @@
|
|||||||
{ "@id": "urn:solid-server:default:V6MigrationKeyStorage" },
|
{ "@id": "urn:solid-server:default:V6MigrationKeyStorage" },
|
||||||
{ "@id": "urn:solid-server:default:V6MigrationAdapterStorage" },
|
{ "@id": "urn:solid-server:default:V6MigrationAdapterStorage" },
|
||||||
{ "@id": "urn:solid-server:default:V6MigrationTokenStorage" },
|
{ "@id": "urn:solid-server:default:V6MigrationTokenStorage" },
|
||||||
{ "@id": "urn:solid-server:default:V6MigrationNotificationStorage" },
|
{ "@id": "urn:solid-server:default:V6MigrationNotificationStorage" }
|
||||||
{ "@id": "urn:solid-server:default:V6MigrationSetupStorage" }
|
|
||||||
],
|
],
|
||||||
"newStorage": { "@id": "urn:solid-server:default:AccountStorage" },
|
"newAccountStorage": { "@id": "urn:solid-server:default:AccountStorage" },
|
||||||
|
"newSetupStorage": { "@id": "urn:solid-server:default:SetupStorage" },
|
||||||
"skipConfirmation": { "@id": "urn:solid-server:default:variable:confirmMigration" }
|
"skipConfirmation": { "@id": "urn:solid-server:default:variable:confirmMigration" }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -50,11 +50,11 @@ const STORAGE_DESCRIPTION = {
|
|||||||
|
|
||||||
export interface V6MigrationInitializerArgs {
|
export interface V6MigrationInitializerArgs {
|
||||||
/**
|
/**
|
||||||
* The storage in which the version is saved that was stored last time the server was started.
|
* The storage in which all setup values are stored, including the version of the server.
|
||||||
*/
|
*/
|
||||||
versionStorage: KeyValueStorage<string, string>;
|
setupStorage: KeyValueStorage<string, string>;
|
||||||
/**
|
/**
|
||||||
* The key necessary to get the version from the `versionStorage`.
|
* The key necessary to get the version from the `setupStorage`.
|
||||||
*/
|
*/
|
||||||
versionKey: string;
|
versionKey: string;
|
||||||
/**
|
/**
|
||||||
@ -72,7 +72,11 @@ export interface V6MigrationInitializerArgs {
|
|||||||
/**
|
/**
|
||||||
* The storage that will contain the account data in the new format.
|
* The storage that will contain the account data in the new format.
|
||||||
*/
|
*/
|
||||||
newStorage: AccountLoginStorage<any>;
|
newAccountStorage: AccountLoginStorage<any>;
|
||||||
|
/**
|
||||||
|
* The storage that will contain the setup entries in the new format.
|
||||||
|
*/
|
||||||
|
newSetupStorage: KeyValueStorage<string, string>;
|
||||||
/**
|
/**
|
||||||
* If true, no confirmation prompt will be printed to the stdout.
|
* If true, no confirmation prompt will be printed to the stdout.
|
||||||
*/
|
*/
|
||||||
@ -92,27 +96,29 @@ export class V6MigrationInitializer extends Initializer {
|
|||||||
private readonly skipConfirmation: boolean;
|
private readonly skipConfirmation: boolean;
|
||||||
|
|
||||||
private readonly versionKey: string;
|
private readonly versionKey: string;
|
||||||
private readonly versionStorage: KeyValueStorage<string, string>;
|
private readonly setupStorage: KeyValueStorage<string, string>;
|
||||||
|
|
||||||
private readonly accountStorage: KeyValueStorage<string, Account | Settings>;
|
private readonly accountStorage: KeyValueStorage<string, Account | Settings>;
|
||||||
private readonly clientCredentialsStorage: KeyValueStorage<string, ClientCredentials>;
|
private readonly clientCredentialsStorage: KeyValueStorage<string, ClientCredentials>;
|
||||||
private readonly cleanupStorages: KeyValueStorage<string, any>[];
|
private readonly cleanupStorages: KeyValueStorage<string, any>[];
|
||||||
|
|
||||||
private readonly newStorage: AccountLoginStorage<typeof STORAGE_DESCRIPTION>;
|
private readonly newAccountStorage: AccountLoginStorage<typeof STORAGE_DESCRIPTION>;
|
||||||
|
private readonly newSetupStorage: KeyValueStorage<string, string>;
|
||||||
|
|
||||||
public constructor(args: V6MigrationInitializerArgs) {
|
public constructor(args: V6MigrationInitializerArgs) {
|
||||||
super();
|
super();
|
||||||
this.skipConfirmation = Boolean(args.skipConfirmation);
|
this.skipConfirmation = Boolean(args.skipConfirmation);
|
||||||
this.versionKey = args.versionKey;
|
this.versionKey = args.versionKey;
|
||||||
this.versionStorage = args.versionStorage;
|
this.setupStorage = args.setupStorage;
|
||||||
this.accountStorage = args.accountStorage;
|
this.accountStorage = args.accountStorage;
|
||||||
this.clientCredentialsStorage = args.clientCredentialsStorage;
|
this.clientCredentialsStorage = args.clientCredentialsStorage;
|
||||||
this.cleanupStorages = args.cleanupStorages;
|
this.cleanupStorages = args.cleanupStorages;
|
||||||
this.newStorage = args.newStorage;
|
this.newAccountStorage = args.newAccountStorage;
|
||||||
|
this.newSetupStorage = args.newSetupStorage;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async handle(): Promise<void> {
|
public async handle(): Promise<void> {
|
||||||
const previousVersion = await this.versionStorage.get(this.versionKey);
|
const previousVersion = await this.setupStorage.get(this.versionKey);
|
||||||
if (!previousVersion) {
|
if (!previousVersion) {
|
||||||
// This happens if this is the first time the server is started
|
// This happens if this is the first time the server is started
|
||||||
this.logger.debug('No previous version found');
|
this.logger.debug('No previous version found');
|
||||||
@ -166,7 +172,13 @@ export class V6MigrationInitializer extends Initializer {
|
|||||||
this.logger.warn(`Unable to find account for client credentials ${label}. Skipping migration of this token.`);
|
this.logger.warn(`Unable to find account for client credentials ${label}. Skipping migration of this token.`);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
await this.newStorage.create(CLIENT_CREDENTIALS_STORAGE_TYPE, { webId, label, secret, accountId });
|
await this.newAccountStorage.create(CLIENT_CREDENTIALS_STORAGE_TYPE, { webId, label, secret, accountId });
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logger.debug('Converting setup entries.');
|
||||||
|
for await (const [ key, value ] of this.setupStorage.entries()) {
|
||||||
|
await this.newSetupStorage.set(key, value);
|
||||||
|
await this.setupStorage.delete(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cleanup all old entries
|
// Cleanup all old entries
|
||||||
@ -206,17 +218,17 @@ export class V6MigrationInitializer extends Initializer {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { id: accountId } = await this.newStorage.create(ACCOUNT_TYPE, {});
|
const { id: accountId } = await this.newAccountStorage.create(ACCOUNT_TYPE, {});
|
||||||
// The `toLowerCase` call is important here to have the expected value
|
// The `toLowerCase` call is important here to have the expected value
|
||||||
await this.newStorage.create(PASSWORD_STORAGE_TYPE,
|
await this.newAccountStorage.create(PASSWORD_STORAGE_TYPE,
|
||||||
{ email: email.toLowerCase(), password, verified, accountId });
|
{ email: email.toLowerCase(), password, verified, accountId });
|
||||||
if (settings.useIdp) {
|
if (settings.useIdp) {
|
||||||
await this.newStorage.create(WEBID_STORAGE_TYPE, { webId, accountId });
|
await this.newAccountStorage.create(WEBID_STORAGE_TYPE, { webId, accountId });
|
||||||
}
|
}
|
||||||
if (settings.podBaseUrl) {
|
if (settings.podBaseUrl) {
|
||||||
const { id: podId } = await this.newStorage.create(POD_STORAGE_TYPE,
|
const { id: podId } = await this.newAccountStorage.create(POD_STORAGE_TYPE,
|
||||||
{ baseUrl: settings.podBaseUrl, accountId });
|
{ baseUrl: settings.podBaseUrl, accountId });
|
||||||
await this.newStorage.create(OWNER_STORAGE_TYPE, { webId, podId, visible: false });
|
await this.newAccountStorage.create(OWNER_STORAGE_TYPE, { webId, podId, visible: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
return { accountId, webId };
|
return { accountId, webId };
|
||||||
|
@ -51,6 +51,7 @@ describe('A server migrating from v6', (): void => {
|
|||||||
it('can start the server to migrate the data.', async(): Promise<void> => {
|
it('can start the server to migrate the data.', async(): Promise<void> => {
|
||||||
// This is going to trigger the migration step
|
// This is going to trigger the migration step
|
||||||
await expect(app.start()).resolves.toBeUndefined();
|
await expect(app.start()).resolves.toBeUndefined();
|
||||||
|
|
||||||
// If migration was successful, there should be no files left in these folders
|
// If migration was successful, there should be no files left in these folders
|
||||||
const accountDir = await readdir(joinFilePath(rootFilePath, '.internal/accounts/'));
|
const accountDir = await readdir(joinFilePath(rootFilePath, '.internal/accounts/'));
|
||||||
expect(accountDir).toEqual(expect.arrayContaining([ 'data', 'index', 'credentials' ]));
|
expect(accountDir).toEqual(expect.arrayContaining([ 'data', 'index', 'credentials' ]));
|
||||||
@ -58,6 +59,15 @@ describe('A server migrating from v6', (): void => {
|
|||||||
expect(credentialsDir).toEqual([]);
|
expect(credentialsDir).toEqual([]);
|
||||||
const forgotDir = await readdir(joinFilePath(rootFilePath, '.internal/forgot-password/'));
|
const forgotDir = await readdir(joinFilePath(rootFilePath, '.internal/forgot-password/'));
|
||||||
expect(forgotDir).toEqual([]);
|
expect(forgotDir).toEqual([]);
|
||||||
|
|
||||||
|
// Setup resources should have been migrated
|
||||||
|
const setupDir = await readdir(joinFilePath(rootFilePath, '.internal/setup/'));
|
||||||
|
expect(setupDir).toEqual([
|
||||||
|
'current-base-url$.json',
|
||||||
|
'current-server-version$.json',
|
||||||
|
'setupCompleted-2.0$.json',
|
||||||
|
'v6-migration$.json',
|
||||||
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('still allows existing accounts to log in.', async(): Promise<void> => {
|
it('still allows existing accounts to log in.', async(): Promise<void> => {
|
||||||
|
@ -42,11 +42,12 @@ describe('A V6MigrationInitializer', (): void => {
|
|||||||
let accounts: Record<string, Account>;
|
let accounts: Record<string, Account>;
|
||||||
let clientCredentials: Record<string, ClientCredentials>;
|
let clientCredentials: Record<string, ClientCredentials>;
|
||||||
const versionKey = 'version';
|
const versionKey = 'version';
|
||||||
let versionStorage: jest.Mocked<KeyValueStorage<string, string>>;
|
let setupStorage: jest.Mocked<KeyValueStorage<string, string>>;
|
||||||
let accountStorage: jest.Mocked<KeyValueStorage<string, Account | Settings>>;
|
let accountStorage: jest.Mocked<KeyValueStorage<string, Account | Settings>>;
|
||||||
let clientCredentialsStorage: jest.Mocked<KeyValueStorage<string, ClientCredentials>>;
|
let clientCredentialsStorage: jest.Mocked<KeyValueStorage<string, ClientCredentials>>;
|
||||||
let forgotPasswordStorage: jest.Mocked<KeyValueStorage<string, unknown>>;
|
let forgotPasswordStorage: jest.Mocked<KeyValueStorage<string, unknown>>;
|
||||||
let newStorage: jest.Mocked<AccountLoginStorage<any>>;
|
let newAccountStorage: jest.Mocked<AccountLoginStorage<any>>;
|
||||||
|
let newSetupStorage: jest.Mocked<KeyValueStorage<string, string>>;
|
||||||
let initializer: V6MigrationInitializer;
|
let initializer: V6MigrationInitializer;
|
||||||
|
|
||||||
beforeEach(async(): Promise<void> => {
|
beforeEach(async(): Promise<void> => {
|
||||||
@ -62,8 +63,16 @@ describe('A V6MigrationInitializer', (): void => {
|
|||||||
token: { webId, secret: 'secret!' },
|
token: { webId, secret: 'secret!' },
|
||||||
};
|
};
|
||||||
|
|
||||||
versionStorage = {
|
setupStorage = {
|
||||||
get: jest.fn().mockResolvedValue('6.0.0'),
|
get: jest.fn().mockResolvedValue('6.0.0'),
|
||||||
|
delete: jest.fn(),
|
||||||
|
entries: jest.fn(async function* (): AsyncGenerator<[string, string]> {
|
||||||
|
yield [ 'version', '6.0.0' ];
|
||||||
|
}),
|
||||||
|
} satisfies Partial<KeyValueStorage<string, string>> as any;
|
||||||
|
|
||||||
|
newSetupStorage = {
|
||||||
|
set: jest.fn(),
|
||||||
} satisfies Partial<KeyValueStorage<string, string>> as any;
|
} satisfies Partial<KeyValueStorage<string, string>> as any;
|
||||||
|
|
||||||
accountStorage = {
|
accountStorage = {
|
||||||
@ -89,17 +98,18 @@ describe('A V6MigrationInitializer', (): void => {
|
|||||||
}),
|
}),
|
||||||
} satisfies Partial<KeyValueStorage<string, any>> as any;
|
} satisfies Partial<KeyValueStorage<string, any>> as any;
|
||||||
|
|
||||||
newStorage = {
|
newAccountStorage = {
|
||||||
create: jest.fn((type): any => ({ id: `${type}-id` })),
|
create: jest.fn((type): any => ({ id: `${type}-id` })),
|
||||||
} satisfies Partial<AccountLoginStorage<any>> as any;
|
} satisfies Partial<AccountLoginStorage<any>> as any;
|
||||||
|
|
||||||
initializer = new V6MigrationInitializer({
|
initializer = new V6MigrationInitializer({
|
||||||
versionKey,
|
versionKey,
|
||||||
versionStorage,
|
setupStorage,
|
||||||
accountStorage,
|
accountStorage,
|
||||||
clientCredentialsStorage,
|
clientCredentialsStorage,
|
||||||
cleanupStorages: [ accountStorage, clientCredentialsStorage, forgotPasswordStorage ],
|
cleanupStorages: [ accountStorage, clientCredentialsStorage, forgotPasswordStorage ],
|
||||||
newStorage,
|
newAccountStorage,
|
||||||
|
newSetupStorage,
|
||||||
skipConfirmation: true,
|
skipConfirmation: true,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -107,8 +117,8 @@ describe('A V6MigrationInitializer', (): void => {
|
|||||||
it('migrates the data.', async(): Promise<void> => {
|
it('migrates the data.', async(): Promise<void> => {
|
||||||
await expect(initializer.handle()).resolves.toBeUndefined();
|
await expect(initializer.handle()).resolves.toBeUndefined();
|
||||||
|
|
||||||
expect(versionStorage.get).toHaveBeenCalledTimes(1);
|
expect(setupStorage.get).toHaveBeenCalledTimes(1);
|
||||||
expect(versionStorage.get).toHaveBeenLastCalledWith(versionKey);
|
expect(setupStorage.get).toHaveBeenLastCalledWith(versionKey);
|
||||||
|
|
||||||
expect(accountStorage.get).toHaveBeenCalledTimes(2);
|
expect(accountStorage.get).toHaveBeenCalledTimes(2);
|
||||||
expect(accountStorage.get).toHaveBeenCalledWith(webId);
|
expect(accountStorage.get).toHaveBeenCalledWith(webId);
|
||||||
@ -125,43 +135,50 @@ describe('A V6MigrationInitializer', (): void => {
|
|||||||
expect(forgotPasswordStorage.delete).toHaveBeenCalledTimes(1);
|
expect(forgotPasswordStorage.delete).toHaveBeenCalledTimes(1);
|
||||||
expect(forgotPasswordStorage.delete).toHaveBeenCalledWith('forgot');
|
expect(forgotPasswordStorage.delete).toHaveBeenCalledWith('forgot');
|
||||||
|
|
||||||
expect(newStorage.create).toHaveBeenCalledTimes(11);
|
expect(newAccountStorage.create).toHaveBeenCalledTimes(11);
|
||||||
expect(newStorage.create).toHaveBeenCalledWith(ACCOUNT_TYPE, {});
|
expect(newAccountStorage.create).toHaveBeenCalledWith(ACCOUNT_TYPE, {});
|
||||||
expect(newStorage.create).toHaveBeenCalledWith(PASSWORD_STORAGE_TYPE,
|
expect(newAccountStorage.create).toHaveBeenCalledWith(PASSWORD_STORAGE_TYPE,
|
||||||
{ email: 'email@example.com', password: '123', verified: true, accountId: 'account-id' });
|
{ email: 'email@example.com', password: '123', verified: true, accountId: 'account-id' });
|
||||||
expect(newStorage.create).toHaveBeenCalledWith(PASSWORD_STORAGE_TYPE,
|
expect(newAccountStorage.create).toHaveBeenCalledWith(PASSWORD_STORAGE_TYPE,
|
||||||
{ email: 'email2@example.com', password: '1234', verified: true, accountId: 'account-id' });
|
{ email: 'email2@example.com', password: '1234', verified: true, accountId: 'account-id' });
|
||||||
expect(newStorage.create).toHaveBeenCalledWith(WEBID_STORAGE_TYPE, { webId, accountId: 'account-id' });
|
expect(newAccountStorage.create).toHaveBeenCalledWith(WEBID_STORAGE_TYPE, { webId, accountId: 'account-id' });
|
||||||
expect(newStorage.create).toHaveBeenCalledWith(WEBID_STORAGE_TYPE, { webId: webId2, accountId: 'account-id' });
|
expect(newAccountStorage.create).toHaveBeenCalledWith(WEBID_STORAGE_TYPE,
|
||||||
expect(newStorage.create).toHaveBeenCalledWith(POD_STORAGE_TYPE, { baseUrl: 'http://example.com/test/', accountId: 'account-id' });
|
{ webId: webId2, accountId: 'account-id' });
|
||||||
expect(newStorage.create).toHaveBeenCalledWith(POD_STORAGE_TYPE, { baseUrl: 'http://example.com/test2/', accountId: 'account-id' });
|
expect(newAccountStorage.create).toHaveBeenCalledWith(POD_STORAGE_TYPE, { baseUrl: 'http://example.com/test/', accountId: 'account-id' });
|
||||||
expect(newStorage.create).toHaveBeenCalledWith(OWNER_STORAGE_TYPE, { webId, podId: 'pod-id', visible: false });
|
expect(newAccountStorage.create).toHaveBeenCalledWith(POD_STORAGE_TYPE, { baseUrl: 'http://example.com/test2/', accountId: 'account-id' });
|
||||||
expect(newStorage.create).toHaveBeenCalledWith(OWNER_STORAGE_TYPE,
|
expect(newAccountStorage.create).toHaveBeenCalledWith(OWNER_STORAGE_TYPE,
|
||||||
|
{ webId, podId: 'pod-id', visible: false });
|
||||||
|
expect(newAccountStorage.create).toHaveBeenCalledWith(OWNER_STORAGE_TYPE,
|
||||||
{ webId: webId2, podId: 'pod-id', visible: false });
|
{ webId: webId2, podId: 'pod-id', visible: false });
|
||||||
expect(newStorage.create).toHaveBeenCalledWith(CLIENT_CREDENTIALS_STORAGE_TYPE,
|
expect(newAccountStorage.create).toHaveBeenCalledWith(CLIENT_CREDENTIALS_STORAGE_TYPE,
|
||||||
{ label: 'token', secret: 'secret!', webId, accountId: 'account-id' });
|
{ label: 'token', secret: 'secret!', webId, accountId: 'account-id' });
|
||||||
|
|
||||||
|
expect(newSetupStorage.set).toHaveBeenCalledTimes(1);
|
||||||
|
expect(newSetupStorage.set).toHaveBeenLastCalledWith('version', '6.0.0');
|
||||||
|
expect(setupStorage.delete).toHaveBeenCalledTimes(1);
|
||||||
|
expect(setupStorage.delete).toHaveBeenLastCalledWith('version');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does nothing if the server has no stored version number.', async(): Promise<void> => {
|
it('does nothing if the server has no stored version number.', async(): Promise<void> => {
|
||||||
versionStorage.get.mockResolvedValueOnce(undefined);
|
setupStorage.get.mockResolvedValueOnce(undefined);
|
||||||
await expect(initializer.handle()).resolves.toBeUndefined();
|
await expect(initializer.handle()).resolves.toBeUndefined();
|
||||||
expect(accountStorage.get).toHaveBeenCalledTimes(0);
|
expect(accountStorage.get).toHaveBeenCalledTimes(0);
|
||||||
expect(newStorage.create).toHaveBeenCalledTimes(0);
|
expect(newAccountStorage.create).toHaveBeenCalledTimes(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does nothing if stored version is more than 6.', async(): Promise<void> => {
|
it('does nothing if stored version is more than 6.', async(): Promise<void> => {
|
||||||
versionStorage.get.mockResolvedValueOnce('7.0.0');
|
setupStorage.get.mockResolvedValueOnce('7.0.0');
|
||||||
await expect(initializer.handle()).resolves.toBeUndefined();
|
await expect(initializer.handle()).resolves.toBeUndefined();
|
||||||
expect(accountStorage.get).toHaveBeenCalledTimes(0);
|
expect(accountStorage.get).toHaveBeenCalledTimes(0);
|
||||||
expect(newStorage.create).toHaveBeenCalledTimes(0);
|
expect(newAccountStorage.create).toHaveBeenCalledTimes(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('ignores accounts and credentials for which it cannot find the settings.', async(): Promise<void> => {
|
it('ignores accounts and credentials for which it cannot find the settings.', async(): Promise<void> => {
|
||||||
delete settings[webId];
|
delete settings[webId];
|
||||||
await expect(initializer.handle()).resolves.toBeUndefined();
|
await expect(initializer.handle()).resolves.toBeUndefined();
|
||||||
|
|
||||||
expect(versionStorage.get).toHaveBeenCalledTimes(1);
|
expect(setupStorage.get).toHaveBeenCalledTimes(1);
|
||||||
expect(versionStorage.get).toHaveBeenLastCalledWith(versionKey);
|
expect(setupStorage.get).toHaveBeenLastCalledWith(versionKey);
|
||||||
|
|
||||||
expect(accountStorage.get).toHaveBeenCalledTimes(2);
|
expect(accountStorage.get).toHaveBeenCalledTimes(2);
|
||||||
expect(accountStorage.get).toHaveBeenCalledWith(webId);
|
expect(accountStorage.get).toHaveBeenCalledWith(webId);
|
||||||
@ -171,14 +188,20 @@ describe('A V6MigrationInitializer', (): void => {
|
|||||||
expect(accountStorage.delete).toHaveBeenCalledWith('account');
|
expect(accountStorage.delete).toHaveBeenCalledWith('account');
|
||||||
expect(accountStorage.delete).toHaveBeenCalledWith('account2');
|
expect(accountStorage.delete).toHaveBeenCalledWith('account2');
|
||||||
|
|
||||||
expect(newStorage.create).toHaveBeenCalledTimes(5);
|
expect(newAccountStorage.create).toHaveBeenCalledTimes(5);
|
||||||
expect(newStorage.create).toHaveBeenCalledWith(ACCOUNT_TYPE, {});
|
expect(newAccountStorage.create).toHaveBeenCalledWith(ACCOUNT_TYPE, {});
|
||||||
expect(newStorage.create).toHaveBeenCalledWith(PASSWORD_STORAGE_TYPE,
|
expect(newAccountStorage.create).toHaveBeenCalledWith(PASSWORD_STORAGE_TYPE,
|
||||||
{ email: 'email2@example.com', password: '1234', verified: true, accountId: 'account-id' });
|
{ email: 'email2@example.com', password: '1234', verified: true, accountId: 'account-id' });
|
||||||
expect(newStorage.create).toHaveBeenCalledWith(WEBID_STORAGE_TYPE, { webId: webId2, accountId: 'account-id' });
|
expect(newAccountStorage.create).toHaveBeenCalledWith(WEBID_STORAGE_TYPE,
|
||||||
expect(newStorage.create).toHaveBeenCalledWith(POD_STORAGE_TYPE, { baseUrl: 'http://example.com/test2/', accountId: 'account-id' });
|
{ webId: webId2, accountId: 'account-id' });
|
||||||
expect(newStorage.create).toHaveBeenCalledWith(OWNER_STORAGE_TYPE,
|
expect(newAccountStorage.create).toHaveBeenCalledWith(POD_STORAGE_TYPE, { baseUrl: 'http://example.com/test2/', accountId: 'account-id' });
|
||||||
|
expect(newAccountStorage.create).toHaveBeenCalledWith(OWNER_STORAGE_TYPE,
|
||||||
{ webId: webId2, podId: 'pod-id', visible: false });
|
{ webId: webId2, podId: 'pod-id', visible: false });
|
||||||
|
|
||||||
|
expect(newSetupStorage.set).toHaveBeenCalledTimes(1);
|
||||||
|
expect(newSetupStorage.set).toHaveBeenLastCalledWith('version', '6.0.0');
|
||||||
|
expect(setupStorage.delete).toHaveBeenCalledTimes(1);
|
||||||
|
expect(setupStorage.delete).toHaveBeenLastCalledWith('version');
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('with prompts enabled', (): void => {
|
describe('with prompts enabled', (): void => {
|
||||||
@ -187,11 +210,12 @@ describe('A V6MigrationInitializer', (): void => {
|
|||||||
|
|
||||||
initializer = new V6MigrationInitializer({
|
initializer = new V6MigrationInitializer({
|
||||||
versionKey,
|
versionKey,
|
||||||
versionStorage,
|
setupStorage,
|
||||||
accountStorage,
|
accountStorage,
|
||||||
clientCredentialsStorage,
|
clientCredentialsStorage,
|
||||||
cleanupStorages: [ accountStorage, clientCredentialsStorage, forgotPasswordStorage ],
|
cleanupStorages: [ accountStorage, clientCredentialsStorage, forgotPasswordStorage ],
|
||||||
newStorage,
|
newAccountStorage,
|
||||||
|
newSetupStorage,
|
||||||
skipConfirmation: false,
|
skipConfirmation: false,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -200,15 +224,16 @@ describe('A V6MigrationInitializer', (): void => {
|
|||||||
await expect(initializer.handle()).resolves.toBeUndefined();
|
await expect(initializer.handle()).resolves.toBeUndefined();
|
||||||
|
|
||||||
expect(questionMock).toHaveBeenCalledTimes(1);
|
expect(questionMock).toHaveBeenCalledTimes(1);
|
||||||
expect(questionMock.mock.invocationCallOrder[0]).toBeLessThan(newStorage.create.mock.invocationCallOrder[0]);
|
expect(questionMock.mock.invocationCallOrder[0])
|
||||||
|
.toBeLessThan(newAccountStorage.create.mock.invocationCallOrder[0]);
|
||||||
|
|
||||||
expect(newStorage.create).toHaveBeenCalledTimes(11);
|
expect(newAccountStorage.create).toHaveBeenCalledTimes(11);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('throws an error to stop the server if no positive answer is received.', async(): Promise<void> => {
|
it('throws an error to stop the server if no positive answer is received.', async(): Promise<void> => {
|
||||||
questionMock.mockImplementation((input, callback): void => callback('n'));
|
questionMock.mockImplementation((input, callback): void => callback('n'));
|
||||||
await expect(initializer.handle()).rejects.toThrow('Stopping server as migration was cancelled.');
|
await expect(initializer.handle()).rejects.toThrow('Stopping server as migration was cancelled.');
|
||||||
expect(newStorage.create).toHaveBeenCalledTimes(0);
|
expect(newAccountStorage.create).toHaveBeenCalledTimes(0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user