Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions packages/murmur-cli/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,7 @@ function printUsage(): void {
const lines = [
'Usage:',
' murmur sign-in [--first-name <name>] [--last-name <name>]',
' murmur update-profile --first-name <name> [--last-name <name>]',
' murmur me',
' murmur delete-account --confirm',
' murmur contacts',
Expand Down Expand Up @@ -519,6 +520,7 @@ type WebhookContext = {
senderId: string
senderIdentityKey: string
senderName: string
text: string
receivedAt: number
hasAttachments: boolean
}
Expand Down Expand Up @@ -594,6 +596,7 @@ async function emitWebhook(
senderId: formatWebhookSenderId(contact, message.conversationId),
senderIdentityKey: message.conversationId,
senderName: formatName(contact?.firstName, contact?.lastName, 'Unknown'),
text: message.text,
receivedAt: message.createdAt,
hasAttachments: Boolean(message.attachments && message.attachments.length > 0)
}
Expand Down Expand Up @@ -698,6 +701,14 @@ async function run(): Promise<void> {
console.log(JSON.stringify(profile, null, 2))
return
}
case 'update-profile': {
await requireInitialized(getEngine())
const firstName = requireStringOption(parsed.options, 'first-name', 'MURMUR_FIRST_NAME')
const lastName = readStringOption(parsed.options, 'last-name', 'MURMUR_LAST_NAME')
const account = await getEngine().updateProfile(firstName, lastName)
printAccountSummary('Profile updated.', account)
return
}
case 'delete-account': {
await requireInitialized(getEngine())
const confirmed = readBooleanOption(parsed.options, 'confirm', 'MURMUR_CONFIRM_DELETE')
Expand Down
40 changes: 40 additions & 0 deletions packages/murmur-cli/src/engine/engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import {
decryptProfile,
createProfileForRegistration,
verifyProfileKeySignature,
signProfileKey,
type Profile
} from './profile.js'
import { publicKeyFromPrivate } from '../encryption/crypto/dh.js'
Expand Down Expand Up @@ -521,6 +522,45 @@ export class MurmurEngine {
return this.account
}

/**
* Update the current account's profile (firstName, lastName).
*/
async updateProfile(firstName: string, lastName?: string): Promise<Account> {
if (!this.agent || !this.account) {
throw new Error('Not initialized')
}

// Create new encrypted profile
const profile: Profile = { firstName, lastName }
const profileSecretKeyBytes = decodeBase64(this.account.profileSecretKey, 'base64url')
const profilePublicKeyBytes = decodeBase64(this.account.profilePublicKey)
const encryptedProfile = encryptProfile(profile, profileSecretKeyBytes)
const profileKeySignature = signProfileKey(
profilePublicKeyBytes,
this.agent.keyStore.identityKeyPair.privateKey
)

// Upload to server
await this.api.updateProfile(
this.account.profilePublicKey,
profileKeySignature,
encryptedProfile
)

// Update local account
this.account = {
...this.account,
firstName,
lastName,
encryptedProfile
}

// Save to database
this.db.saveAccount(this.account)

return this.account
}

/**
* Delete the current account and local data.
*/
Expand Down