feat: implement ActiveDid migration to active_identity table
- Add $getActiveIdentity() method to PlatformServiceMixin interface - Update HomeView.vue to use new active_identity API methods - Update ContactsView.vue to use new active_identity API methods - Fix apiServer default handling in PlatformServiceMixin - Ensure DEFAULT_ENDORSER_API_SERVER is used when apiServer is empty - Add comprehensive logging for debugging ActiveDid migration - Resolve TypeScript interface issues with Vue mixins
This commit is contained in:
@@ -45,7 +45,6 @@ import type {
|
||||
PlatformCapabilities,
|
||||
} from "@/services/PlatformService";
|
||||
import {
|
||||
MASTER_SETTINGS_KEY,
|
||||
type Settings,
|
||||
type SettingsWithJsonStrings,
|
||||
} from "@/db/tables/settings";
|
||||
@@ -58,8 +57,6 @@ import {
|
||||
generateInsertStatement,
|
||||
generateUpdateStatement,
|
||||
} from "@/utils/sqlHelpers";
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
import { ActiveIdentity } from "@/db/tables/activeIdentity";
|
||||
|
||||
// =================================================
|
||||
// TYPESCRIPT INTERFACES
|
||||
@@ -198,6 +195,80 @@ export const PlatformServiceMixin = {
|
||||
// SELF-CONTAINED UTILITY METHODS (no databaseUtil dependency)
|
||||
// =================================================
|
||||
|
||||
/**
|
||||
* Ensure active_identity table is populated with data from settings
|
||||
* This is a one-time fix for the migration gap
|
||||
*/
|
||||
async $ensureActiveIdentityPopulated(): Promise<void> {
|
||||
try {
|
||||
logger.info(
|
||||
"[PlatformServiceMixin] $ensureActiveIdentityPopulated() called",
|
||||
);
|
||||
|
||||
// Check if active_identity has data
|
||||
const activeIdentity = await this.$dbQuery(
|
||||
"SELECT activeDid FROM active_identity WHERE id = 1",
|
||||
);
|
||||
|
||||
const currentActiveDid = activeIdentity?.values?.[0]?.[0] as string;
|
||||
logger.info(
|
||||
"[PlatformServiceMixin] Current active_identity table state:",
|
||||
{ currentActiveDid, hasData: !!currentActiveDid },
|
||||
);
|
||||
|
||||
if (!currentActiveDid) {
|
||||
logger.info(
|
||||
"[PlatformServiceMixin] Active identity table empty, populating from settings",
|
||||
);
|
||||
|
||||
// Get activeDid from settings (any row with accountDid)
|
||||
const settings = await this.$dbQuery(
|
||||
"SELECT accountDid FROM settings WHERE accountDid IS NOT NULL LIMIT 1",
|
||||
);
|
||||
|
||||
const settingsAccountDid = settings?.values?.[0]?.[0] as string;
|
||||
logger.info("[PlatformServiceMixin] Found settings accountDid:", {
|
||||
settingsAccountDid,
|
||||
});
|
||||
|
||||
if (settingsAccountDid) {
|
||||
await this.$dbExec(
|
||||
"UPDATE active_identity SET activeDid = ?, lastUpdated = datetime('now') WHERE id = 1",
|
||||
[settingsAccountDid],
|
||||
);
|
||||
logger.info(
|
||||
`[PlatformServiceMixin] Populated active_identity with: ${settingsAccountDid}`,
|
||||
);
|
||||
} else {
|
||||
// If no settings found, try to get any account DID
|
||||
const accounts = await this.$dbQuery(
|
||||
"SELECT did FROM accounts LIMIT 1",
|
||||
);
|
||||
const accountDid = accounts?.values?.[0]?.[0] as string;
|
||||
|
||||
if (accountDid) {
|
||||
await this.$dbExec(
|
||||
"UPDATE active_identity SET activeDid = ?, lastUpdated = datetime('now') WHERE id = 1",
|
||||
[accountDid],
|
||||
);
|
||||
logger.info(
|
||||
`[PlatformServiceMixin] Populated active_identity with account DID: ${accountDid}`,
|
||||
);
|
||||
} else {
|
||||
logger.warn(
|
||||
"[PlatformServiceMixin] No accountDid found in settings or accounts table",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
logger.warn(
|
||||
"[PlatformServiceMixin] Failed to populate active_identity:",
|
||||
error,
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Update the current activeDid and trigger change detection
|
||||
* This method should be called when the user switches identities
|
||||
@@ -213,22 +284,18 @@ export const PlatformServiceMixin = {
|
||||
`[PlatformServiceMixin] ActiveDid updated from ${oldDid} to ${newDid}`,
|
||||
);
|
||||
|
||||
// Dual-write to both tables for backward compatibility
|
||||
// Write only to active_identity table (single source of truth)
|
||||
try {
|
||||
await this.$dbExec(
|
||||
"UPDATE active_identity SET activeDid = ?, lastUpdated = datetime('now') WHERE id = 1",
|
||||
[newDid || ""],
|
||||
);
|
||||
await this.$dbExec("UPDATE settings SET activeDid = ? WHERE id = ?", [
|
||||
newDid || "",
|
||||
MASTER_SETTINGS_KEY,
|
||||
]);
|
||||
logger.debug(
|
||||
`[PlatformServiceMixin] ActiveDid dual-write completed for ${newDid}`,
|
||||
`[PlatformServiceMixin] ActiveDid updated in active_identity table: ${newDid}`,
|
||||
);
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
`[PlatformServiceMixin] Error in dual-write for activeDid ${newDid}:`,
|
||||
`[PlatformServiceMixin] Error updating activeDid in active_identity table ${newDid}:`,
|
||||
error,
|
||||
);
|
||||
// Continue with in-memory update even if database write fails
|
||||
@@ -468,10 +535,18 @@ export const PlatformServiceMixin = {
|
||||
fallback: Settings | null = null,
|
||||
): Promise<Settings | null> {
|
||||
try {
|
||||
// Master settings: query by id
|
||||
// Get current active identity
|
||||
const activeIdentity = await this.$getActiveIdentity();
|
||||
const activeDid = activeIdentity.activeDid;
|
||||
|
||||
if (!activeDid) {
|
||||
return fallback;
|
||||
}
|
||||
|
||||
// Get identity-specific settings
|
||||
const result = await this.$dbQuery(
|
||||
"SELECT * FROM settings WHERE id = ?",
|
||||
[MASTER_SETTINGS_KEY],
|
||||
"SELECT * FROM settings WHERE accountDid = ?",
|
||||
[activeDid],
|
||||
);
|
||||
|
||||
if (!result?.values?.length) {
|
||||
@@ -508,7 +583,6 @@ export const PlatformServiceMixin = {
|
||||
* Handles the common pattern of layered settings
|
||||
*/
|
||||
async $getMergedSettings(
|
||||
defaultKey: string,
|
||||
accountDid?: string,
|
||||
defaultFallback: Settings = {},
|
||||
): Promise<Settings> {
|
||||
@@ -564,7 +638,6 @@ export const PlatformServiceMixin = {
|
||||
return mergedSettings;
|
||||
} catch (error) {
|
||||
logger.error(`[Settings Trace] ❌ Failed to get merged settings:`, {
|
||||
defaultKey,
|
||||
accountDid,
|
||||
error,
|
||||
});
|
||||
@@ -578,12 +651,29 @@ export const PlatformServiceMixin = {
|
||||
*/
|
||||
async $getActiveIdentity(): Promise<{ activeDid: string }> {
|
||||
try {
|
||||
logger.info(
|
||||
"[PlatformServiceMixin] $getActiveIdentity() called - API layer verification",
|
||||
);
|
||||
|
||||
// Ensure the table is populated before reading
|
||||
await this.$ensureActiveIdentityPopulated();
|
||||
|
||||
logger.debug(
|
||||
"[PlatformServiceMixin] Getting active identity from active_identity table",
|
||||
);
|
||||
const result = await this.$dbQuery(
|
||||
"SELECT activeDid FROM active_identity WHERE id = 1",
|
||||
);
|
||||
|
||||
if (result?.values?.length) {
|
||||
const activeDid = result.values[0][0] as string;
|
||||
logger.debug("[PlatformServiceMixin] Active identity found:", {
|
||||
activeDid,
|
||||
});
|
||||
logger.info(
|
||||
"[PlatformServiceMixin] $getActiveIdentity(): activeDid resolved",
|
||||
{ activeDid },
|
||||
);
|
||||
|
||||
// Validate activeDid exists in accounts
|
||||
if (activeDid) {
|
||||
@@ -593,9 +683,15 @@ export const PlatformServiceMixin = {
|
||||
);
|
||||
|
||||
if (accountExists?.values?.length) {
|
||||
logger.debug(
|
||||
"[PlatformServiceMixin] Active identity validated in accounts",
|
||||
);
|
||||
return { activeDid };
|
||||
} else {
|
||||
// Clear corrupted activeDid
|
||||
logger.warn(
|
||||
"[PlatformServiceMixin] Active identity not found in accounts, clearing",
|
||||
);
|
||||
await this.$dbExec(
|
||||
"UPDATE active_identity SET activeDid = '', lastUpdated = datetime('now') WHERE id = 1",
|
||||
);
|
||||
@@ -604,6 +700,9 @@ export const PlatformServiceMixin = {
|
||||
}
|
||||
}
|
||||
|
||||
logger.debug(
|
||||
"[PlatformServiceMixin] No active identity found, returning empty",
|
||||
);
|
||||
return { activeDid: "" };
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
@@ -825,14 +924,14 @@ export const PlatformServiceMixin = {
|
||||
return defaults;
|
||||
}
|
||||
|
||||
// FIXED: Remove forced override - respect user preferences
|
||||
// FIXED: Set default apiServer for all platforms, not just Electron
|
||||
// Only set default if no user preference exists
|
||||
if (!settings.apiServer && process.env.VITE_PLATFORM === "electron") {
|
||||
if (!settings.apiServer) {
|
||||
// Import constants dynamically to get platform-specific values
|
||||
const { DEFAULT_ENDORSER_API_SERVER } = await import(
|
||||
"../constants/app"
|
||||
);
|
||||
// Only set if user hasn't specified a preference
|
||||
// Set default for all platforms when apiServer is empty
|
||||
settings.apiServer = DEFAULT_ENDORSER_API_SERVER;
|
||||
}
|
||||
|
||||
@@ -858,10 +957,9 @@ export const PlatformServiceMixin = {
|
||||
return defaults;
|
||||
}
|
||||
|
||||
// Determine which DID to use - prioritize new active_identity table, fallback to settings
|
||||
// Get DID from active_identity table (single source of truth)
|
||||
const activeIdentity = await this.$getActiveIdentity();
|
||||
const targetDid =
|
||||
did || activeIdentity.activeDid || defaultSettings.activeDid;
|
||||
const targetDid = did || activeIdentity.activeDid;
|
||||
|
||||
// If no target DID, return default settings
|
||||
if (!targetDid) {
|
||||
@@ -870,27 +968,29 @@ export const PlatformServiceMixin = {
|
||||
|
||||
// Get merged settings using existing method
|
||||
const mergedSettings = await this.$getMergedSettings(
|
||||
MASTER_SETTINGS_KEY,
|
||||
targetDid,
|
||||
defaultSettings,
|
||||
);
|
||||
|
||||
// Ensure activeDid comes from new table when available
|
||||
if (activeIdentity.activeDid) {
|
||||
mergedSettings.activeDid = activeIdentity.activeDid;
|
||||
}
|
||||
// Set activeDid from active_identity table (single source of truth)
|
||||
mergedSettings.activeDid = activeIdentity.activeDid;
|
||||
logger.debug(
|
||||
"[PlatformServiceMixin] Using activeDid from active_identity table:",
|
||||
{ activeDid: activeIdentity.activeDid },
|
||||
);
|
||||
logger.info(
|
||||
"[PlatformServiceMixin] $accountSettings() returning activeDid:",
|
||||
{ activeDid: mergedSettings.activeDid },
|
||||
);
|
||||
|
||||
// FIXED: Remove forced override - respect user preferences
|
||||
// FIXED: Set default apiServer for all platforms, not just Electron
|
||||
// Only set default if no user preference exists
|
||||
if (
|
||||
!mergedSettings.apiServer &&
|
||||
process.env.VITE_PLATFORM === "electron"
|
||||
) {
|
||||
if (!mergedSettings.apiServer) {
|
||||
// Import constants dynamically to get platform-specific values
|
||||
const { DEFAULT_ENDORSER_API_SERVER } = await import(
|
||||
"../constants/app"
|
||||
);
|
||||
// Only set if user hasn't specified a preference
|
||||
// Set default for all platforms when apiServer is empty
|
||||
mergedSettings.apiServer = DEFAULT_ENDORSER_API_SERVER;
|
||||
}
|
||||
|
||||
@@ -928,16 +1028,36 @@ export const PlatformServiceMixin = {
|
||||
async $saveSettings(changes: Partial<Settings>): Promise<boolean> {
|
||||
try {
|
||||
// Remove fields that shouldn't be updated
|
||||
const { accountDid, id, ...safeChanges } = changes;
|
||||
const {
|
||||
accountDid,
|
||||
id,
|
||||
activeDid: activeDidField,
|
||||
...safeChanges
|
||||
} = changes;
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
void accountDid;
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
void id;
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
void activeDidField;
|
||||
|
||||
logger.debug(
|
||||
"[PlatformServiceMixin] $saveSettings - Original changes:",
|
||||
changes,
|
||||
);
|
||||
logger.debug(
|
||||
"[PlatformServiceMixin] $saveSettings - Safe changes:",
|
||||
safeChanges,
|
||||
);
|
||||
|
||||
if (Object.keys(safeChanges).length === 0) return true;
|
||||
|
||||
// Convert settings for database storage (handles searchBoxes conversion)
|
||||
const convertedChanges = this._convertSettingsForStorage(safeChanges);
|
||||
logger.debug(
|
||||
"[PlatformServiceMixin] $saveSettings - Converted changes:",
|
||||
convertedChanges,
|
||||
);
|
||||
|
||||
const setParts: string[] = [];
|
||||
const params: unknown[] = [];
|
||||
@@ -949,17 +1069,33 @@ export const PlatformServiceMixin = {
|
||||
}
|
||||
});
|
||||
|
||||
logger.debug(
|
||||
"[PlatformServiceMixin] $saveSettings - Set parts:",
|
||||
setParts,
|
||||
);
|
||||
logger.debug("[PlatformServiceMixin] $saveSettings - Params:", params);
|
||||
|
||||
if (setParts.length === 0) return true;
|
||||
|
||||
params.push(MASTER_SETTINGS_KEY);
|
||||
await this.$dbExec(
|
||||
`UPDATE settings SET ${setParts.join(", ")} WHERE id = ?`,
|
||||
params,
|
||||
);
|
||||
// Get current active DID and update that identity's settings
|
||||
const activeIdentity = await this.$getActiveIdentity();
|
||||
const currentActiveDid = activeIdentity.activeDid;
|
||||
|
||||
if (currentActiveDid) {
|
||||
params.push(currentActiveDid);
|
||||
await this.$dbExec(
|
||||
`UPDATE settings SET ${setParts.join(", ")} WHERE accountDid = ?`,
|
||||
params,
|
||||
);
|
||||
} else {
|
||||
logger.warn(
|
||||
"[PlatformServiceMixin] No active DID found, cannot save settings",
|
||||
);
|
||||
}
|
||||
|
||||
// Update activeDid tracking if it changed
|
||||
if (changes.activeDid !== undefined) {
|
||||
await this.$updateActiveDid(changes.activeDid);
|
||||
if (activeDidField !== undefined) {
|
||||
await this.$updateActiveDid(activeDidField);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -1409,13 +1545,16 @@ export const PlatformServiceMixin = {
|
||||
fields: string[],
|
||||
did?: string,
|
||||
): Promise<unknown[] | undefined> {
|
||||
// Use correct settings table schema
|
||||
const whereClause = did ? "WHERE accountDid = ?" : "WHERE id = ?";
|
||||
const params = did ? [did] : [MASTER_SETTINGS_KEY];
|
||||
// Use current active DID if no specific DID provided
|
||||
const targetDid = did || (await this.$getActiveIdentity()).activeDid;
|
||||
|
||||
if (!targetDid) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return await this.$one(
|
||||
`SELECT ${fields.join(", ")} FROM settings ${whereClause}`,
|
||||
params,
|
||||
`SELECT ${fields.join(", ")} FROM settings WHERE accountDid = ?`,
|
||||
[targetDid],
|
||||
);
|
||||
},
|
||||
|
||||
@@ -1655,7 +1794,6 @@ export const PlatformServiceMixin = {
|
||||
|
||||
// Get merged settings
|
||||
const mergedSettings = await this.$getMergedSettings(
|
||||
MASTER_SETTINGS_KEY,
|
||||
did,
|
||||
defaultSettings || {},
|
||||
);
|
||||
@@ -1697,6 +1835,7 @@ export interface IPlatformServiceMixin {
|
||||
accountDid?: string,
|
||||
defaultFallback?: Settings,
|
||||
): Promise<Settings>;
|
||||
$getActiveIdentity(): Promise<{ activeDid: string }>;
|
||||
$withTransaction<T>(callback: () => Promise<T>): Promise<T>;
|
||||
isCapacitor: boolean;
|
||||
isWeb: boolean;
|
||||
|
||||
Reference in New Issue
Block a user