Skip to content

Commit

Permalink
Implement utils for parsing and creating invitation code with multipl…
Browse files Browse the repository at this point in the history
…e addresses
  • Loading branch information
EmiM committed Aug 3, 2023
1 parent bfc272b commit 8ba87a5
Show file tree
Hide file tree
Showing 18 changed files with 287 additions and 158 deletions.
2 changes: 1 addition & 1 deletion packages/backend/src/nest/storage/storage.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ export class StorageService extends EventEmitter {
return
}
for (const a of addr) {
this.logger(`Pubsub - subscribe to ${addr}`)
this.logger(`Pubsub - subscribe to ${a}`)
// @ts-ignore
await this.orbitDb._pubsub.subscribe(
a,
Expand Down
69 changes: 64 additions & 5 deletions packages/common/src/invitationCode.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { InvitationPair } from '@quiet/types'
import { InvitationParams, Site } from './static'

export const retrieveInvitationCode = (url: string): string => {
Expand All @@ -20,20 +21,78 @@ export const retrieveInvitationCode = (url: string): string => {
return ''
}

export const argvInvitationCode = (argv: string[]): string => {
export const retrieveInvitationCodePairs = (url: string): InvitationPair[] => {
/**
* Extract invitation code from deep url.
* Valid format: quiet://?<peerid1>=<address1>&<peerid2>=<addresss2>
*/
let data: URL
try {
data = new URL(url)
} catch (e) {
return []
}
if (!data || data.protocol !== 'quiet:') return []
const params = data.searchParams
const codes: InvitationPair[] = []
for (const [peerId, address] of params) {
// TODO: basic check if peerid and address have proper format?
if (peerId.length !== 46 || address.length !== 56) {
console.log(`peerId '${peerId}' or address ${address} is not valid`)
continue
}
codes.push({
peerId,
address,
})
}
console.log('Retrieved codes:', codes)
return codes
}

export const invitationShareUrlMultipleAddresses = (pairs: InvitationPair[] = []): string => {
// Valid format: https://tryquiet.org/join/#<peerid1>=<address1>&<peerid2>=<addresss2>
const code = pairs.map(pair => `${pair.peerId}=${pair.address}`).join('&')
const url = new URL(`https://${Site.DOMAIN}/${Site.JOIN_PAGE}#${code}`)
return url.href
}

export const invitationDeepUrlMultipleAddresses = (pairs: InvitationPair[] = []): string => {
const url = new URL('quiet://')
for (const pair of pairs) {
url.searchParams.append(pair.peerId, pair.address)
}
return url.href
}

export const argvInvitationCode = (argv: string[]): InvitationPair[] => {
/**
* Extract invitation code from deep url if url is present in argv
*/
let invitationCode = ''
let invitationCodes = []
for (const arg of argv) {
invitationCode = retrieveInvitationCode(arg)
if (invitationCode) {
invitationCodes = retrieveInvitationCodePairs(arg)
if (invitationCodes.length > 0) {
break
}
}
return invitationCode
return invitationCodes
}

// export const argvInvitationCode = (argv: string[]): string => {
// /**
// * Extract invitation code from deep url if url is present in argv
// */
// let invitationCode = ''
// for (const arg of argv) {
// invitationCode = retrieveInvitationCode(arg)
// if (invitationCode) {
// break
// }
// }
// return invitationCode
// }

export const invitationDeepUrl = (code = ''): string => {
const url = new URL('quiet://')
url.searchParams.append(InvitationParams.CODE, code)
Expand Down
7 changes: 4 additions & 3 deletions packages/desktop/src/main/invitation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ import path from 'path'
import os from 'os'
import { execSync } from 'child_process'
import { BrowserWindow } from 'electron'
import { InvitationPair } from '@quiet/types'

export const processInvitationCode = (mainWindow: BrowserWindow, code: string) => {
if (!code) return
export const processInvitationCode = (mainWindow: BrowserWindow, codes: InvitationPair[]) => {
if (codes.length === 0) return
mainWindow.webContents.send('invitation', {
code,
codes,
})
}

Expand Down
9 changes: 4 additions & 5 deletions packages/desktop/src/main/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@ import { Crypto } from '@peculiar/webcrypto'
import logger from './logger'
import { DATA_DIR, DEV_DATA_DIR } from '../shared/static'
import { fork, ChildProcess } from 'child_process'
import { getFilesData } from '@quiet/common'
import { argvInvitationCode, getFilesData, retrieveInvitationCodePairs } from '@quiet/common'
import { updateDesktopFile, processInvitationCode } from './invitation'
import { argvInvitationCode, retrieveInvitationCode } from '@quiet/common'
const ElectronStore = require('electron-store')
ElectronStore.initRenderer()

Expand Down Expand Up @@ -148,7 +147,7 @@ app.on('open-url', (event, url) => {
event.preventDefault()
if (mainWindow) {
invitationUrl = null
const invitationCode = retrieveInvitationCode(url)
const invitationCode = retrieveInvitationCodePairs(url)
processInvitationCode(mainWindow, invitationCode)
}
})
Expand Down Expand Up @@ -475,12 +474,12 @@ app.on('ready', async () => {
throw new Error(`mainWindow is on unexpected type ${mainWindow}`)
}
if (process.platform === 'darwin' && invitationUrl) {
const invitationCode = retrieveInvitationCode(invitationUrl)
const invitationCode = retrieveInvitationCodePairs(invitationUrl)
processInvitationCode(mainWindow, invitationCode)
invitationUrl = null
}
if (process.platform !== 'darwin' && process.argv) {
const invitationCode = argvInvitationCode(process.argv)
const invitationCode = argvInvitationCodeMultipleAddresses(process.argv)
processInvitationCode(mainWindow, invitationCode)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useEffect, useState } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { socketSelectors } from '../../../sagas/socket/socket.selectors'
import { CommunityOwnership, CreateNetworkPayload, TOR_BOOTSTRAP_COMPLETE } from '@quiet/types'
import { CommunityOwnership, CreateNetworkPayload, InvitationPair, TOR_BOOTSTRAP_COMPLETE } from '@quiet/types'
import { communities, identity, connection } from '@quiet/state-manager'
import PerformCommunityActionComponent from '../../../components/CreateJoinCommunity/PerformCommunityActionComponent'
import { ModalName } from '../../../sagas/modals/modals.types'
Expand Down Expand Up @@ -41,10 +41,10 @@ const JoinCommunity = () => {
}
}, [currentCommunity])

const handleCommunityAction = (address: string) => {
const handleCommunityAction = (address: InvitationPair[]) => {
const payload: CreateNetworkPayload = {
ownership: CommunityOwnership.User,
registrar: address,
peers: address,
}
dispatch(communities.actions.createNetwork(payload))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { IconButton, InputAdornment } from '@mui/material'
import VisibilityOff from '@mui/icons-material/VisibilityOff'
import Visibility from '@mui/icons-material/Visibility'
import { ONION_ADDRESS_REGEX, parseName } from '@quiet/common'
import { getInvitationCode } from '@quiet/state-manager'
import { getInvitationCodes } from '@quiet/state-manager'

const PREFIX = 'PerformCommunityActionComponent'

Expand Down Expand Up @@ -129,7 +129,7 @@ interface PerformCommunityActionFormValues {
export interface PerformCommunityActionProps {
open: boolean
communityOwnership: CommunityOwnership
handleCommunityAction: (value: string) => void
handleCommunityAction: (value: any) => void
handleRedirection: () => void
handleClose: () => void
isConnectionReady?: boolean
Expand Down Expand Up @@ -178,22 +178,30 @@ export const PerformCommunityActionComponent: React.FC<PerformCommunityActionPro
const onSubmit = (values: PerformCommunityActionFormValues) => submitForm(handleCommunityAction, values, setFormSent)

const submitForm = (
handleSubmit: (value: string) => void,
handleSubmit: (value: any) => void,
values: PerformCommunityActionFormValues,
setFormSent: (value: boolean) => void
) => {
let submitValue = communityOwnership === CommunityOwnership.Owner ? parseName(values.name) : values.name.trim()
if (communityOwnership === CommunityOwnership.Owner) {
setFormSent(true)
handleSubmit(parseName(values.name))
return
}

// let submitValue = communityOwnership === CommunityOwnership.Owner ? parseName(values.name) : values.name.trim()

if (communityOwnership === CommunityOwnership.User) {
submitValue = getInvitationCode(submitValue)
if (!submitValue || !submitValue.match(ONION_ADDRESS_REGEX)) {
const codes = getInvitationCodes(values.name.trim())
if (!codes.length) {
// if (!submitValue || !submitValue.match(ONION_ADDRESS_REGEX)) { // TODO: add basic validation
setError('name', { message: InviteLinkErrors.InvalidCode })
return
// }
}
}

setFormSent(true)
handleSubmit(submitValue)
setFormSent(true)
handleSubmit(codes)
}
}

const onChange = (name: string) => {
Expand Down
5 changes: 5 additions & 0 deletions packages/desktop/src/renderer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ ipcRenderer.on('invitation', (_event, invitation) => {
store.dispatch(communities.actions.handleInvitationCode(invitation.code))
})

ipcRenderer.on('invitationMA', (_event, invitation) => {
console.log('invitation', invitation, 'dispatching action')
store.dispatch(communities.actions.handleInvitationCodes(invitation.codes))
})

const container = document.getElementById('root')
if (!container) throw new Error('No root html element!')
let root = createRoot(container)
Expand Down
Loading

0 comments on commit 8ba87a5

Please sign in to comment.