Skip to content
Draft
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
123 changes: 123 additions & 0 deletions .github/support/prosody.cfg.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
run_as_root = true
daemonize = false

---------- Server-wide settings ----------
-- Settings in this section apply to the whole server and are the default settings
-- for any virtual hosts

-- This is a (by default, empty) list of accounts that are admins
-- for the server. Note that you must create the accounts separately
-- (see https://prosody.im/doc/creating_accounts for info)
-- Example: admins = { "user1@example.com", "user2@example.net" }
admins = { }

-- Enable use of libevent for better performance under high load
-- For more information see: https://prosody.im/doc/libevent
--use_libevent = true

-- Prosody will always look in its source directory for modules, but
-- this option allows you to specify additional locations where Prosody
-- will look for modules first. For community modules, see https://modules.prosody.im/
plugin_paths = { "/usr/lib/prosody-modules" }

-- This is the list of modules Prosody will load on startup.
-- It looks for mod_modulename.lua in the plugins folder, so make sure that exists too.
-- Documentation for bundled modules can be found at: https://prosody.im/doc/modules
modules_enabled = {

-- Generally required
"roster"; -- Allow users to have a roster. Recommended ;)
"saslauth"; -- Authentication for clients and servers. Recommended if you want to log in.
"tls"; -- Add support for secure TLS on c2s/s2s connections
"dialback"; -- s2s dialback support
"disco"; -- Service discovery

-- Not essential, but recommended
"carbons"; -- Keep multiple clients in sync
"pep"; -- Enables users to publish their mood, activity, playing music and more
"private"; -- Private XML storage (for room bookmarks, etc.)
"blocklist"; -- Allow users to block communications with other users
"vcard"; -- Allow users to set vCards

-- Nice to have
"version"; -- Replies to server version requests
"uptime"; -- Report how long server has been running
"time"; -- Let others know the time here on this server
"ping"; -- Replies to XMPP pings with pongs
"register"; -- Allow users to register on this server using a client and change passwords
--"mam"; -- Store messages in an archive and allow users to access it

-- Admin interfaces
"admin_adhoc"; -- Allows administration via an XMPP client that supports ad-hoc commands
--"admin_telnet"; -- Opens telnet console interface on localhost port 5582

-- HTTP modules
--"bosh"; -- Enable BOSH clients, aka "Jabber over HTTP"
--"websocket"; -- XMPP over WebSockets
--"http_files"; -- Serve static files from a directory over HTTP

-- Other specific functionality
--"limits"; -- Enable bandwidth limiting for XMPP connections
--"groups"; -- Shared roster support
"server_contact_info"; -- Publish contact information for this service
--"announce"; -- Send announcement to all online users
--"welcome"; -- Welcome users who register accounts
--"watchregistrations"; -- Alert admins of registrations
--"motd"; -- Send a message to users when they log in
--"legacyauth"; -- Legacy authentication. Only used by some old clients and bots.
--"proxy65"; -- Enables a file transfer proxy service which clients behind NAT can use

"bidi" -- Bi-directional S2S streams

-- Bridging
-- This was disabled as we now use components, which do not require us to register users.
-- "register_json"
}

-- These modules are auto-loaded, but should you want
-- to disable them then uncomment them here:
modules_disabled = {
-- "offline"; -- Store offline messages
-- "c2s"; -- Handle client connections
-- "s2s"; -- Handle server-to-server connections
"posix"; -- POSIX functionality, sends server to background, enables syslog, etc.
}

allow_registration = true
c2s_require_encryption = true
s2s_require_encryption = true
s2s_secure_auth = true

component_ports = { 5347 }
component_interfaces = { "*" }

authentication = "internal_hashed"

archive_expires_after = "1w" -- Remove archived messages after 1 week

log = "*console"

-- Uncomment to enable statistics
-- For more info see https://prosody.im/doc/statistics
-- statistics = "internal"

-- Certificates
-- Every virtual host and component needs a certificate so that clients and
-- servers can securely verify its identity. Prosody will automatically load
-- certificates/keys from the directory specified here.
-- For more information, including how to use 'prosodyctl' to auto-import certificates
-- (from e.g. Let's Encrypt) see https://prosody.im/doc/certificates

-- Location of directory to find certificates in (relative to main config file):
certificates = "certs"

VirtualHost "localhost"

-- This must be localhost, it's not used but it allows
-- prosody to start.

------ Components ------

-- This is for the purple bridge
Component "matrixbridge.localhost"
component_secret = "my_service_password"
132 changes: 132 additions & 0 deletions .github/workflows/e2e-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
name: E2E tests

on:
push:
branches: ["develop", "release-*"]
pull_request:
workflow_dispatch:

jobs:
# Build the latest version of complement-compatible-synapse, and cache the image for use in e2e tests.
build-synapse:
runs-on: ubuntu-latest
steps:
- name: Checkout synapse
uses: actions/checkout@v3
with:
repository: matrix-org/synapse
ref: master
- name: Get synapse git sha
id: gitsha
run: echo '::set-output name=sha::'`git rev-parse --short HEAD`
- name: Cache complement-synapse image
id: cached-image
uses: actions/cache@v3
with:
path: /tmp/img-synapse.tar
key: ${{ runner.os }}-complement-synapse-${{ steps.gitsha.outputs.sha }}
- if: ${{ steps.cached-image.outputs.cache-hit != 'true' }}
name: Build images
run: |
# enable buildkit for the docker builds
export DOCKER_BUILDKIT=1
docker build -f docker/Dockerfile-workers -t matrixdotorg/synapse-workers:latest .
docker build -f docker/complement/Dockerfile -t complement-synapse:latest docker/complement
docker image save complement-synapse:latest > /tmp/img-synapse.tar

prosody-test:
runs-on: ubuntu-latest
timeout-minutes: 30
needs:
- build-synapse
services:
postgres:
image: postgres:latest
ports:
- 5432:5432
env:
POSTGRES_DB: postgres
POSTGRES_PASSWORD: postgres_password
POSTGRES_PORT: 5432
POSTGRES_USER: postgres_user
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- name: "Set Go Version"
run: |
echo "$GOROOT_1_17_X64/bin" >> $GITHUB_PATH
echo "~/go/bin" >> $GITHUB_PATH
- name: Checkout matrix-bifrost
uses: actions/checkout@v3
with:
path: matrix-bifrost

# Set up the XMPP server
- name: Set up prosody
run: |
sudo apt update
sudo apt install prosody
sudo cp matrix-bifrost/.github/support/prosody.cfg.lua /etc/prosody/prosody.cfg.lua
sudo /etc/init.d/prosody start
sudo prosodyctl register bob localhost xmpp_password

# Pull the complement-synapse image from cache
- name: Checkout synapse
uses: actions/checkout@v3
with:
path: synapse
repository: matrix-org/synapse
ref: master
- name: Get synapse git sha
id: gitsha
run: |
cd synapse
echo '::set-output name=sha::'`git rev-parse --short HEAD`
cd ..
- name: Load cached complement-synapse image
uses: actions/cache@v3
with:
path: /tmp/img-synapse.tar
key: ${{ runner.os }}-complement-synapse-${{ steps.gitsha.outputs.sha }}
- name: Load images
run: |
docker load --input /tmp/img-synapse.tar

# Build and install homerunner
- name: Checkout matrix-org/complement
uses: actions/checkout@v3
with:
repository: matrix-org/complement
path: complement
- name: Install Complement Dependencies
run: |
sudo apt-get update && sudo apt-get install -y libolm3 libolm-dev
- name: Build homerunner
run: |
cd complement
go build ./cmd/homerunner
cd ..

# Setup node & run tests
- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: 18
- name: Run Homerunner tests
timeout-minutes: 10
env:
BIFROST_TEST_PGDB: "bifrost_integtest"
BIFROST_TEST_PGURL: "postgresql://postgres_user:postgres_password@localhost"
BIFROST_TEST_ENABLEPG: "yes"
BIFROST_TEST_XMPP_SERVICE: "xmpp://localhost:5347"
BIFROST_TEST_XMPP_DOMAIN: "matrixbridge.localhost"
BIFROST_TEST_XMPP_PASSWORD: "my_service_password"
BIFROST_TEST_XMPP_USER: "bob:xmpp_test"
run: |
cd matrix-bifrost
yarn --frozen
HOMERUNNER_SPAWN_HS_TIMEOUT_SECS=100 ../complement/homerunner &
bash -ic 'yarn test:e2e'
11 changes: 9 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"start": "node lib/Program.js -c config.yaml",
"genreg": "node lib/Program.js -r -c config.yaml",
"test": "mocha -r ts-node/register test/test.ts test/*.ts test/**/*.ts",
"test:e2e": "jest --config spec/jest.config.js 'spec/e2e/*'",
"changelog": "scripts/towncrier.sh",
"coverage": "nyc mocha -r ts-node/register test/test.ts test/*.ts test/**/*.ts"
},
Expand All @@ -28,12 +29,16 @@
},
"homepage": "https://github.com/matrix-org/matrix-bifrost",
"dependencies": {
"@xmpp/client": "^0.13.1",
"@xmpp/component": "^0.12.0",
"@xmpp/component-core": "^0.12.0",
"@xmpp/jid": "^0.12.0",
"@xmpp/reconnect": "^0.12.0",
"@xmpp/xml": "^0.12.0",
"axios": "^0.21.1",
"cross-fetch": "^3.1.5",
"fast-xml-parser": "^3.17.4",
"homerunner-client": "^0.0.6",
"html-entities": "^2.3.2",
"htmlparser2": "^6.1.0",
"leven": "^3.1.0",
Expand All @@ -42,7 +47,6 @@
"pg": "8.7.1",
"prom-client": "^13.1.0",
"quick-lru": "^5.1.1",
"axios": "^0.21.1",
"source-map-support": "^0.5.19",
"uuid": "^8.3.2"
},
Expand All @@ -52,8 +56,9 @@
"@types/marked": "^2.0.4",
"@types/mocha": "^9.0.0",
"@types/nedb": "^1.8.12",
"@types/node": "^12",
"@types/node": "^16",
"@types/pg": "^7.14.5",
"@types/xmpp__client": "^0.13.0",
"@types/xmpp__jid": "^1.3.1",
"@types/xmpp__xml": "^0.6.1",
"@typescript-eslint/eslint-plugin": "^4.28.5",
Expand All @@ -63,10 +68,12 @@
"eslint": "^7.31.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-jsdoc": "^39.3.6",
"jest": "^29.2.1",
"mocha": "^9.0.3",
"mock-require": "^3.0.3",
"nedb": "^1.8.0",
"nyc": "^15.1.0",
"ts-jest": "^29.0.3",
"ts-node": "^10.1.0",
"typescript": "^4.3.5"
},
Expand Down
33 changes: 33 additions & 0 deletions spec/e2e/basic.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { BifrostTestEnvironment } from "../utils/test";
import { it, expect } from '@jest/globals';
import xml from "@xmpp/xml";

BifrostTestEnvironment.describeTest('Basic bridge usage', (env) => {
it('should be able to handle an incoming DM', async () => {
const { homeserver, bifrostBridge, client } = env();
const alice = homeserver.users[0].client;
const bob = client;

// Send a message to alice
await bob.send(xml("message", {
from: bob.jid?.toString(),
id: Date.now(),
to: 'alice@matrixbridge.localhost',
type: 'chat',
'xml:lang': 'en',
}, xml("body", "Hello world!")));

const { roomId } = await alice.waitForRoomEvent(
{eventType: 'm.room.member', sender: '@_xmpp_bob:localhost'}
);
const message = alice.waitForRoomEvent(
{eventType: 'm.room.message', sender: '@_xmpp_bob:localhost'}
);
await alice.joinRoom(roomId);
await alice.getRoomStateEvent(roomId, 'm.room.create', '');
// Await for the XMPP message.
await message;
});
}, {
matrixLocalparts: ['alice'],
});
6 changes: 6 additions & 0 deletions spec/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
transformIgnorePatterns: ['<rootDir>/node_modules/'],
};
Loading