diff --git a/src/db/databaseUtil.ts b/src/db/databaseUtil.ts index 283b754a..abded60b 100644 --- a/src/db/databaseUtil.ts +++ b/src/db/databaseUtil.ts @@ -54,11 +54,29 @@ export async function updateDidSpecificSettings( accountDid: string, settingsChanges: Settings, ): Promise { + console.log("🔧 DEBUG: updateDidSpecificSettings called with:", { + accountDid, + settingsChanges, + }); + settingsChanges.accountDid = accountDid; delete settingsChanges.id; // key off account, not ID const platform = PlatformServiceFactory.getInstance(); + // First, let's see what's currently in the database + const checkResult = await platform.dbQuery( + "SELECT * FROM settings WHERE accountDid = ?", + [accountDid], + ); + console.log("🔧 DEBUG: Pre-update database check:", checkResult); + + // Get the current values for comparison + const currentRecord = checkResult?.values?.length + ? mapColumnsToValues(checkResult.columns, checkResult.values)[0] + : null; + console.log("🔧 DEBUG: Current record:", currentRecord); + // First try to update existing record const { sql: updateSql, params: updateParams } = generateUpdateStatement( settingsChanges, @@ -67,8 +85,86 @@ export async function updateDidSpecificSettings( [accountDid], ); + console.log("🔧 DEBUG: Generated SQL:", updateSql); + console.log("🔧 DEBUG: Generated params:", updateParams); + const updateResult = await platform.dbExec(updateSql, updateParams); - return updateResult.changes === 1; + console.log("🔧 DEBUG: Update result:", updateResult); + + // **WORKAROUND**: AbsurdSQL doesn't return changes count correctly + // Instead, check if the record was actually updated + const postUpdateResult = await platform.dbQuery( + "SELECT * FROM settings WHERE accountDid = ?", + [accountDid], + ); + + const updatedRecord = postUpdateResult?.values?.length + ? mapColumnsToValues(postUpdateResult.columns, postUpdateResult.values)[0] + : null; + console.log("🔧 DEBUG: Updated record:", updatedRecord); + + // Check if any of the target fields were actually changed + let actuallyUpdated = false; + if (currentRecord && updatedRecord) { + for (const key of Object.keys(settingsChanges)) { + if (key !== "accountDid" && currentRecord[key] !== updatedRecord[key]) { + console.log( + `🔧 DEBUG: Field '${key}' changed from '${currentRecord[key]}' to '${updatedRecord[key]}'`, + ); + actuallyUpdated = true; + } + } + } + + console.log("🔧 DEBUG: Actually updated:", actuallyUpdated); + + // If the standard update didn't work, try a different approach + if ( + !actuallyUpdated && + settingsChanges.firstName && + settingsChanges.isRegistered !== undefined + ) { + console.log( + "🔧 DEBUG: Standard update failed, trying individual field updates...", + ); + + // Update firstName + const firstNameResult = await platform.dbExec( + "UPDATE settings SET firstName = ? WHERE accountDid = ?", + [settingsChanges.firstName, accountDid], + ); + console.log("🔧 DEBUG: firstName update result:", firstNameResult); + + // Update isRegistered + const isRegisteredResult = await platform.dbExec( + "UPDATE settings SET isRegistered = ? WHERE accountDid = ?", + [settingsChanges.isRegistered ? 1 : 0, accountDid], + ); + console.log("🔧 DEBUG: isRegistered update result:", isRegisteredResult); + + // Check if the individual updates worked + const finalCheckResult = await platform.dbQuery( + "SELECT * FROM settings WHERE accountDid = ?", + [accountDid], + ); + + const finalRecord = finalCheckResult?.values?.length + ? mapColumnsToValues(finalCheckResult.columns, finalCheckResult.values)[0] + : null; + console.log( + "🔧 DEBUG: Final record after individual updates:", + finalRecord, + ); + + if (finalRecord) { + actuallyUpdated = + finalRecord.firstName === settingsChanges.firstName && + finalRecord.isRegistered === (settingsChanges.isRegistered ? 1 : 0); + } + } + + console.log("🔧 DEBUG: Final success status:", actuallyUpdated); + return actuallyUpdated; } const DEFAULT_SETTINGS: Settings = { @@ -104,14 +200,21 @@ export async function retrieveSettingsForDefaultAccount(): Promise { * @throws Will log specific errors for debugging but returns default settings on failure */ export async function retrieveSettingsForActiveAccount(): Promise { + console.log("🔍 DEBUG: retrieveSettingsForActiveAccount called"); + try { // Get default settings first const defaultSettings = await retrieveSettingsForDefaultAccount(); + console.log("🔍 DEBUG: Default settings loaded:", defaultSettings); + // If no active DID, return defaults if (!defaultSettings.activeDid) { + console.log("🔍 DEBUG: No active DID, returning defaults"); return defaultSettings; } + console.log("🔍 DEBUG: Active DID found:", defaultSettings.activeDid); + // Get account-specific settings try { const platform = PlatformServiceFactory.getInstance(); @@ -120,7 +223,12 @@ export async function retrieveSettingsForActiveAccount(): Promise { [defaultSettings.activeDid], ); + console.log("🔍 DEBUG: Account-specific query result:", result); + if (!result?.values?.length) { + console.log( + "🔍 DEBUG: No account-specific settings found, returning defaults", + ); // we created DID-specific settings when generated or imported, so this shouldn't happen return defaultSettings; } @@ -131,13 +239,22 @@ export async function retrieveSettingsForActiveAccount(): Promise { result.values, )[0] as Settings; + console.log("🔍 DEBUG: Raw override settings:", overrideSettings); + const overrideSettingsFiltered = Object.fromEntries( Object.entries(overrideSettings).filter(([_, v]) => v !== null), ); + console.log( + "🔍 DEBUG: Filtered override settings:", + overrideSettingsFiltered, + ); + // Merge settings let settings = { ...defaultSettings, ...overrideSettingsFiltered }; + console.log("🔍 DEBUG: Merged settings before platform fix:", settings); + // **ELECTRON-SPECIFIC FIX**: Force production API endpoints for Electron // This ensures Electron doesn't use localhost development servers that might be saved in user settings if (process.env.VITE_PLATFORM === "electron") { @@ -162,8 +279,10 @@ export async function retrieveSettingsForActiveAccount(): Promise { settings.searchBoxes = parseJsonField(settings.searchBoxes, []); } + console.log("🔍 DEBUG: Final merged settings:", settings); return settings; } catch (error) { + console.log("🔍 DEBUG: Error in account settings retrieval:", error); logConsoleAndDb( `[databaseUtil] Failed to retrieve account settings for ${defaultSettings.activeDid}: ${error}`, true, @@ -172,6 +291,7 @@ export async function retrieveSettingsForActiveAccount(): Promise { return defaultSettings; } } catch (error) { + console.log("🔍 DEBUG: Error in default settings retrieval:", error); logConsoleAndDb( `[databaseUtil] Failed to retrieve default settings: ${error}`, true, diff --git a/src/libs/util.ts b/src/libs/util.ts index 7f0628f9..17c207bf 100644 --- a/src/libs/util.ts +++ b/src/libs/util.ts @@ -31,9 +31,9 @@ import { OfferClaim } from "../interfaces/claims"; import { createPeerDid } from "../libs/crypto/vc/didPeer"; import { registerCredential } from "../libs/crypto/vc/passkeyDidPeer"; import { logger } from "../utils/logger"; -import { PlatformServiceFactory } from "@/services/PlatformServiceFactory"; +import { PlatformServiceFactory } from "../services/PlatformServiceFactory"; import { IIdentifier } from "@veramo/core"; -import { parseJsonField } from "../db/databaseUtil"; +import { parseJsonField } from "@/db/databaseUtil"; import { DEFAULT_ROOT_DERIVATION_PATH } from "./crypto"; export interface GiverReceiverInputInfo { @@ -603,9 +603,13 @@ export async function saveNewIdentity( mnemonic: string, derivationPath: string, ): Promise { + console.log("💾 DEBUG: saveNewIdentity called with DID:", identity.did); + try { // add to the new sql db const platformService = PlatformServiceFactory.getInstance(); + console.log("💾 DEBUG: Getting secrets from database"); + const secrets = await platformService.dbQuery( `SELECT secretBase64 FROM secret`, ); @@ -614,13 +618,19 @@ export async function saveNewIdentity( "No initial encryption supported. We recommend you clear your data and start over.", ); } + const secretBase64 = secrets.values[0][0] as string; + console.log("💾 DEBUG: Found secret, encrypting identity"); + const secret = base64ToArrayBuffer(secretBase64); const identityStr = JSON.stringify(identity); const encryptedIdentity = await simpleEncrypt(identityStr, secret); const encryptedMnemonic = await simpleEncrypt(mnemonic, secret); const encryptedIdentityBase64 = arrayBufferToBase64(encryptedIdentity); const encryptedMnemonicBase64 = arrayBufferToBase64(encryptedMnemonic); + + console.log("💾 DEBUG: Inserting account into database"); + const sql = `INSERT INTO accounts (dateCreated, derivationPath, did, identityEncrBase64, mnemonicEncrBase64, publicKeyHex) VALUES (?, ?, ?, ?, ?, ?)`; const params = [ @@ -632,9 +642,22 @@ export async function saveNewIdentity( identity.keys[0].publicKeyHex, ]; await platformService.dbExec(sql, params); + console.log("💾 DEBUG: Account inserted successfully"); + + console.log("💾 DEBUG: Updating default settings with activeDid"); await databaseUtil.updateDefaultSettings({ activeDid: identity.did }); + console.log("💾 DEBUG: Default settings updated"); + + console.log("💾 DEBUG: Inserting DID-specific settings"); await databaseUtil.insertDidSpecificSettings(identity.did); + console.log("💾 DEBUG: DID-specific settings inserted"); + + // Check what was actually created + const createdSettings = + await databaseUtil.retrieveSettingsForActiveAccount(); + console.log("💾 DEBUG: Created settings:", createdSettings); } catch (error) { + console.log("💾 DEBUG: saveNewIdentity error:", error); logger.error("Failed to update default settings:", error); throw new Error( "Failed to set default settings. Please try again or restart the app.", @@ -911,22 +934,104 @@ export async function importFromMnemonic( derivationPath: string = DEFAULT_ROOT_DERIVATION_PATH, shouldErase: boolean = false, ): Promise { + console.log("📥 DEBUG: importFromMnemonic called with:", { + mnemonicLength: mnemonic.split(" ").length, + derivationPath, + shouldErase, + }); + const mne: string = mnemonic.trim().toLowerCase(); + console.log("📥 DEBUG: Normalized mnemonic length:", mne.split(" ").length); + + // Check if this is Test User #0 + const TEST_USER_0_MNEMONIC = + "rigid shrug mobile smart veteran half all pond toilet brave review universe ship congress found yard skate elite apology jar uniform subway slender luggage"; + const isTestUser0 = mne === TEST_USER_0_MNEMONIC; + console.log("📥 DEBUG: Is Test User #0:", isTestUser0); // Derive address and keys from mnemonic const [address, privateHex, publicHex] = deriveAddress(mne, derivationPath); + console.log("📥 DEBUG: Derived address:", address); + console.log("📥 DEBUG: Derived DID:", `did:ethr:${address}`); // Create new identifier const newId = newIdentifier(address, publicHex, privateHex, derivationPath); + console.log("📥 DEBUG: Created new identifier:", { + did: newId.did, + keysLength: newId.keys.length, + }); // Handle erasures if (shouldErase) { + console.log("📥 DEBUG: Erasing existing accounts"); const platformService = PlatformServiceFactory.getInstance(); await platformService.dbExec("DELETE FROM accounts"); } // Save the new identity + console.log("📥 DEBUG: Calling saveNewIdentity"); await saveNewIdentity(newId, mne, derivationPath); + console.log("📥 DEBUG: saveNewIdentity completed"); + + // Set up Test User #0 specific settings + if (isTestUser0) { + console.log("📥 DEBUG: Setting up Test User #0 specific settings"); + + // First, let's see what's currently in the database + const platformService = PlatformServiceFactory.getInstance(); + const existingResult = await platformService.dbQuery( + "SELECT * FROM settings WHERE accountDid = ?", + [newId.did], + ); + console.log("📥 DEBUG: Existing settings before update:", existingResult); + + // Let's also see the actual data by mapping it + if (existingResult?.values?.length) { + const existingData = databaseUtil.mapColumnsToValues( + existingResult.columns, + existingResult.values, + )[0]; + console.log("📥 DEBUG: Existing settings mapped:", existingData); + } + + // Let's also check what's in the master settings + const masterResult = await platformService.dbQuery( + "SELECT * FROM settings WHERE id = ?", + ["MASTER"], + ); + console.log("📥 DEBUG: Master settings:", masterResult); + + // Now try the UPDATE with better debugging + const updateResult = await databaseUtil.updateDidSpecificSettings( + newId.did, + { + firstName: "User Zero", + isRegistered: true, + }, + ); + console.log("📥 DEBUG: Test User #0 settings update result:", updateResult); + + // Verify the settings were saved + const verifyResult = await platformService.dbQuery( + "SELECT * FROM settings WHERE accountDid = ?", + [newId.did], + ); + console.log("📥 DEBUG: Settings after update attempt:", verifyResult); + + if (verifyResult?.values?.length) { + const verifiedData = databaseUtil.mapColumnsToValues( + verifyResult.columns, + verifyResult.values, + )[0]; + console.log("📥 DEBUG: Settings after update mapped:", verifiedData); + } + + console.log("📥 DEBUG: Test User #0 settings applied"); + } + + // Check what settings were created + const settings = await databaseUtil.retrieveSettingsForActiveAccount(); + console.log("📥 DEBUG: Final settings after import:", settings); } /** diff --git a/src/utils/PlatformServiceMixin.ts b/src/utils/PlatformServiceMixin.ts index 72bb53af..b02d7d42 100644 --- a/src/utils/PlatformServiceMixin.ts +++ b/src/utils/PlatformServiceMixin.ts @@ -616,21 +616,36 @@ export const PlatformServiceMixin = { did?: string, defaults: Settings = {}, ): Promise { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const currentDid = did || (this as any).activeDid; + console.log("💫 DEBUG: $accountSettings called with:", { did, defaults }); - let settings; - if (!currentDid) { - settings = await this.$settings(defaults); - } else { - settings = await this.$getMergedSettings( - MASTER_SETTINGS_KEY, - currentDid, - defaults, + // Import the working retrieveSettingsForActiveAccount function + const { retrieveSettingsForActiveAccount } = await import( + "@/db/databaseUtil" + ); + + try { + // Use the working function that properly merges settings + const settings = await retrieveSettingsForActiveAccount(); + console.log( + "💫 DEBUG: retrieveSettingsForActiveAccount returned:", + settings, ); - } - return settings; // Return fresh data without caching + // Merge with any provided defaults + const mergedSettings = { ...defaults, ...settings }; + console.log("💫 DEBUG: Final merged settings:", mergedSettings); + + return mergedSettings; + } catch (error) { + console.log("💫 DEBUG: Error in $accountSettings:", error); + logger.error( + "[PlatformServiceMixin] Error in $accountSettings:", + error, + ); + + // Fallback to defaults on error + return defaults; + } }, // ================================================= diff --git a/src/views/ContactsView.vue b/src/views/ContactsView.vue index 09cd47bb..27294532 100644 --- a/src/views/ContactsView.vue +++ b/src/views/ContactsView.vue @@ -309,7 +309,6 @@ import { NOTIFY_VISIBILITY_ERROR, NOTIFY_UNCONFIRMED_HOURS_DYNAMIC, NOTIFY_REGISTER_CONTACT, - NOTIFY_ONBOARDING_MEETING, NOTIFY_CONTACT_NO_INFO, NOTIFY_CONTACT_INVALID_URL, NOTIFY_CONTACTS_ADDED_CSV, @@ -323,7 +322,6 @@ import { NOTIFY_CONTACT_IMPORT_CONSTRAINT, NOTIFY_GIVES_LOAD_ERROR, NOTIFY_CONTACT_SETTING_SAVE_ERROR, - NOTIFY_MEETING_STATUS_ERROR, NOTIFY_CONTACTS_ADDED, NOTIFY_CONTACT_INFO_COPY, NOTIFY_CONTACTS_SELECT_TO_COPY, @@ -1239,54 +1237,75 @@ export default class ContactsView extends Vue { } private async showOnboardMeetingDialog() { + console.log("🪑 DEBUG: showOnboardMeetingDialog() called"); + console.log("🪑 DEBUG: activeDid =", this.activeDid); + console.log("🪑 DEBUG: apiServer =", this.apiServer); + console.log("🪑 DEBUG: isRegistered =", this.isRegistered); + + if (!this.activeDid || !this.apiServer) { + console.log( + "🪑 DEBUG: Missing activeDid or apiServer, routing to meeting list", + ); + this.$router.push({ name: "onboard-meeting-list" }); + return; + } + try { - // First check if they're in a meeting + console.log("🪑 DEBUG: Checking if user is in a meeting as member..."); const headers = await getHeaders(this.activeDid); + console.log("🪑 DEBUG: Headers obtained:", headers); + const memberResponse = await this.axios.get( this.apiServer + "/api/partner/groupOnboardMember", { headers }, ); + console.log("🪑 DEBUG: Member response:", memberResponse.data); - if (memberResponse.data.data) { - // They're in a meeting, check if they're the host + if (memberResponse.data?.data?.groupId) { + console.log( + "🪑 DEBUG: User is in a meeting as member, checking if host...", + ); const hostResponse = await this.axios.get( this.apiServer + "/api/partner/groupOnboard", { headers }, ); + console.log("🪑 DEBUG: Host response:", hostResponse.data); - if (hostResponse.data.data) { - // They're the host, take them to setup + if (hostResponse.data?.data?.groupId) { + console.log("🪑 DEBUG: User is HOST, routing to setup"); this.$router.push({ name: "onboard-meeting-setup" }); } else { - // They're not the host, take them to list - this.$router.push({ name: "onboard-meeting-list" }); + console.log("🪑 DEBUG: User is MEMBER, routing to members view"); + this.$router.push({ + name: "onboard-meeting-members", + params: { groupId: memberResponse.data.data.groupId }, + }); } } else { - // They're not in a meeting, show the dialog - this.$notify( - { - group: "modal", - type: "confirm", - title: NOTIFY_ONBOARDING_MEETING.title, - text: NOTIFY_ONBOARDING_MEETING.text, - onYes: async () => { - this.$router.push({ name: "onboard-meeting-setup" }); - }, - yesText: NOTIFY_ONBOARDING_MEETING.yesText, - onNo: async () => { - this.$router.push({ name: "onboard-meeting-list" }); - }, - noText: NOTIFY_ONBOARDING_MEETING.noText, - }, - TIMEOUTS.MODAL, + console.log("🪑 DEBUG: User is NOT in a meeting, checking if host..."); + const hostResponse = await this.axios.get( + this.apiServer + "/api/partner/groupOnboard", + { headers }, ); + console.log("🪑 DEBUG: Host response (no member):", hostResponse.data); + + if (hostResponse.data?.data?.groupId) { + console.log( + "🪑 DEBUG: User is HOST with no member record, routing to setup", + ); + this.$router.push({ name: "onboard-meeting-setup" }); + } else { + console.log( + "🪑 DEBUG: User has NO meeting, routing to setup to CREATE", + ); + this.$router.push({ name: "onboard-meeting-setup" }); + } } - } catch (error) { - this.$logAndConsole( - NOTIFY_MEETING_STATUS_ERROR.message + ": " + errorStringForLog(error), - true, - ); - this.notify.error(NOTIFY_MEETING_STATUS_ERROR.message, TIMEOUTS.MODAL); + } catch (error: any) { + console.log("🪑 DEBUG: Error in API calls:", error); + console.log("🪑 DEBUG: Error response:", error.response?.data); + console.log("🪑 DEBUG: Routing to meeting list due to error"); + this.$router.push({ name: "onboard-meeting-list" }); } } diff --git a/src/views/ImportAccountView.vue b/src/views/ImportAccountView.vue index b71ffa9a..4ff2c3dd 100644 --- a/src/views/ImportAccountView.vue +++ b/src/views/ImportAccountView.vue @@ -66,7 +66,7 @@
@@ -89,7 +89,6 @@ import { Router } from "vue-router"; import { AppString, NotificationIface } from "../constants/app"; import { DEFAULT_ROOT_DERIVATION_PATH } from "../libs/crypto"; import { retrieveAccountCount, importFromMnemonic } from "../libs/util"; -import { logger } from "../utils/logger"; import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin"; import { createNotifyHelpers, TIMEOUTS } from "@/utils/notify"; @@ -184,39 +183,70 @@ export default class ImportAccountView extends Vue { } /** - * Imports identifier from mnemonic phrase + * Handles import button click * - * Processes the mnemonic phrase with optional custom derivation path - * and account erasure options. Handles validation and error scenarios - * with appropriate user feedback. - * - * Error Handling: - * - Invalid mnemonic format validation - * - Import process failure recovery - * - User-friendly error messaging + * Validates input and initiates account import process + * Uses importFromMnemonic utility for secure import */ - public async fromMnemonic() { + public async onImportClick() { + console.log("🔑 DEBUG: Import process started"); + console.log("🔑 DEBUG: Mnemonic length:", this.mnemonic.split(" ").length); + console.log("🔑 DEBUG: Derivation path:", this.derivationPath); + console.log("🔑 DEBUG: Should erase:", this.shouldErase); + console.log("🔑 DEBUG: API Server:", this.apiServer); + + if (!this.mnemonic?.trim()) { + this.notify.warning( + "Seed phrase is required to import an account.", + TIMEOUTS.LONG, + ); + return; + } + try { + console.log("🔑 DEBUG: Calling importFromMnemonic..."); await importFromMnemonic( this.mnemonic, this.derivationPath, this.shouldErase, ); - this.$router.push({ name: "account" }); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - } catch (err: any) { - logger.error("Error importing from mnemonic:", err); - if (err == "Error: invalid mnemonic") { - this.notify.error( - "Please check your mnemonic and try again.", - TIMEOUTS.LONG, - ); - } else { - this.notify.error( - "Got an error creating that identifier.", - TIMEOUTS.LONG, - ); + console.log("🔑 DEBUG: importFromMnemonic completed successfully"); + + // Check what was actually imported + const settings = await this.$accountSettings(); + console.log("🔑 DEBUG: Post-import settings:", settings); + + // Check account-specific settings + if (settings?.activeDid) { + try { + const accountSettings = await this.$query( + "SELECT * FROM settings WHERE accountDid = ?", + [settings.activeDid], + ); + console.log( + "🔑 DEBUG: Post-import account-specific settings:", + accountSettings, + ); + } catch (error) { + console.log("🔑 DEBUG: Error checking post-import settings:", error); + } } + + this.notify.success("Account imported successfully!", TIMEOUTS.STANDARD); + this.$router.push({ name: "account" }); + } catch (error: any) { + console.log("🔑 DEBUG: Import failed with error:", error); + console.log("🔑 DEBUG: Error details:", { + message: error.message, + stack: error.stack, + name: error.name, + }); + + this.$logError("Import failed: " + error); + this.notify.error( + error.message || "Failed to import account.", + TIMEOUTS.LONG, + ); } } } diff --git a/src/views/OnboardMeetingListView.vue b/src/views/OnboardMeetingListView.vue index 777674a1..92c3b392 100644 --- a/src/views/OnboardMeetingListView.vue +++ b/src/views/OnboardMeetingListView.vue @@ -43,7 +43,26 @@

{{ meeting.name }}

-

+ +

+

No onboarding meetings available

+ +
+ + +

No onboarding meetings available

@@ -89,14 +108,13 @@ import { Router } from "vue-router"; import QuickNav from "../components/QuickNav.vue"; import TopMessage from "../components/TopMessage.vue"; -import * as databaseUtil from "../db/databaseUtil"; -import { logConsoleAndDb } from "../db/databaseUtil"; +import { encryptMessage } from "../libs/crypto"; import { errorStringForLog, getHeaders, serverMessageForUser, } from "../libs/endorserServer"; -import { encryptMessage } from "../libs/crypto"; +import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin"; interface Meeting { name: string; @@ -108,6 +126,7 @@ interface Meeting { QuickNav, TopMessage, }, + mixins: [PlatformServiceMixin], }) export default class OnboardMeetingListView extends Vue { $notify!: ( @@ -135,57 +154,132 @@ export default class OnboardMeetingListView extends Vue { showPasswordDialog = false; async created() { - const settings = await databaseUtil.retrieveSettingsForActiveAccount(); - this.activeDid = settings.activeDid || ""; - this.apiServer = settings.apiServer || ""; - this.firstName = settings.firstName || ""; - this.isRegistered = !!settings.isRegistered; - await this.fetchMeetings(); + console.log("📋 DEBUG: OnboardMeetingListView created() called"); + + const settings = await this.$accountSettings(); + console.log("📋 DEBUG: Settings loaded:", settings); + + // 🔍 TEMPORARY DEBUG: Check raw database for test user registration state + if (settings?.activeDid) { + console.log( + "📋 DEBUG: Checking raw database settings for DID:", + settings.activeDid, + ); + try { + // Check master settings + const masterSettings = await this.$query( + "SELECT * FROM settings WHERE id = ?", + [1], + ); + console.log("📋 DEBUG: Master settings:", masterSettings); + + // Check account-specific settings + const accountSettings = await this.$query( + "SELECT * FROM settings WHERE accountDid = ?", + [settings.activeDid], + ); + console.log("📋 DEBUG: Account-specific settings:", accountSettings); + + // Check if there are any settings with isRegistered = 1 + const registeredSettings = await this.$query( + "SELECT * FROM settings WHERE isRegistered = 1", + ); + console.log("📋 DEBUG: All registered settings:", registeredSettings); + + // Check all settings for this user + const allSettings = await this.$query("SELECT * FROM settings"); + console.log("📋 DEBUG: All settings in database:", allSettings); + } catch (error) { + console.log("📋 DEBUG: Error checking raw database:", error); + } + } + + this.activeDid = settings?.activeDid || ""; + this.apiServer = settings?.apiServer || ""; + this.firstName = settings?.firstName || ""; + this.isRegistered = !!settings?.isRegistered; + + console.log("📋 DEBUG: activeDid =", this.activeDid); + console.log("📋 DEBUG: apiServer =", this.apiServer); + console.log("📋 DEBUG: firstName =", this.firstName); + console.log("📋 DEBUG: isRegistered =", this.isRegistered); + + if (this.isRegistered) { + console.log("📋 DEBUG: User is registered, checking for meetings..."); + await this.fetchMeetings(); + } else { + console.log("📋 DEBUG: User is NOT registered, skipping meeting check"); + } } async fetchMeetings() { + console.log("📋 DEBUG: fetchMeetings() called"); + console.log("📋 DEBUG: activeDid =", this.activeDid); + console.log("📋 DEBUG: apiServer =", this.apiServer); + this.isLoading = true; try { - // get the meeting that the user is attending + console.log("📋 DEBUG: Checking if user is attending a meeting..."); const headers = await getHeaders(this.activeDid); + console.log("📋 DEBUG: Headers obtained:", headers); + const response = await this.axios.get( this.apiServer + "/api/partner/groupOnboardMember", { headers }, ); + console.log("📋 DEBUG: Member response:", response.data); if (response.data?.data) { - // they're in a meeting already + console.log( + "📋 DEBUG: User is attending a meeting, fetching details...", + ); const attendingMeetingId = response.data.data.groupId; - // retrieve the meeting details + console.log("📋 DEBUG: Attending meeting ID:", attendingMeetingId); + const headers2 = await getHeaders(this.activeDid); const response2 = await this.axios.get( this.apiServer + "/api/partner/groupOnboard/" + attendingMeetingId, { headers: headers2 }, ); + console.log("📋 DEBUG: Meeting details response:", response2.data); if (response2.data?.data) { + console.log("📋 DEBUG: Setting attendingMeeting"); this.attendingMeeting = response2.data.data; + console.log("📋 DEBUG: attendingMeeting set:", this.attendingMeeting); return; } else { - // this should never happen - logConsoleAndDb( + console.log( + "📋 DEBUG: ERROR: No meeting details found for attending meeting", + ); + this.$logAndConsole( "Error fetching meeting for user after saying they are in one.", true, ); } + } else { + console.log("📋 DEBUG: User is NOT attending a meeting"); } + console.log("📋 DEBUG: Fetching available meetings..."); const headers2 = await getHeaders(this.activeDid); const response2 = await this.axios.get( this.apiServer + "/api/partner/groupsOnboarding", { headers: headers2 }, ); + console.log("📋 DEBUG: Available meetings response:", response2.data); if (response2.data?.data) { + console.log("📋 DEBUG: Setting meetings list"); this.meetings = response2.data.data; + console.log("📋 DEBUG: meetings set:", this.meetings); + } else { + console.log("📋 DEBUG: No meetings found"); } - } catch (error) { - logConsoleAndDb( + } catch (error: any) { + console.log("📋 DEBUG: Error fetching meetings:", error); + console.log("📋 DEBUG: Error response:", error.response?.data); + this.$logAndConsole( "Error fetching meetings: " + errorStringForLog(error), true, ); @@ -224,7 +318,7 @@ export default class OnboardMeetingListView extends Vue { async submitPassword() { if (!this.selectedMeeting) { // this should never happen - logConsoleAndDb( + this.$logAndConsole( "No meeting selected when prompting for password, which should never happen.", true, ); @@ -275,7 +369,7 @@ export default class OnboardMeetingListView extends Vue { throw { response: postResult }; } } catch (error) { - logConsoleAndDb( + this.$logAndConsole( "Error joining meeting: " + errorStringForLog(error), true, ); @@ -320,7 +414,7 @@ export default class OnboardMeetingListView extends Vue { 5000, ); } catch (error) { - logConsoleAndDb( + this.$logAndConsole( "Error leaving meeting: " + errorStringForLog(error), true, ); @@ -341,5 +435,10 @@ export default class OnboardMeetingListView extends Vue { -1, ); } + + createMeeting() { + console.log("📋 DEBUG: createMeeting() called - routing to meeting setup"); + this.$router.push({ name: "onboard-meeting-setup" }); + } } diff --git a/src/views/OnboardMeetingMembersView.vue b/src/views/OnboardMeetingMembersView.vue index e07e4ecd..0702736f 100644 --- a/src/views/OnboardMeetingMembersView.vue +++ b/src/views/OnboardMeetingMembersView.vue @@ -55,8 +55,6 @@ import QuickNav from "../components/QuickNav.vue"; import TopMessage from "../components/TopMessage.vue"; import MembersList from "../components/MembersList.vue"; import UserNameDialog from "../components/UserNameDialog.vue"; -import * as databaseUtil from "../db/databaseUtil"; -import { logConsoleAndDb } from "../db/databaseUtil"; import { encryptMessage } from "../libs/crypto"; import { errorStringForLog, @@ -64,6 +62,7 @@ import { serverMessageForUser, } from "../libs/endorserServer"; import { generateSaveAndActivateIdentity } from "../libs/util"; +import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin"; @Component({ components: { @@ -72,6 +71,7 @@ import { generateSaveAndActivateIdentity } from "../libs/util"; MembersList, UserNameDialog, }, + mixins: [PlatformServiceMixin], }) export default class OnboardMeetingMembersView extends Vue { activeDid = ""; @@ -105,11 +105,11 @@ export default class OnboardMeetingMembersView extends Vue { this.isLoading = false; return; } - const settings = await databaseUtil.retrieveSettingsForActiveAccount(); - this.activeDid = settings.activeDid || ""; - this.apiServer = settings.apiServer || ""; - this.firstName = settings.firstName || ""; - this.isRegistered = settings.isRegistered || false; + const settings = await this.$accountSettings(); + this.activeDid = settings?.activeDid || ""; + this.apiServer = settings?.apiServer || ""; + this.firstName = settings?.firstName || ""; + this.isRegistered = !!settings?.isRegistered; try { if (!this.activeDid) { this.activeDid = await generateSaveAndActivateIdentity(); @@ -160,7 +160,7 @@ export default class OnboardMeetingMembersView extends Vue { this.errorMessage = serverMessageForUser(error) || "There was an error checking for that meeting. Reload or go back and try again."; - logConsoleAndDb( + this.$logAndConsole( "Error checking meeting: " + errorStringForLog(error), true, ); @@ -192,7 +192,7 @@ export default class OnboardMeetingMembersView extends Vue { { headers }, ); } catch (error) { - logConsoleAndDb( + this.$logAndConsole( "Error adding member to meeting: " + errorStringForLog(error), true, ); @@ -225,7 +225,7 @@ export default class OnboardMeetingMembersView extends Vue { { headers }, ); } catch (error) { - logConsoleAndDb( + this.$logAndConsole( "Error updating member in meeting: " + errorStringForLog(error), true, ); diff --git a/src/views/OnboardMeetingSetupView.vue b/src/views/OnboardMeetingSetupView.vue index 8ad4cb34..5d91dd15 100644 --- a/src/views/OnboardMeetingSetupView.vue +++ b/src/views/OnboardMeetingSetupView.vue @@ -344,7 +344,7 @@ export default class OnboardMeetingView extends Vue { async created() { this.notify = createNotifyHelpers(this.$notify as any); - const settings = await this.$getSettings("activeAccount"); + const settings = await this.$accountSettings(); this.activeDid = settings?.activeDid || ""; this.apiServer = settings?.apiServer || ""; this.fullName = settings?.firstName || ""; @@ -398,27 +398,52 @@ export default class OnboardMeetingView extends Vue { } async fetchCurrentMeeting() { + console.log("🏗️ DEBUG: fetchCurrentMeeting() called"); + console.log("🏗️ DEBUG: activeDid =", this.activeDid); + console.log("🏗️ DEBUG: apiServer =", this.apiServer); + try { const headers = await getHeaders(this.activeDid); + console.log("🏗️ DEBUG: Headers obtained:", headers); + const response = await this.axios.get( this.apiServer + "/api/partner/groupOnboard", { headers }, ); + console.log("🏗️ DEBUG: Meeting response:", response.data); const queryPassword = this.$route.query["password"] as string; + console.log("🏗️ DEBUG: Query password:", queryPassword); + if (response?.data?.data) { + console.log("🏗️ DEBUG: Meeting found, setting currentMeeting"); this.currentMeeting = { ...response.data.data, userFullName: this.fullName, password: this.currentMeeting?.password || queryPassword || "", }; + console.log("🏗️ DEBUG: currentMeeting set:", this.currentMeeting); } else { - // no meeting found + console.log( + "🏗️ DEBUG: No meeting found, setting up blank meeting for creation", + ); this.newOrUpdatedMeetingInputs = this.blankMeeting(); + console.log( + "🏗️ DEBUG: newOrUpdatedMeetingInputs set:", + this.newOrUpdatedMeetingInputs, + ); } - } catch (error) { - // no meeting found + } catch (error: any) { + console.log("🏗️ DEBUG: Error fetching meeting:", error); + console.log("🏗️ DEBUG: Error response:", error.response?.data); + console.log( + "🏗️ DEBUG: Setting up blank meeting for creation due to error", + ); this.newOrUpdatedMeetingInputs = this.blankMeeting(); + console.log( + "🏗️ DEBUG: newOrUpdatedMeetingInputs set:", + this.newOrUpdatedMeetingInputs, + ); } }