Skip to content
Merged
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
90 changes: 45 additions & 45 deletions ee/apps/federation-service/package.json
Original file line number Diff line number Diff line change
@@ -1,47 +1,47 @@
{
"name": "@rocket.chat/federation-service",
"private": true,
"version": "0.1.0",
"description": "Rocket.Chat Federation service",
"main": "./dist/index.js",
"exports": {
".": {
"import": "./dist/index.js",
"require": "./dist/index.js"
}
},
"scripts": {
"build": "tsc -p tsconfig.json",
"ms": "TRANSPORTER=${TRANSPORTER:-TCP} MONGO_URL=${MONGO_URL:-mongodb://localhost:3001/meteor} bun --watch run src/service.ts",
"start": "bun run src/service.ts",
"dev": "bun --watch run src/service.ts",
"test": "echo \"Error: no test specified\" && exit 1",
"lint": "eslint src",
"typecheck": "tsc --noEmit --skipLibCheck -p tsconfig.json"
},
"dependencies": {
"@hono/node-server": "^1.14.4",
"@rocket.chat/core-services": "workspace:^",
"@rocket.chat/core-typings": "workspace:*",
"@rocket.chat/emitter": "^0.31.25",
"@rocket.chat/federation-matrix": "workspace:^",
"@rocket.chat/homeserver": "workspace:*",
"@rocket.chat/http-router": "workspace:*",
"@rocket.chat/models": "workspace:*",
"hono": "^3.11.0",
"pino": "^8.16.0",
"polka": "^0.5.2",
"reflect-metadata": "^0.2.2",
"tsyringe": "^4.10.0",
"zod": "^3.22.0"
},
"devDependencies": {
"@types/bun": "latest",
"@types/express": "^4.17.17",
"typescript": "^5.3.0"
},
"keywords": [
"rocketchat"
],
"author": "Rocket.Chat"
"name": "@rocket.chat/federation-service",
"private": true,
"version": "0.1.0",
"description": "Rocket.Chat Federation service",
"main": "./dist/index.js",
"exports": {
".": {
"import": "./dist/index.js",
"require": "./dist/index.js"
}
},
"scripts": {
"build": "tsc -p tsconfig.json",
"ms": "TRANSPORTER=${TRANSPORTER:-TCP} MONGO_URL=${MONGO_URL:-mongodb://localhost:3001/meteor} bun --watch run src/service.ts",
"start": "bun run src/service.ts",
"dev": "bun --watch run src/service.ts",
"test": "echo \"Error: no test specified\" && exit 1",
"lint": "eslint src",
"typecheck": "tsc --noEmit --skipLibCheck -p tsconfig.json"
},
"dependencies": {
"@hono/node-server": "^1.14.4",
"@hs/federation-sdk": "workspace:*",
"@rocket.chat/core-services": "workspace:^",
"@rocket.chat/core-typings": "workspace:*",
"@rocket.chat/emitter": "^0.31.25",
"@rocket.chat/federation-matrix": "workspace:^",
"@rocket.chat/http-router": "workspace:*",
"@rocket.chat/models": "workspace:*",
"hono": "^3.11.0",
"pino": "^8.16.0",
"polka": "^0.5.2",
"reflect-metadata": "^0.2.2",
"tsyringe": "^4.10.0",
"zod": "^3.22.0"
},
"devDependencies": {
"@types/bun": "latest",
"@types/express": "^4.17.17",
"typescript": "^5.3.0"
},
"keywords": [
"rocketchat"
],
"author": "Rocket.Chat"
}
55 changes: 25 additions & 30 deletions ee/apps/federation-service/src/service.ts
Original file line number Diff line number Diff line change
@@ -1,41 +1,36 @@
import 'reflect-metadata';
import { serve } from '@hono/node-server';
import { api, getConnection, getTrashCollection } from '@rocket.chat/core-services';
import type { RouteDefinition, RouteContext } from '@rocket.chat/homeserver';
// import type { RouteDefinition, RouteContext } from '@hs/federation-sdk';
import { registerServiceModels } from '@rocket.chat/models';
import { startBroker } from '@rocket.chat/network-broker';
import { Hono } from 'hono';

import { config } from './config';

export function handleFederationRoutesRegistration(app: Hono, homeserverRoutes: RouteDefinition[]): Hono {
console.info(`Registering ${homeserverRoutes.length} homeserver routes`);

for (const route of homeserverRoutes) {
const method = route.method.toLowerCase() as 'get' | 'post' | 'put' | 'delete';

app[method](route.path, async (c) => {
try {
const context = {
req: c.req,
res: c.res,
params: c.req.param(),
query: c.req.query(),
body: await c.req.json().catch(() => ({})),
};

const result = await route.handler(context as unknown as RouteContext);

return c.json(result);
} catch (error) {
console.error(`Error handling route ${method.toUpperCase()} ${route.path}:`, error);
return c.json({ error: 'Internal server error' }, 500);
}
});
}

return app;
}
// export function handleFederationRoutesRegistration(app: Hono, homeserverRoutes: RouteDefinition[]): Hono {
// // console.info(`Registering ${homeserverRoutes.length} homeserver routes`);
// // for (const route of homeserverRoutes) {
// // const method = route.method.toLowerCase() as 'get' | 'post' | 'put' | 'delete';
// // app[method](route.path, async (c) => {
// // try {
// // const context = {
// // req: c.req,
// // res: c.res,
// // params: c.req.param(),
// // query: c.req.query(),
// // body: await c.req.json().catch(() => ({})),
// // };
// // const result = await route.handler(context as unknown as RouteContext);
// // return c.json(result);
// // } catch (error) {
// // console.error(`Error handling route ${method.toUpperCase()} ${route.path}:`, error);
// // return c.json({ error: 'Internal server error' }, 500);
// // }
// // });
// // }
// // return app;
// }

function handleHealthCheck(app: Hono) {
app.get('/health', async (c) => {
Expand All @@ -61,7 +56,7 @@ function handleHealthCheck(app: Hono) {
api.registerService(federationMatrix);

const app = new Hono();
handleFederationRoutesRegistration(app, federationMatrix.getAllRoutes());
// handleFederationRoutesRegistration(app, federationMatrix.getAllRoutes());
handleHealthCheck(app);

serve({
Expand Down
2 changes: 1 addition & 1 deletion ee/packages/federation-matrix/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@
"extends": "../../../package.json"
},
"dependencies": {
"@hs/federation-sdk": "workspace:^",
"@rocket.chat/core-services": "workspace:^",
"@rocket.chat/core-typings": "workspace:^",
"@rocket.chat/emitter": "^0.31.25",
"@rocket.chat/homeserver": "workspace:^",
"@rocket.chat/models": "workspace:^",
"@rocket.chat/network-broker": "workspace:^",
"mongodb": "6.10.0",
Expand Down
9 changes: 5 additions & 4 deletions ee/packages/federation-matrix/src/FederationMatrix.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { type IFederationMatrixService, ServiceClass, Settings } from '@rocket.chat/core-services';
import type { IMessage, IRoom, IUser } from '@rocket.chat/core-typings';
import { Emitter } from '@rocket.chat/emitter';
import type { HomeserverEventSignatures, HomeserverServices } from '@rocket.chat/homeserver';
import { setupHomeserver, getAllRoutes, getAllServices } from '@rocket.chat/homeserver';
import type { HomeserverEventSignatures, HomeserverServices } from '@hs/federation-sdk';
import { getAllServices } from '@hs/federation-sdk';
import { Logger } from '@rocket.chat/logger';
import { MatrixBridgedUser, MatrixBridgedRoom, Users } from '@rocket.chat/models';

import { registerEvents } from './events';
import { setup } from './setupContainers';

export class FederationMatrix extends ServiceClass implements IFederationMatrixService {
protected name = 'federation-matrix';
Expand All @@ -26,7 +27,7 @@ export class FederationMatrix extends ServiceClass implements IFederationMatrixS

async created(): Promise<void> {
try {
setupHomeserver({ emitter: this.eventHandler });
setup(this.eventHandler);
registerEvents(this.eventHandler);
} catch (error) {
this.logger.warn('Homeserver module not available, running in limited mode');
Expand All @@ -51,7 +52,7 @@ export class FederationMatrix extends ServiceClass implements IFederationMatrixS
}

getAllRoutes() {
return getAllRoutes();
return [];
}

async createRoom(room: IRoom, owner: IUser, members: string[]): Promise<void> {
Expand Down
2 changes: 1 addition & 1 deletion ee/packages/federation-matrix/src/events/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { HomeserverEventSignatures } from '@hs/federation-sdk';
import type { Emitter } from '@rocket.chat/emitter';
import type { HomeserverEventSignatures } from '@rocket.chat/homeserver';

import { invite } from './invite';
import { message } from './message';
Expand Down
2 changes: 1 addition & 1 deletion ee/packages/federation-matrix/src/events/invite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { Room } from '@rocket.chat/core-services';
import { UserStatus } from '@rocket.chat/core-typings';
import type { Emitter } from '@rocket.chat/emitter';
import type { HomeserverEventSignatures } from '@rocket.chat/homeserver';
import type { HomeserverEventSignatures } from '@hs/federation-sdk';
import { MatrixBridgedRoom, MatrixBridgedUser, Users } from '@rocket.chat/models';

export function invite(emitter: Emitter<HomeserverEventSignatures>) {
Expand Down
8 changes: 4 additions & 4 deletions ee/packages/federation-matrix/src/events/message.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import type { Emitter } from '@rocket.chat/emitter';
import type { HomeserverEventSignatures } from '@rocket.chat/homeserver';
import type { HomeserverEventSignatures } from '@hs/federation-sdk';
import { Message } from '@rocket.chat/core-services';
import { UserStatus } from '@rocket.chat/core-typings';
import type { IUser } from '@rocket.chat/core-typings';
import { Users, MatrixBridgedUser, MatrixBridgedRoom, Rooms, Subscriptions } from '@rocket.chat/models';
import type { Emitter } from '@rocket.chat/emitter';
import { Logger } from '@rocket.chat/logger';
import { Users, MatrixBridgedUser, MatrixBridgedRoom, Rooms, Subscriptions } from '@rocket.chat/models';

const logger = new Logger('federation-matrix:message');

Expand All @@ -17,7 +17,7 @@ export function message(emitter: Emitter<HomeserverEventSignatures>) {
sender: data.sender,
});

const message = data.event.content?.body?.toString();
const message = data.content?.body?.toString();
if (!message) {
logger.debug('No message found in event content');
return;
Expand Down
2 changes: 1 addition & 1 deletion ee/packages/federation-matrix/src/events/ping.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Emitter } from '@rocket.chat/emitter';
import type { HomeserverEventSignatures } from '@rocket.chat/homeserver';
import type { HomeserverEventSignatures } from '@hs/federation-sdk';

export const ping = async (emitter: Emitter<HomeserverEventSignatures>) => {
emitter.on('homeserver.ping', async (data) => {
Expand Down
110 changes: 110 additions & 0 deletions ee/packages/federation-matrix/src/setupContainers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import 'reflect-metadata';

import { toUnpaddedBase64 } from '@hs/core';
import {
ConfigService,
EventRepository,
type FederationModuleOptions,
FederationRequestService,
FederationService,
type HomeserverEventSignatures,
KeyRepository,
RoomRepository,
ServerRepository,
StateEventRepository,
StateRepository,
MissingEventListener,
DatabaseConnectionService,
EventAuthorizationService,
EventFetcherService,
EventStateService,
EventService,
EventEmitterService,
InviteService,
MessageService,
MissingEventService,
NotificationService,
ProfilesService,
RoomService,
ServerService,
StateService,
StagingAreaService,
WellKnownService,
LockManagerService,
MissingEventsQueue,
StagingAreaListener,
StagingAreaQueue,
} from '@hs/federation-sdk';
import { Emitter } from '@rocket.chat/emitter';
import { container } from 'tsyringe';

export async function setup(emitter: Emitter<HomeserverEventSignatures> = new Emitter<HomeserverEventSignatures>()) {
const config = new ConfigService();
const matrixConfig = config.getMatrixConfig();
const serverConfig = config.getServerConfig();
const signingKeys = await config.getSigningKey();
const signingKey = signingKeys[0];

container.register<FederationModuleOptions>('FEDERATION_OPTIONS', {
useValue: {
serverName: matrixConfig.serverName,
signingKey: toUnpaddedBase64(signingKey.privateKey),
signingKeyId: `ed25519:${signingKey.version}`,
timeout: 30000,
baseUrl: serverConfig.baseUrl,
},
});

container.registerSingleton(FederationRequestService);
container.registerSingleton('ConfigService', ConfigService);
container.registerSingleton('DatabaseConnectionService', DatabaseConnectionService);
container.registerSingleton('StateRepository', StateRepository);
container.registerSingleton(StateService);
container.registerSingleton(EventAuthorizationService);
container.registerSingleton(EventFetcherService);
container.registerSingleton(EventStateService);
container.registerSingleton('EventService', EventService);
container.registerSingleton(EventEmitterService);
container.registerSingleton(InviteService);
container.registerSingleton(MessageService);
container.registerSingleton(MissingEventService);
container.registerSingleton(NotificationService);
container.registerSingleton(ProfilesService);
container.registerSingleton(RoomService);
container.registerSingleton('RoomService', RoomService);
container.registerSingleton(ServerService);
container.registerSingleton(StagingAreaService);
container.registerSingleton('StagingAreaService', StagingAreaService);
container.registerSingleton(WellKnownService);
container.registerSingleton('EventRepository', EventRepository);
container.registerSingleton('KeyRepository', KeyRepository);
container.registerSingleton('RoomRepository', RoomRepository);
container.registerSingleton('ServerRepository', ServerRepository);
container.registerSingleton('StateRepository', StateRepository);
container.registerSingleton('StateEventRepository', StateEventRepository);
container.registerSingleton('MissingEventsQueue', MissingEventsQueue);
container.registerSingleton('StagingAreaQueue', StagingAreaQueue);
container.registerSingleton(MissingEventListener);
container.registerSingleton(StagingAreaListener);
container.registerSingleton('FederationService', FederationService);

container.register(LockManagerService, {
useFactory: () => new LockManagerService({ type: 'memory' }),

// NATS configuration example:
// useFactory: () => new LockManagerService({
// type: 'nats',
// servers: ['nats://localhost:4222'],
// timeout: 5000,
// reconnect: true,
// maxReconnectAttempts: 10
// })
});

const eventEmitterService = container.resolve(EventEmitterService);

eventEmitterService.setEmitter(emitter);

container.resolve(StagingAreaListener);
container.resolve(MissingEventListener);
}
Loading
Loading