Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle multiple invitation addresses #1686

Merged
merged 36 commits into from
Sep 11, 2023
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
8ba87a5
Implement utils for parsing and creating invitation code with multipl…
EmiM Aug 3, 2023
2e69186
Merge branch 'develop' into feature/1557
EmiM Aug 8, 2023
7510cab
Adjust code to multiple addresses
EmiM Aug 10, 2023
ee91ad1
Merge branch 'develop' into feature/1557
EmiM Aug 11, 2023
525383a
Adjust code to display multiple addresses in invitation url
EmiM Aug 11, 2023
cf60b7f
Merge branch 'feature/1556' into feature/1557
EmiM Aug 17, 2023
b3e59c5
Do not launch registrar, do not wait for certificates to join community
EmiM Aug 21, 2023
28ba290
Add eventlog DB for CSRs; Create invitation link basing on user's dat…
EmiM Aug 23, 2023
2e2d3b5
Remove tmp fix for sendCommand
EmiM Aug 24, 2023
289d9df
Merge branch 'develop' into feature/1557
EmiM Aug 24, 2023
30ec894
Merge branch 'fix/async-tor' into feature/1557
EmiM Aug 24, 2023
bb30494
Fix community double launch
vinkabuki Aug 25, 2023
f2972df
Simulate registrar by creating certificate on csr replication
EmiM Aug 27, 2023
ee55f92
Update own certificate on replication
vinkabuki Aug 29, 2023
17e2903
Merge branch 'develop' into feature/1557
EmiM Sep 4, 2023
51cbda4
Cleanup
EmiM Sep 4, 2023
61b78d8
Check if peerid and onion address are valid in deep link
EmiM Sep 4, 2023
fe1eac5
Validate invitation codes format in url pasted in join screen; cleanu…
EmiM Sep 4, 2023
56e4faf
Cleanup
EmiM Sep 6, 2023
6bb6f49
Add community metadata to database
EmiM Sep 7, 2023
0928c02
Do not save same csr twice
EmiM Sep 7, 2023
99e8a46
Merge branch 'develop' into feature/1557
EmiM Sep 7, 2023
dd11cd6
Fix handleInvitationCode test; revive warning modal when no code is v…
EmiM Sep 7, 2023
f1fe680
Temporarly do not show "invitation code invalid" modal
EmiM Sep 7, 2023
912e3de
Rename address -> onionAddress in InvitationPair type
EmiM Sep 7, 2023
985278d
Cleanup
EmiM Sep 7, 2023
974324a
Fix
EmiM Sep 7, 2023
1cd5094
Fix backend tests
EmiM Sep 7, 2023
9a2b402
Fix
EmiM Sep 7, 2023
aed8825
Fix state-manager tests
EmiM Sep 7, 2023
92182af
Fix or skip desktop tests
EmiM Sep 7, 2023
6232b9c
Uncomment deeplink test on mobile
EmiM Sep 7, 2023
d4d60e5
Adjust e2e tests
EmiM Sep 7, 2023
af8003b
Merge branch 'develop' into feature/1557
EmiM Sep 7, 2023
5022d62
Fix/skip deepLink mobile tests
EmiM Sep 11, 2023
7362b47
Update changelog
EmiM Sep 11, 2023
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
10 changes: 2 additions & 8 deletions packages/backend/src/nest/common/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import { TestConfig } from '../const'
import logger from './logger'
import { createCertificatesTestHelper } from './client-server'
import { Libp2pNodeParams } from '../libp2p/libp2p.types'
import { ONION_ADDRESS_REGEX, Site, createLibp2pAddress, createLibp2pListenAddress } from '@quiet/common'
import { multiaddr } from '@multiformats/multiaddr'
const log = logger('test')

export interface Ports {
Expand Down Expand Up @@ -143,14 +145,6 @@ export const torDirForPlatform = (basePath?: string): string => {
return torPath
}

export const createLibp2pAddress = (address: string, peerId: string) => {
return `/dns4/${address}/tcp/80/ws/p2p/${peerId}`
}

export const createLibp2pListenAddress = (address: string) => {
return `/dns4/${address}/tcp/80/ws`
}

export const getUsersAddresses = async (users: User[]): Promise<string[]> => {
const peers = users.map(async (userData: User) => {
return createLibp2pAddress(userData.onionAddress, userData.peerId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,7 @@ import crypto from 'crypto'
import { CustomEvent } from '@libp2p/interfaces/events'
import { jest, beforeEach, describe, it, expect, afterEach } from '@jest/globals'
import { communities, getFactory, identity, prepareStore, Store } from '@quiet/state-manager'
import {
createLibp2pAddress,
createPeerId,
createTmpDir,
libp2pInstanceParams,
removeFilesFromDir,
tmpQuietDirPath,
} from '../common/utils'
import { createPeerId, createTmpDir, libp2pInstanceParams, removeFilesFromDir, tmpQuietDirPath } from '../common/utils'

import { NetworkStats, type Community, type Identity, type InitCommunityPayload } from '@quiet/types'
import { LazyModuleLoader } from '@nestjs/core'
Expand All @@ -37,6 +30,7 @@ import { DateTime } from 'luxon'
import waitForExpect from 'wait-for-expect'
import { Libp2pEvents } from '../libp2p/libp2p.types'
import { sleep } from '../common/sleep'
import { createLibp2pAddress } from '@quiet/common'

jest.setTimeout(100_000)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ import {
StorePeerListPayload,
UploadFilePayload,
PeerId as PeerIdType,
SaveCSRPayload,
SendUserCertificatePayload,
CommunityMetadata,
CommunityMetadataPayload,
} from '@quiet/types'
import { CONFIG_OPTIONS, QUIET_DIR, SERVER_IO_PROVIDER, SOCKS_PROXY_AGENT } from '../const'
import { ConfigOptions, GetPorts, ServerIoProviderTypes } from '../types'
Expand Down Expand Up @@ -165,17 +169,9 @@ export class ConnectionsManagerService extends EventEmitter implements OnModuleI
if ([ServiceState.LAUNCHING, ServiceState.LAUNCHED].includes(this.communityState)) return
this.communityState = ServiceState.LAUNCHING
}
const registrarData: LaunchRegistrarPayload = await this.localDbService.get(LocalDBKeys.REGISTRAR)
if (registrarData) {
if ([ServiceState.LAUNCHING, ServiceState.LAUNCHED].includes(this.registrarState)) return
this.registrarState = ServiceState.LAUNCHING
}
if (community) {
await this.launchCommunity(community)
}
if (registrarData) {
await this.registrationService.launchRegistrar(registrarData)
}
}

public async closeAllServices(options: { saveTor: boolean } = { saveTor: false }) {
Expand Down Expand Up @@ -273,20 +269,22 @@ export class ConnectionsManagerService extends EventEmitter implements OnModuleI
community: {
...community,
privateKey: network2.hiddenService.privateKey,
registrarUrl: community.registrarUrl || network2.hiddenService.onionAddress.split('.')[0],
registrarUrl: community.registrarUrl || network2.hiddenService.onionAddress.split('.')[0], // TODO: remove
},
network,
}
this.serverIoProvider.io.emit(SocketActionTypes.NETWORK, payload)
}

public async createCommunity(payload: InitCommunityPayload) {
console.log('ConnectionsManager.createCommunity peers:', payload.peers)
await this.launchCommunity(payload)
this.logger(`Created and launched community ${payload.id}`)
this.serverIoProvider.io.emit(SocketActionTypes.NEW_COMMUNITY, { id: payload.id })
}

public async launchCommunity(payload: InitCommunityPayload) {
console.log('ConnectionsManager.launchCommunity peers:', payload.peers)
this.communityState = ServiceState.LAUNCHING
const communityData: InitCommunityPayload = await this.localDbService.get(LocalDBKeys.COMMUNITY)
if (!communityData) {
Expand Down Expand Up @@ -327,7 +325,6 @@ export class ConnectionsManagerService extends EventEmitter implements OnModuleI

const { Libp2pModule } = await import('../libp2p/libp2p.module')
const moduleRef = await this.lazyModuleLoader.load(() => Libp2pModule)
this.logger('launchCommunityFromStorage')
const { Libp2pService } = await import('../libp2p/libp2p.service')
const lazyService = moduleRef.get(Libp2pService)
this.libp2pService = lazyService
Expand All @@ -336,6 +333,7 @@ export class ConnectionsManagerService extends EventEmitter implements OnModuleI
const _peerId = await peerIdFromKeys(restoredRsa.marshalPubKey(), restoredRsa.marshalPrivKey())

let peers = payload.peers
console.log(`Launching community ${payload.id}, payload peers: ${peers}`)
if (!peers || peers.length === 0) {
peers = [this.libp2pService.createLibp2pAddress(onionAddress, _peerId.toString())]
}
Expand All @@ -344,9 +342,6 @@ export class ConnectionsManagerService extends EventEmitter implements OnModuleI
peerId: _peerId,
listenAddresses: [this.libp2pService.createLibp2pListenAddress(onionAddress)],
agent: this.socksProxyAgent,
cert: payload.certs.certificate,
key: payload.certs.key,
ca: payload.certs.CA,
localAddress: this.libp2pService.createLibp2pAddress(onionAddress, _peerId.toString()),
targetPort: this.ports.libp2pHiddenService,
peers,
Expand Down Expand Up @@ -397,19 +392,9 @@ export class ConnectionsManagerService extends EventEmitter implements OnModuleI
this.registrationService.on(SocketActionTypes.SAVED_OWNER_CERTIFICATE, payload => {
this.serverIoProvider.io.emit(SocketActionTypes.SAVED_OWNER_CERTIFICATE, payload)
})
this.registrationService.on(RegistrationEvents.SPAWN_HS_FOR_REGISTRAR, async payload => {
await this.tor.spawnHiddenService({
targetPort: payload.port,
privKey: payload.privateKey,
virtPort: payload.targetPort,
})
})
this.registrationService.on(RegistrationEvents.ERROR, payload => {
emitError(this.serverIoProvider.io, payload)
})
this.registrationService.on(SocketActionTypes.SEND_USER_CERTIFICATE, payload => {
this.serverIoProvider.io.emit(SocketActionTypes.SEND_USER_CERTIFICATE, payload)
})
this.registrationService.on(RegistrationEvents.NEW_USER, async payload => {
await this.storageService?.saveCertificate(payload)
})
Expand Down Expand Up @@ -446,18 +431,16 @@ export class ConnectionsManagerService extends EventEmitter implements OnModuleI
this.communityState = ServiceState.LAUNCHING
await this.launchCommunity(args)
})
// Registration
this.socketService.on(SocketActionTypes.LAUNCH_REGISTRAR, async (args: LaunchRegistrarPayload) => {
// Event left for setting permsData purposes
this.logger(`socketService - ${SocketActionTypes.LAUNCH_REGISTRAR}`)

const communityData = await this.localDbService.get(LocalDBKeys.REGISTRAR)
if (!communityData) {
await this.localDbService.put(LocalDBKeys.REGISTRAR, args)
this.registrationService.permsData = {
certificate: args.rootCertString,
privKey: args.rootKeyString,
}
console.log('this.registrarState', this.registrarState)
if ([ServiceState.LAUNCHING, ServiceState.LAUNCHED].includes(this.registrarState)) return
this.registrarState = ServiceState.LAUNCHING
await this.registrationService.launchRegistrar(args)
})
this.socketService.on(SocketActionTypes.SEND_COMMUNITY_METADATA, async (payload: CommunityMetadata) => {
await this.storageService?.updateCommunityMetadata(payload)
})
this.socketService.on(SocketActionTypes.SAVED_OWNER_CERTIFICATE, async (args: SaveOwnerCertificatePayload) => {
const saveCertificatePayload: SaveCertificatePayload = {
Expand All @@ -466,18 +449,10 @@ export class ConnectionsManagerService extends EventEmitter implements OnModuleI
}
await this.storageService?.saveCertificate(saveCertificatePayload)
})
this.socketService.on(SocketActionTypes.REGISTER_USER_CERTIFICATE, async (args: RegisterUserCertificatePayload) => {
// if (!this.socksProxyAgent) {
// this.createAgent()
// }

await this.registrationService.sendCertificateRegistrationRequest(
args.serviceAddress,
args.userCsr,
args.communityId,
120_000,
this.socksProxyAgent
)
this.socketService.on(SocketActionTypes.SAVE_USER_CSR, async (payload: SaveCSRPayload) => {
console.log(`On ${SocketActionTypes.SAVE_USER_CSR}: ${payload.csr}`)
await this.storageService?.saveCSR(payload)
this.serverIoProvider.io.emit(SocketActionTypes.SAVED_USER_CSR, payload)
})
this.socketService.on(
SocketActionTypes.REGISTER_OWNER_CERTIFICATE,
Expand Down Expand Up @@ -592,5 +567,17 @@ export class ConnectionsManagerService extends EventEmitter implements OnModuleI
console.log('emitting deleted channel event back to state manager')
this.serverIoProvider.io.emit(SocketActionTypes.CHANNEL_DELETION_RESPONSE, payload)
})
this.storageService.on(StorageEvents.REPLICATED_CSR, async (payload: { csr: string }) => {
console.log(`On ${StorageEvents.REPLICATED_CSR}`)
this.registrationService.emit(RegistrationEvents.REGISTER_USER_CERTIFICATE, payload.csr)
})
this.storageService.on(StorageEvents.REPLICATED_COMMUNITY_METADATA, (payload: CommunityMetadata) => {
console.log(`On ${StorageEvents.REPLICATED_COMMUNITY_METADATA}: ${payload}`)
const communityMetadataPayload: CommunityMetadataPayload = {
rootCa: payload.rootCa,
ownerCertificate: payload.ownerCertificate,
}
this.serverIoProvider.io.emit(SocketActionTypes.SAVE_COMMUNITY_METADATA, communityMetadataPayload)
})
}
}
4 changes: 2 additions & 2 deletions packages/backend/src/nest/libp2p/libp2p.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@ describe('Libp2pService', () => {

it('creates libp2p address with proper ws type (%s)', async () => {
const libp2pAddress = libp2pService.createLibp2pAddress(params.localAddress, params.peerId.toString())
expect(libp2pAddress).toStrictEqual(`/dns4/${params.localAddress}.onion/tcp/80/wss/p2p/${params.peerId.toString()}`)
expect(libp2pAddress).toStrictEqual(`/dns4/${params.localAddress}.onion/tcp/80/ws/p2p/${params.peerId.toString()}`)
})

it('creates libp2p listen address', async () => {
const libp2pListenAddress = libp2pService.createLibp2pListenAddress('onionAddress')
expect(libp2pListenAddress).toStrictEqual(`/dns4/onionAddress.onion/tcp/80/wss`)
expect(libp2pListenAddress).toStrictEqual(`/dns4/onionAddress.onion/tcp/80/ws`)
})
})
6 changes: 4 additions & 2 deletions packages/backend/src/nest/libp2p/libp2p.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ import { multiaddr } from '@multiformats/multiaddr'
import { ConnectionProcessInfo, PeerId, SocketActionTypes } from '@quiet/types'
import { SERVER_IO_PROVIDER, SOCKS_PROXY_AGENT } from '../const'
import { ServerIoProviderTypes } from '../types'
import { createLibp2pListenAddress, createLibp2pAddress } from './libp2p.utils'
import Logger from '../common/logger'
import { webSockets } from '../websocketOverTor'
import { all } from '../websocketOverTor/filters'
import { createLibp2pAddress, createLibp2pListenAddress } from '@quiet/common'

@Injectable()
export class Libp2pService extends EventEmitter {
Expand All @@ -44,7 +44,8 @@ export class Libp2pService extends EventEmitter {
return createLibp2pListenAddress(address)
}

public async createInstance(params: Libp2pNodeParams): Promise<any> {
public async createInstance(params: Libp2pNodeParams): Promise<Libp2p> {
console.log('Libp2p.createInstance::: peers:::', params.peers)
if (this.libp2pInstance) {
return this.libp2pInstance
}
Expand Down Expand Up @@ -112,6 +113,7 @@ export class Libp2pService extends EventEmitter {

this.libp2pInstance.addEventListener('peer:connect', async peer => {
const remotePeerId = peer.detail.remotePeer.toString()
console.log('ADDRESS', peer.detail.remoteAddr)
this.logger(`${peerId.toString()} connected to ${remotePeerId}`)

// Stop dialing as soon as we connect to a peer
Expand Down
6 changes: 3 additions & 3 deletions packages/backend/src/nest/libp2p/libp2p.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ export interface Libp2pNodeParams {
peerId: any
listenAddresses: string[]
agent: Agent
cert: string
key: string
ca: string[]
cert?: string
key?: string
ca?: string[]
EmiM marked this conversation as resolved.
Show resolved Hide resolved
localAddress: string
targetPort: number
peers: string[]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ export const registerUser = async (
let cert: string
const userData = new UserCsrData()
userData.csr = csr
console.log('USER DATA', userData)
const validationErrors = await validate(userData)
if (validationErrors.length > 0) {
logger.error(`Received data is not valid: ${validationErrors.toString()}`)
Expand Down
21 changes: 19 additions & 2 deletions packages/backend/src/nest/registration/registration.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export class RegistrationService extends EventEmitter implements OnModuleInit {
private _server: Server
private _port: number
public registrationService: any
public certificates: string[]
public certificates: string[] = []
private _permsData: PermsData
private _ownerCertificate: string

Expand All @@ -40,8 +40,17 @@ export class RegistrationService extends EventEmitter implements OnModuleInit {

onModuleInit() {
this.on(RegistrationEvents.SET_CERTIFICATES, certs => {
console.log('SET CERTIFICATES', certs)
this.setCertificates(certs)
})
this.on(RegistrationEvents.REGISTER_USER_CERTIFICATE, async (csr: string) => {
if (!this._permsData) {
console.log('NO PERMS DATA')
return
}
console.log('CSR in registration service', csr)
const response = await this.registerUser(csr)
})
this.setRouting()
}

Expand Down Expand Up @@ -84,6 +93,14 @@ export class RegistrationService extends EventEmitter implements OnModuleInit {
})
}

public set permsData(perms: PermsData) {
console.log('Setting owner perms data')
this._permsData = {
certificate: perms.certificate,
privKey: perms.privKey,
}
}

public async registerOwnerCertificate(payload: RegisterOwnerCertificatePayload): Promise<void> {
let cert: string
try {
Expand Down Expand Up @@ -123,7 +140,7 @@ export class RegistrationService extends EventEmitter implements OnModuleInit {
this.emit(response.eventType, response.data)
}

private async registerUser(csr: string): Promise<{ status: number; body: any }> {
public async registerUser(csr: string): Promise<{ status: number; body: any }> {
const result = await registerUser(csr, this._permsData, this.certificates, this._ownerCertificate)
if (result?.status === 200) {
this.emit(RegistrationEvents.NEW_USER, { certificate: result.body.certificate, rootPermsData: this._permsData })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ export enum RegistrationEvents {
NEW_USER = 'newUser',
SET_CERTIFICATES = 'setCertificates',
REGISTRAR_STATE = 'registrarState',
REGISTER_USER_CERTIFICATE = 'registerUserCertificate',
}
17 changes: 13 additions & 4 deletions packages/backend/src/nest/socket/socket.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import {
LaunchRegistrarPayload,
Community,
DeleteFilesFromChannelSocketPayload,
SaveCSRPayload,
CommunityMetadata,
} from '@quiet/types'
import cors, { CorsOptions } from 'cors'
import EventEmitter from 'events'
Expand Down Expand Up @@ -100,11 +102,11 @@ export class SocketService extends EventEmitter implements OnModuleInit {
this.emit(SocketActionTypes.ASK_FOR_MESSAGES, payload)
})

socket.on(SocketActionTypes.REGISTER_USER_CERTIFICATE, async (payload: RegisterUserCertificatePayload) => {
this.logger(`Registering user certificate (${payload.communityId}) on ${payload.serviceAddress}`)
this.emit(SocketActionTypes.REGISTER_USER_CERTIFICATE, payload)
socket.on(SocketActionTypes.SAVE_USER_CSR, async (payload: SaveCSRPayload) => {
this.logger(`SAVING user CSR ${payload.csr}`)
this.emit(SocketActionTypes.SAVE_USER_CSR, payload)
await new Promise<void>(resolve => setTimeout(() => resolve(), 2000))
this.emit(SocketActionTypes.CONNECTION_PROCESS_INFO, ConnectionProcessInfo.REGISTERING_USER_CERTIFICATE)
this.emit(SocketActionTypes.CONNECTION_PROCESS_INFO, ConnectionProcessInfo.SAVING_USER_CSR)
})
socket.on(SocketActionTypes.REGISTER_OWNER_CERTIFICATE, async (payload: RegisterOwnerCertificatePayload) => {
this.logger(`Registering owner certificate (${payload.communityId})`)
Expand All @@ -114,6 +116,13 @@ export class SocketService extends EventEmitter implements OnModuleInit {
socket.on(SocketActionTypes.SAVE_OWNER_CERTIFICATE, async (payload: SaveOwnerCertificatePayload) => {
this.logger(`Saving owner certificate (${payload.peerId}), community: ${payload.id}`)
this.emit(SocketActionTypes.SAVED_OWNER_CERTIFICATE, payload)
const communityMetadataPayload: CommunityMetadata = {
id: payload.id,
ownerCertificate: payload.certificate,
rootCa: payload.permsData.certificate,
}
console.log('meta from state-manager', communityMetadataPayload)
this.emit(SocketActionTypes.SEND_COMMUNITY_METADATA, communityMetadataPayload)
})
socket.on(SocketActionTypes.CREATE_COMMUNITY, async (payload: InitCommunityPayload) => {
this.logger(`Creating community ${payload.id}`)
Expand Down
Loading