Refactor vault sql to include release info (#955)

This commit is contained in:
Leendert de Borst
2025-06-23 15:29:14 +02:00
committed by Leendert de Borst
parent 41b2a959ed
commit 822b95d940
21 changed files with 355 additions and 334 deletions

View File

@@ -1,16 +1,17 @@
import { describe, it, expect } from 'vitest';
import { VaultSqlGenerator } from '../sql/VaultSqlGenerator.js';
import { CURRENT_VAULT_VERSION } from '../types/VaultVersion.js';
import { VaultSqlGenerator } from '../sql/VaultSqlGenerator';
describe('VaultSqlGenerator', () => {
const generator = new VaultSqlGenerator();
describe('getCreateVaultSql', () => {
it('should return SQL commands for creating a new vault', () => {
const result = VaultSqlGenerator.getCreateVaultSql();
const result = generator.getCreateVaultSql();
expect(result.success).toBe(true);
expect(result.sqlCommands.length).toBeGreaterThan(0);
expect(result.version).toBe(CURRENT_VAULT_VERSION.version);
expect(result.migrationNumber).toBe(CURRENT_VAULT_VERSION.migrationNumber);
expect(result.version).toBe(generator.getLatestVersion().version);
expect(result.migrationNumber).toBe(generator.getLatestVersion().revision);
// Should include PRAGMA and schema creation
expect(result.sqlCommands[0]).toBe('PRAGMA foreign_keys = ON;');
@@ -21,16 +22,16 @@ describe('VaultSqlGenerator', () => {
describe('getUpgradeVaultSql', () => {
it('should return empty commands when vault is already at target version', () => {
const result = VaultSqlGenerator.getUpgradeVaultSql(CURRENT_VAULT_VERSION.migrationNumber);
const result = generator.getUpgradeVaultSql(generator.getLatestVersion().revision);
expect(result.success).toBe(true);
expect(result.sqlCommands).toEqual([]);
expect(result.version).toBe(CURRENT_VAULT_VERSION.version);
expect(result.migrationNumber).toBe(CURRENT_VAULT_VERSION.migrationNumber);
expect(result.version).toBe(generator.getLatestVersion().version);
expect(result.migrationNumber).toBe(generator.getLatestVersion().revision);
});
it('should return upgrade commands for older version', () => {
const result = VaultSqlGenerator.getUpgradeVaultSql(1, 3); // Upgrade from v1.0.0 to v1.1.0
const result = generator.getUpgradeVaultSql(1, 3); // Upgrade from v1.0.0 to v1.1.0
expect(result.success).toBe(true);
expect(result.sqlCommands.length).toBeGreaterThan(0);
@@ -41,7 +42,7 @@ describe('VaultSqlGenerator', () => {
});
it('should handle invalid target migration number', () => {
const result = VaultSqlGenerator.getUpgradeVaultSql(1, 999);
const result = generator.getUpgradeVaultSql(1, 999);
expect(result.success).toBe(false);
expect(result.error).toContain('not found');
@@ -50,14 +51,14 @@ describe('VaultSqlGenerator', () => {
describe('getUpgradeToVersionSql', () => {
it('should upgrade to specific version', () => {
const result = VaultSqlGenerator.getUpgradeToVersionSql(1, '1.2.0');
const result = generator.getUpgradeToVersionSql(1, '1.2.0');
expect(result.success).toBe(true);
expect(result.sqlCommands.length).toBeGreaterThan(0);
});
it('should handle invalid version', () => {
const result = VaultSqlGenerator.getUpgradeToVersionSql(1, '99.99.99');
const result = generator.getUpgradeToVersionSql(1, '99.99.99');
expect(result.success).toBe(false);
expect(result.error).toContain('not found');
@@ -66,7 +67,7 @@ describe('VaultSqlGenerator', () => {
describe('getVersionCheckSql', () => {
it('should return SQL commands to check vault version', () => {
const commands = VaultSqlGenerator.getVersionCheckSql();
const commands = generator.getVersionCheckSql();
expect(commands.length).toBe(3);
expect(commands[0]).toContain('sqlite_master');
@@ -77,7 +78,7 @@ describe('VaultSqlGenerator', () => {
describe('getVaultValidationSql', () => {
it('should return SQL to validate vault structure', () => {
const sql = VaultSqlGenerator.getVaultValidationSql();
const sql = generator.getVaultValidationSql();
expect(sql).toContain('sqlite_master');
expect(sql).toContain('Aliases');
@@ -88,15 +89,15 @@ describe('VaultSqlGenerator', () => {
describe('parseVaultVersionInfo', () => {
it('should parse vault version info correctly', () => {
const info = VaultSqlGenerator.parseVaultVersionInfo(true, '1.2.0', '4');
const info = generator.parseVaultVersionInfo(true, '1.2.0', '4');
expect(info.currentVersion).toBe('1.2.0');
expect(info.currentMigrationNumber).toBe(4);
expect(info.needsUpgrade).toBe(info.currentMigrationNumber < CURRENT_VAULT_VERSION.migrationNumber);
expect(info.needsUpgrade).toBe(info.currentMigrationNumber < generator.getLatestVersion().revision);
});
it('should handle missing Settings table', () => {
const info = VaultSqlGenerator.parseVaultVersionInfo(false);
const info = generator.parseVaultVersionInfo(false);
expect(info.currentVersion).toBe('0.0.0');
expect(info.currentMigrationNumber).toBe(0);
@@ -104,7 +105,7 @@ describe('VaultSqlGenerator', () => {
});
it('should handle Settings table without version info', () => {
const info = VaultSqlGenerator.parseVaultVersionInfo(true);
const info = generator.parseVaultVersionInfo(true);
expect(info.currentVersion).toBe('1.0.0');
expect(info.currentMigrationNumber).toBe(1);
@@ -114,21 +115,21 @@ describe('VaultSqlGenerator', () => {
describe('validateVaultStructure', () => {
it('should validate vault with all required tables', () => {
const tables = ['Aliases', 'Services', 'Credentials', 'Passwords', 'Settings'];
const isValid = VaultSqlGenerator.validateVaultStructure(tables);
const isValid = generator.validateVaultStructure(tables);
expect(isValid).toBe(true);
});
it('should reject vault with missing core tables', () => {
const tables = ['Aliases', 'Services'];
const isValid = VaultSqlGenerator.validateVaultStructure(tables);
const isValid = generator.validateVaultStructure(tables);
expect(isValid).toBe(false);
});
it('should handle case-insensitive table names', () => {
const tables = ['aliases', 'services', 'credentials', 'passwords'];
const isValid = VaultSqlGenerator.validateVaultStructure(tables);
const isValid = generator.validateVaultStructure(tables);
expect(isValid).toBe(true);
});
@@ -136,27 +137,27 @@ describe('VaultSqlGenerator', () => {
describe('utility methods', () => {
it('should return available versions', () => {
const versions = VaultSqlGenerator.getAvailableVersions();
const versions = generator.getAllVersions();
expect(versions.length).toBeGreaterThan(0);
expect(versions[0].version).toBe('1.0.0');
});
it('should return current version', () => {
const version = VaultSqlGenerator.getCurrentVersion();
const version = generator.getLatestVersion();
expect(version).toEqual(CURRENT_VAULT_VERSION);
expect(version).toEqual(generator.getLatestVersion());
});
it('should return migration SQL by number', () => {
const sql = VaultSqlGenerator.getMigrationSql(1);
const sql = generator.getMigrationSql(1);
expect(sql).toBeDefined();
expect(sql).toContain('CREATE TABLE');
});
it('should return complete schema SQL', () => {
const sql = VaultSqlGenerator.getCompleteSchemaeSql();
const sql = generator.getCompleteSchemaSql();
expect(sql).toBeDefined();
expect(sql).toContain('CREATE TABLE "Aliases"');

View File

@@ -234,14 +234,14 @@ export class VaultSqlGenerator {
/**
* Get all available vault versions
*/
getAvailableVersions(): IVaultVersion[] {
getAllVersions(): IVaultVersion[] {
return [...VAULT_VERSIONS];
}
/**
* Get current/latest vault version info
*/
getCurrentVersion(): IVaultVersion {
getLatestVersion(): IVaultVersion {
return VAULT_VERSIONS[VAULT_VERSIONS.length - 1];
}
@@ -255,7 +255,7 @@ export class VaultSqlGenerator {
/**
* Get complete schema SQL for creating new vault
*/
getCompleteSchemaeSql(): string {
getCompleteSchemaSql(): string {
return COMPLETE_SCHEMA_SQL;
}
}

View File

@@ -6,61 +6,72 @@
import { IVaultVersion } from "../types/VaultVersion";
/**
* Available vault versions in chronological order
* All vault migrations/versions in chronological order. When adding a new migration, make sure to
* update the "releaseVersion" field to the correct AliasVault release version that introduced this
* migration.
*/
export const VAULT_VERSIONS: IVaultVersion[] = [
{
revision: 1,
version: '1.0.1',
description: 'Empty Test Migration',
releaseDate: '2024-07-08'
releaseDate: '2024-07-08',
releaseVersion: '0.2.0',
},
{
revision: 2,
version: '1.0.2',
description: 'Change Email Column',
releaseDate: '2024-07-11'
releaseDate: '2024-07-11',
releaseVersion: '0.3.0',
},
{
revision: 3,
version: '1.1.0',
description: 'Add Pki Tables',
releaseDate: '2024-07-29'
releaseDate: '2024-07-29',
releaseVersion: '0.4.0',
},
{
revision: 4,
version: '1.2.0',
description: 'Add Settings Table',
releaseDate: '2024-08-05'
releaseDate: '2024-08-05',
releaseVersion: '0.4.0',
},
{
revision: 5,
version: '1.3.0',
description: 'Update Identity Structure',
releaseDate: '2024-08-05'
releaseDate: '2024-08-05',
releaseVersion: '0.5.0',
},
{
revision: 6,
version: '1.3.1',
description: 'Make Username Optional',
releaseDate: '2024-08-12'
releaseDate: '2024-08-12',
releaseVersion: '0.5.0',
},
{
revision: 7,
version: '1.4.0',
description: 'Add Sync Support',
releaseDate: '2024-09-16'
releaseDate: '2024-09-16',
releaseVersion: '0.6.0',
},
{
revision: 8,
version: '1.4.1',
description: 'Rename Attachments Plural',
releaseDate: '2024-09-17'
releaseDate: '2024-09-17',
releaseVersion: '0.6.0',
},
{
revision: 9,
version: '1.5.0',
description: 'Add Totp Codes',
releaseDate: '2025-03-10'
releaseDate: '2025-03-10',
releaseVersion: '0.14.0',
},
];

View File

@@ -18,7 +18,15 @@ export interface IVaultVersion {
description: string;
/**
* Release date
* Date that this vault version was released.
*/
releaseDate: string;
/**
* The AliasVault release that this vault version was introduced in (e.g., "0.14.0").
* This value is shown to the user in the UI instead of the actual vault version in order to
* avoid potential confusion. The "version" field is the actual vault database version. While
* this field is just for display purposes.
*/
releaseVersion: string;
}