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

Chore/2312 #2450

Closed
wants to merge 49 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
28dc343
refactor: adjust customProtocolSaga code to be similar to deepLinkSag…
EmiM Mar 5, 2024
b8aa768
fix: customProtocolSaga tests
EmiM Mar 5, 2024
928a412
Merge branch 'develop' into feature/2310
EmiM Mar 5, 2024
1460d57
fix: tests; add missing file
EmiM Mar 5, 2024
b4e8f45
fix: main.ts test
EmiM Mar 6, 2024
7d0b19a
feat: handle old (psk, orbitdbIdentity, addresses) and new (cid, toke…
EmiM Mar 7, 2024
d386067
chore: adjust types
EmiM Mar 11, 2024
d5f7b66
chore: add joinNetwork saga that gathers data for createNetwork; mock…
EmiM Mar 11, 2024
67268d2
Merge branch 'develop' into feature/2310
EmiM Mar 11, 2024
a4d674b
refactor: invitation link parsers
EmiM Mar 14, 2024
8cc6fd3
fix: deepLink saga tests
EmiM Mar 14, 2024
b8203f9
refactor: simplify deepLink and customProtocol sagas
EmiM Mar 15, 2024
7d75c3a
fix: invitation code utils tests
EmiM Mar 15, 2024
d333cfe
chore: add missing github workflow for running common package tests
EmiM Mar 15, 2024
de8533c
refactor: invitation code tests
EmiM Mar 18, 2024
4895b29
fix: unit tests
EmiM Mar 18, 2024
3b5cf43
Merge branch 'develop' into feature/2310
EmiM Mar 18, 2024
54b925c
Merge branch 'develop' into feature/2310
EmiM Mar 19, 2024
6e82f71
feat: add one script for preparing AppImage for e2e tests
EmiM Mar 19, 2024
5f80ac1
fix: 'copy app image for e2e' script
EmiM Mar 19, 2024
7471a24
fix: getting env file name in e2e tests
EmiM Mar 19, 2024
967665d
chore: remove unused code responsible for locking invitation link for…
EmiM Mar 20, 2024
9f84ffe
chore: update changelog
EmiM Mar 20, 2024
bc2430d
Merge branch 'develop' into feature/2310
EmiM Mar 21, 2024
066a201
Merge branch 'develop' into feature/2310
EmiM Mar 25, 2024
3c6796d
feat: add storage server proxy for downloading and uploading data fro…
EmiM Mar 27, 2024
c6c9df4
feat: joining with v2 invitation link
EmiM Mar 28, 2024
6e35699
feat: handle relay server connection errors
EmiM Mar 28, 2024
7e6b4bc
test: add basic storage service proxy tests
EmiM Apr 2, 2024
0963a59
feat: add basic server stored metadata validator
EmiM Apr 2, 2024
fa0d7b9
Merge branch 'develop' into feature/2295
EmiM Apr 4, 2024
beaec60
Merge branch 'develop' into feature/2310
EmiM Apr 4, 2024
376a74c
Merge branch 'feature/2310' into feature/2295
EmiM Apr 4, 2024
2ff58f7
fix: pass dispatch to useEffect
EmiM Apr 4, 2024
7f28330
fix: move handling server error to container
EmiM Apr 5, 2024
cd863db
Merge branch 'develop' into feature/2310
EmiM Apr 9, 2024
a529c7f
fix: mobile tests
EmiM Apr 9, 2024
fcd8b2b
fix: long failing backend test
EmiM Apr 10, 2024
7b5b688
Merge branch 'develop' into feature/2310
EmiM Apr 10, 2024
3b6ec98
Merge branch 'feature/2310' into feature/2295
EmiM Apr 10, 2024
611ffe5
fix: add missing import
EmiM Apr 10, 2024
521c130
test: add Dockerfile for running QSS with e2e test; add e2e test for …
EmiM Apr 11, 2024
bd07e99
refactor: deduplicate UserTestData interface
EmiM Apr 11, 2024
ed6a907
chore: remove DuplicatedCertBug logs
EmiM Apr 11, 2024
ffaea57
test: add temporary workaround to e2e test to fully join community wi…
EmiM Apr 11, 2024
f5c7925
fix: add missing file and fix test
EmiM Apr 12, 2024
3f1051e
feat: pass invitation data to createNetwork saga and LAUNCH_COMMUNITY…
EmiM Apr 15, 2024
858065f
refactor: Remove DOWNLOAD_INVITE_DATA event; remove joinNetwork saga;…
EmiM Apr 15, 2024
7c0898a
fix: tests
EmiM Apr 16, 2024
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
29 changes: 29 additions & 0 deletions .github/workflows/utils-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Common package tests

on:
pull_request:
paths:
- packages/common/**

jobs:
utils-tests:
timeout-minutes: 25
runs-on: ${{ matrix.os }}

strategy:
matrix:
os: [ubuntu-20.04, macos-latest, windows-2019]

steps:
- name: "Print OS"
run: echo ${{ matrix.os }}

- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1

- name: "Setup environment"
uses: ./.github/actions/setup-env
with:
bootstrap-packages: "@quiet/eslint-config,@quiet/logger,@quiet/types,@quiet/common"

- name: "Unit tests"
run: lerna run test --scope @quiet/common --stream
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@

# New features:

* Add support for new format of invitation link: `c=<cid>&t=<token>&s=<serverAddress>&i=<inviterAddress>` ([#2310](https://github.com/TryQuiet/quiet/issues/2310))
* Use server for downloading initial community metadata if v2 invitation link is detected ([#2295](https://github.com/TryQuiet/quiet/issues/2295))

# Refactorings:

# Fixes:
# Fixes

# Chores

Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
"start:desktop": "lerna run --scope @quiet/desktop start",
"lint:all": "lerna run lint",
"distAndRunE2ETests:mac:local": "lerna run --scope @quiet/desktop distMac:local && lerna run --scope e2e-tests test:localBinary --",
"e2e:linux:build": "lerna run --scope @quiet/backend webpack:prod && lerna run --scope @quiet/desktop distUbuntu && lerna run --scope e2e-tests linux:copy",
"e2e:linux:run": "lerna run --scope e2e-tests test --",
"prepare": "husky",
"lint-staged": "lerna run lint-staged"
},
Expand Down
13 changes: 8 additions & 5 deletions packages/backend/jestSetup.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import { setEngine, CryptoEngine } from'pkijs'
import { setEngine, CryptoEngine } from 'pkijs'
import { Crypto } from '@peculiar/webcrypto'

const crypto = new Crypto();
global.crypto = crypto;
const crypto = new Crypto()
global.crypto = crypto

setEngine('newEngine', new CryptoEngine({
setEngine(
'newEngine',
new CryptoEngine({
name: 'newEngine',
// @ts-ignore
crypto: crypto,
}))
})
)
11 changes: 11 additions & 0 deletions packages/backend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@
"dotenv": "8.2.0",
"events": "^3.2.0",
"express": "^4.17.1",
"fetch-retry": "^6.0.0",
"get-port": "^5.1.1",
"go-ipfs": "npm:[email protected]",
"http-server": "^0.12.3",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ import { SocketModule } from '../socket/socket.module'
import { StorageModule } from '../storage/storage.module'
import { TorModule } from '../tor/tor.module'
import { ConnectionsManagerService } from './connections-manager.service'
import { ServerProxyServiceModule } from '../storageServerProxy/storageServerProxy.module'

@Module({
imports: [RegistrationModule, StorageModule, TorModule, SocketModule, LocalDbModule],
imports: [RegistrationModule, StorageModule, TorModule, SocketModule, LocalDbModule, ServerProxyServiceModule],
providers: [ConnectionsManagerService],
exports: [ConnectionsManagerService],
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ 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 { createPeerId, createTmpDir, libp2pInstanceParams, removeFilesFromDir, tmpQuietDirPath } from '../common/utils'

import { NetworkStats, type Community, type Identity, type InitCommunityPayload } from '@quiet/types'
import { NetworkStats, type Community, type Identity } from '@quiet/types'
import { LazyModuleLoader } from '@nestjs/core'
import { TestingModule, Test } from '@nestjs/testing'
import { FactoryGirl } from 'factory-girl'
Expand Down Expand Up @@ -113,7 +112,6 @@ beforeEach(async () => {
})

afterEach(async () => {
await libp2pService?.libp2pInstance?.stop()
if (connectionsManagerService) {
await connectionsManagerService.closeAllServices()
}
Expand All @@ -122,6 +120,10 @@ afterEach(async () => {

describe('Connections manager', () => {
it('saves peer stats when peer has been disconnected', async () => {
// @ts-expect-error
libp2pService.processInChunksService.init = jest.fn()
// @ts-expect-error
libp2pService.processInChunksService.process = jest.fn()
class RemotePeerEventDetail {
peerId: string

Expand All @@ -137,6 +139,10 @@ describe('Connections manager', () => {

// Peer connected
await connectionsManagerService.init()
await connectionsManagerService.launchCommunity({
community,
network: { peerId: userIdentity.peerId, hiddenService: userIdentity.hiddenService },
})
libp2pService.connectedPeers.set(peerId.toString(), DateTime.utc().valueOf())

// Peer disconnected
Expand All @@ -145,11 +151,16 @@ describe('Connections manager', () => {
remotePeer: new RemotePeerEventDetail(peerId.toString()),
remoteAddr: new RemotePeerEventDetail(remoteAddr),
}
await waitForExpect(async () => {
expect(libp2pService.libp2pInstance).not.toBeUndefined()
}, 2_000)
libp2pService.libp2pInstance?.dispatchEvent(
new CustomEvent('peer:disconnect', { detail: peerDisconectEventDetail })
)
await waitForExpect(async () => {
expect(libp2pService.connectedPeers.size).toEqual(0)
}, 2000)

expect(libp2pService.connectedPeers.size).toEqual(0)
await waitForExpect(async () => {
expect(await localDbService.get(LocalDBKeys.PEERS)).not.toBeNull()
}, 2000)
Expand All @@ -166,7 +177,6 @@ describe('Connections manager', () => {
const spyOnDestroyHiddenService = jest.spyOn(tor, 'destroyHiddenService')
await connectionsManagerService.init()
const network = await connectionsManagerService.getNetwork()
console.log('network', network)
expect(network.hiddenService.onionAddress.split('.')[0]).toHaveLength(56)
expect(network.hiddenService.privateKey).toHaveLength(99)
const peerId = await PeerId.createFromJSON(network.peerId)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,69 +1,69 @@
import { peerIdFromKeys } from '@libp2p/peer-id'
import { Inject, Injectable, OnModuleInit } from '@nestjs/common'
import { Crypto } from '@peculiar/webcrypto'
import { Agent } from 'https'
import fs from 'fs'
import path from 'path'
import { peerIdFromKeys } from '@libp2p/peer-id'
import { setEngine, CryptoEngine } from 'pkijs'
import { EventEmitter } from 'events'
import fs from 'fs'
import getPort from 'get-port'
import { Agent } from 'https'
import path from 'path'
import PeerId from 'peer-id'
import { CryptoEngine, setEngine } from 'pkijs'
import { getLibp2pAddressesFromCsrs, removeFilesFromDir } from '../common/utils'

import { LazyModuleLoader } from '@nestjs/core'
import { createLibp2pAddress, isPSKcodeValid, p2pAddressesToPairs } from '@quiet/common'
import { CertFieldsTypes, getCertFieldValue, loadCertificate } from '@quiet/identity'
import {
GetMessagesPayload,
ChannelMessageIdsResponse,
type DeleteChannelResponse,
ChannelSubscribedPayload,
ChannelsReplicatedPayload,
Community,
CommunityId,
CommunityMetadata,
CommunityOwnership,
ConnectionProcessInfo,
CreateChannelPayload,
CreateChannelResponse,
CreateNetworkPayload,
DeleteFilesFromChannelSocketPayload,
DownloadStatus,
ErrorMessages,
FileMetadata,
MessagesLoadedPayload,
GetMessagesPayload,
InitCommunityPayload,
MessagesLoadedPayload,
NetworkDataPayload,
NetworkInfo,
NetworkStats,
type SavedOwnerCertificatePayload,
PushNotificationPayload,
RegisterOwnerCertificatePayload,
RemoveDownloadStatus,
SaveCSRPayload,
SendCertificatesResponse,
SendMessagePayload,
ChannelSubscribedPayload,
ServerInvitationData,
SocketActionTypes,
StorePeerListPayload,
UploadFilePayload,
PeerId as PeerIdType,
SaveCSRPayload,
CommunityMetadata,
type PermsData,
type DeleteChannelResponse,
type SavedOwnerCertificatePayload,
type UserProfile,
type UserProfilesStoredEvent,
} from '@quiet/types'
import Logger from '../common/logger'
import { CONFIG_OPTIONS, QUIET_DIR, SERVER_IO_PROVIDER, SOCKS_PROXY_AGENT } from '../const'
import { ConfigOptions, GetPorts, ServerIoProviderTypes } from '../types'
import { SocketService } from '../socket/socket.service'
import { RegistrationService } from '../registration/registration.service'
import { LocalDbService } from '../local-db/local-db.service'
import { StorageService } from '../storage/storage.service'
import { ServiceState, TorInitState } from './connections-manager.types'
import { Libp2pService } from '../libp2p/libp2p.service'
import { Tor } from '../tor/tor.service'
import { LocalDBKeys } from '../local-db/local-db.types'
import { Libp2pEvents, Libp2pNodeParams } from '../libp2p/libp2p.types'
import { LocalDbService } from '../local-db/local-db.service'
import { LocalDBKeys } from '../local-db/local-db.types'
import { RegistrationService } from '../registration/registration.service'
import { RegistrationEvents } from '../registration/registration.types'
import { StorageEvents } from '../storage/storage.types'
import { LazyModuleLoader } from '@nestjs/core'
import Logger from '../common/logger'
import { emitError } from '../socket/socket.errors'
import { createLibp2pAddress, isPSKcodeValid } from '@quiet/common'
import { CertFieldsTypes, createRootCA, getCertFieldValue, loadCertificate } from '@quiet/identity'
import { SocketService } from '../socket/socket.service'
import { StorageService } from '../storage/storage.service'
import { StorageEvents } from '../storage/storage.types'
import { ServerProxyService } from '../storageServerProxy/storageServerProxy.service'
import { ServerStoredCommunityMetadata } from '../storageServerProxy/storageServerProxy.types'
import { Tor } from '../tor/tor.service'
import { ConfigOptions, GetPorts, ServerIoProviderTypes } from '../types'
import { ServiceState, TorInitState } from './connections-manager.types'

@Injectable()
export class ConnectionsManagerService extends EventEmitter implements OnModuleInit {
Expand All @@ -81,6 +81,7 @@ export class ConnectionsManagerService extends EventEmitter implements OnModuleI
@Inject(SOCKS_PROXY_AGENT) public readonly socksProxyAgent: Agent,
private readonly socketService: SocketService,
private readonly registrationService: RegistrationService,
private readonly storageServerProxyService: ServerProxyService,
private readonly localDbService: LocalDbService,
private readonly storageService: StorageService,
private readonly tor: Tor,
Expand Down Expand Up @@ -392,15 +393,51 @@ export class ConnectionsManagerService extends EventEmitter implements OnModuleI
return community
}

public async downloadCommunityData(inviteData: ServerInvitationData) {
this.logger('Downloading invite data', inviteData)
this.storageServerProxyService.setServerAddress(inviteData.serverAddress)
let downloadedData: ServerStoredCommunityMetadata
try {
downloadedData = await this.storageServerProxyService.downloadData(inviteData.cid)
} catch (e) {
this.logger.error(`Downloading community data failed`, e)
return
}
return {
psk: downloadedData.psk,
peers: downloadedData.peerList,
ownerOrbitDbIdentity: downloadedData.ownerOrbitDbIdentity,
}
}

public async joinCommunity(payload: InitCommunityPayload): Promise<Community | undefined> {
this.logger('Joining community: peers:', payload.peers)
let metadata = {
psk: payload.psk,
peers: payload.peers,
ownerOrbitDbIdentity: payload.ownerOrbitDbIdentity,
}

if (!payload.peers || payload.peers.length === 0) {
const inviteData = payload.inviteData
if (inviteData) {
const downloadedData = await this.downloadCommunityData(inviteData)
if (!downloadedData) {
emitError(this.serverIoProvider.io, {
type: SocketActionTypes.LAUNCH_COMMUNITY,
message: ErrorMessages.STORAGE_SERVER_CONNECTION_FAILED,
})
return
}
metadata = downloadedData
}
this.logger('Joining community: metadata:', metadata)

if (!metadata.peers || metadata.peers.length === 0) {
this.logger.error('Joining community: Peers required')
return
}

if (!payload.psk || !isPSKcodeValid(payload.psk)) {
if (!metadata.psk || !isPSKcodeValid(metadata.psk)) {
this.logger.error('Joining community: Libp2p PSK is not valid')
emitError(this.serverIoProvider.io, {
type: SocketActionTypes.LAUNCH_COMMUNITY,
Expand All @@ -410,7 +447,7 @@ export class ConnectionsManagerService extends EventEmitter implements OnModuleI
return
}

if (!payload.ownerOrbitDbIdentity) {
if (!metadata.ownerOrbitDbIdentity) {
this.logger.error('Joining community: ownerOrbitDbIdentity is not valid')
emitError(this.serverIoProvider.io, {
type: SocketActionTypes.LAUNCH_COMMUNITY,
Expand All @@ -424,9 +461,9 @@ export class ConnectionsManagerService extends EventEmitter implements OnModuleI

const community = {
id: payload.id,
peerList: [...new Set([localAddress, ...payload.peers])],
psk: payload.psk,
ownerOrbitDbIdentity: payload.ownerOrbitDbIdentity,
peerList: [...new Set([localAddress, ...metadata.peers])],
psk: metadata.psk,
ownerOrbitDbIdentity: metadata.ownerOrbitDbIdentity,
}

const network = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export class ProcessInChunksService<T> extends EventEmitter {
super()
}

public init(data: T[], processItem: (arg: T) => Promise<any>, chunkSize: number = DEFAULT_CHUNK_SIZE) {
public init(data: T[] = [], processItem: (arg: T) => Promise<any>, chunkSize: number = DEFAULT_CHUNK_SIZE) {
this.data = data
this.processItem = processItem
this.chunkSize = chunkSize
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ export const extractPendingCsrs = async (payload: { csrs: string[]; certificates
pendingCsrs.push(csr)
}
}
logger('DuplicatedCertBug', { parsedUniqueCsrs, pendingNames, certNames })
return pendingCsrs
}

Expand Down
Loading
Loading