diff --git a/config/default.yaml b/config/default.yaml index 200af3d..2c60a7c 100644 --- a/config/default.yaml +++ b/config/default.yaml @@ -3,9 +3,23 @@ web: port: 8184 address: '0.0.0.0' -# Homeserver configuration (used to proxy some requests to the homeserver for processing) +# Homeserver configuration homeserver: + # The domain name of the homeserver. This is used in many places, such as with go-neb + # setups, to identify the homeserver. name: "t2bot.io" + + # The URL that Dimension, go-neb, and other services provisioned by Dimension should + # use to access the homeserver with. + clientServerUrl: "https://t2bot.io" + + # The URL that Dimension should use when trying to communicate with federated APIs on + # the homeserver. If not supplied or left empty Dimension will try to resolve the address + # through the normal federation process. + #federationUrl: "https://t2bot.io:8448" + + # The access token Dimension should use for miscellaneous access to the homeserver. This + # should be for a valid user. accessToken: "something" # These users can modify the integrations this Dimension supports. @@ -16,10 +30,10 @@ admins: # IPs and CIDR ranges listed here will be blocked from being widgets. # Note: Widgets may still be embedded with restricted content, although not through Dimension directly. widgetBlacklist: -- 10.0.0.0/8 -- 172.16.0.0/12 -- 192.168.0.0/16 -- 127.0.0.0/8 + - 10.0.0.0/8 + - 172.16.0.0/12 + - 192.168.0.0/16 + - 127.0.0.0/8 # Where the database for Dimension is database: diff --git a/src/api/admin/AdminAppserviceService.ts b/src/api/admin/AdminAppserviceService.ts index efdc667..16aac81 100644 --- a/src/api/admin/AdminAppserviceService.ts +++ b/src/api/admin/AdminAppserviceService.ts @@ -4,7 +4,6 @@ import AppService from "../../db/models/AppService"; import { AppserviceStore } from "../../db/AppserviceStore"; import { ApiError } from "../ApiError"; import { MatrixAppserviceClient } from "../../matrix/MatrixAppserviceClient"; -import config from "../../config"; import { LogService } from "matrix-js-snippets"; interface AppserviceResponse { @@ -67,7 +66,7 @@ export class AdminAppserviceService { await AdminService.validateAndGetAdminTokenOwner(scalarToken); const appservice = await AppserviceStore.getAppservice(asId); - const client = new MatrixAppserviceClient(config.homeserver.name, appservice); + const client = new MatrixAppserviceClient(appservice); const userId = await client.whoAmI(); if (userId.startsWith("@" + appservice.userPrefix)) return {}; // 200 OK diff --git a/src/api/admin/AdminService.ts b/src/api/admin/AdminService.ts index 661e141..1652358 100644 --- a/src/api/admin/AdminService.ts +++ b/src/api/admin/AdminService.ts @@ -4,6 +4,7 @@ import config from "../../config"; import { ApiError } from "../ApiError"; import { MatrixLiteClient } from "../../matrix/MatrixLiteClient"; import { CURRENT_VERSION } from "../../version"; +import { getFederationUrl } from "../../matrix/helpers"; interface DimensionVersionResponse { version: string; @@ -16,6 +17,7 @@ interface DimensionConfigResponse { name: string; userId: string; federationUrl: string; + clientServerUrl: string; }; } @@ -52,14 +54,15 @@ export class AdminService { public async getConfig(@QueryParam("scalar_token") scalarToken: string): Promise { await AdminService.validateAndGetAdminTokenOwner(scalarToken); - const client = new MatrixLiteClient(config.homeserver.name, config.homeserver.accessToken); + const client = new MatrixLiteClient(config.homeserver.accessToken); return { admins: config.admins, widgetBlacklist: config.widgetBlacklist, homeserver: { name: config.homeserver.name, userId: await client.whoAmI(), - federationUrl: await client.getFederationUrl(), + federationUrl: await getFederationUrl(config.homeserver.name), + clientServerUrl: config.homeserver.clientServerUrl, }, }; } diff --git a/src/api/scalar/ScalarWidgetService.ts b/src/api/scalar/ScalarWidgetService.ts index dfca227..ef3c6d3 100644 --- a/src/api/scalar/ScalarWidgetService.ts +++ b/src/api/scalar/ScalarWidgetService.ts @@ -32,7 +32,7 @@ export class ScalarWidgetService { return cachedResult; } - const client = new MatrixLiteClient(config.homeserver.name, config.homeserver.accessToken); + const client = new MatrixLiteClient(config.homeserver.accessToken); try { const preview = await client.getUrlPreview(url); diff --git a/src/config.ts b/src/config.ts index 7149e0a..cca6074 100644 --- a/src/config.ts +++ b/src/config.ts @@ -9,6 +9,8 @@ export interface DimensionConfig { homeserver: { name: string; accessToken: string; + clientServerUrl: string; + federationUrl: string; }; widgetBlacklist: string[]; database: { diff --git a/src/db/AppserviceStore.ts b/src/db/AppserviceStore.ts index 4ee32e8..c4fe326 100644 --- a/src/db/AppserviceStore.ts +++ b/src/db/AppserviceStore.ts @@ -2,7 +2,6 @@ import AppService from "./models/AppService"; import AppServiceUser from "./models/AppServiceUser"; import * as randomString from "random-string"; import { MatrixAppserviceClient } from "../matrix/MatrixAppserviceClient"; -import config from "../config"; export class AppserviceStore { @@ -49,7 +48,7 @@ export class AppserviceStore { const appservice = await AppService.findOne({where: {id: appserviceId}}); if (!appservice) throw new Error("Appservice not found"); - const client = new MatrixAppserviceClient(config.homeserver.name, appservice); + const client = new MatrixAppserviceClient(appservice); const localpart = AppserviceStore.getSafeUserId(userId.substring(1).split(":")[0]); const response = await client.registerUser(localpart); diff --git a/src/matrix/MatrixAppserviceClient.ts b/src/matrix/MatrixAppserviceClient.ts index 5d3fd2e..cf1aa1e 100644 --- a/src/matrix/MatrixAppserviceClient.ts +++ b/src/matrix/MatrixAppserviceClient.ts @@ -1,4 +1,4 @@ -import { doFederatedApiCall } from "./helpers"; +import { doClientApiCall } from "./helpers"; import AppService from "../db/models/AppService"; export interface MatrixUserResponse { @@ -10,13 +10,12 @@ export interface MatrixUserResponse { export class MatrixAppserviceClient { - constructor(private homeserverName: string, private appservice: AppService) { + constructor(private appservice: AppService) { } public async registerUser(localpart: string): Promise { - return doFederatedApiCall( + return doClientApiCall( "POST", - this.homeserverName, "/_matrix/client/r0/register", {access_token: this.appservice.asToken}, {type: "m.login.application_service", username: localpart}, @@ -24,9 +23,8 @@ export class MatrixAppserviceClient { } public async whoAmI(): Promise { - const response = await doFederatedApiCall( + const response = await doClientApiCall( "GET", - this.homeserverName, "/_matrix/client/r0/account/whoami", {access_token: this.appservice.asToken}, ); diff --git a/src/matrix/MatrixLiteClient.ts b/src/matrix/MatrixLiteClient.ts index 4319bdf..9470914 100644 --- a/src/matrix/MatrixLiteClient.ts +++ b/src/matrix/MatrixLiteClient.ts @@ -1,4 +1,4 @@ -import { doFederatedApiCall, getFederationUrl as getFedUrl } from "./helpers"; +import { doClientApiCall } from "./helpers"; export interface MatrixUrlPreview { // This is really the only parameter we care about @@ -7,26 +7,20 @@ export interface MatrixUrlPreview { export class MatrixLiteClient { - constructor(private homeserverName: string, private accessToken: string) { - } - - public async getFederationUrl(): Promise { - return getFedUrl(this.homeserverName); + constructor(private accessToken: string) { } public async getUrlPreview(url: string): Promise { - return doFederatedApiCall( + return doClientApiCall( "GET", - this.homeserverName, "/_matrix/media/r0/preview_url", {access_token: this.accessToken, url: url} ); } public async whoAmI(): Promise { - const response = await doFederatedApiCall( + const response = await doClientApiCall( "GET", - this.homeserverName, "/_matrix/client/r0/account/whoami", {access_token: this.accessToken} ); diff --git a/src/matrix/MatrixOpenIdClient.ts b/src/matrix/MatrixOpenIdClient.ts index f71e84e..cae3d3e 100644 --- a/src/matrix/MatrixOpenIdClient.ts +++ b/src/matrix/MatrixOpenIdClient.ts @@ -7,6 +7,8 @@ export class MatrixOpenIdClient { } public async getUserId(): Promise { + // TODO: Implement/prefer https://github.com/matrix-org/matrix-doc/issues/1115 + // #1115 also means this should become a client API call, not a federated one (finally) const response = await doFederatedApiCall( "GET", this.openId.matrix_server_name, diff --git a/src/matrix/helpers.ts b/src/matrix/helpers.ts index 81911fe..8a5fe4c 100644 --- a/src/matrix/helpers.ts +++ b/src/matrix/helpers.ts @@ -2,6 +2,7 @@ import * as dns from "dns-then"; import { LogService } from "matrix-js-snippets"; import { Cache, CACHE_FEDERATION } from "../MemoryCache"; import * as request from "request"; +import config from "../config"; export async function getFederationUrl(serverName: string): Promise { const cachedUrl = Cache.for(CACHE_FEDERATION).get(serverName); @@ -10,6 +11,17 @@ export async function getFederationUrl(serverName: string): Promise { return cachedUrl; } + if (serverName === config.homeserver.name && config.homeserver.federationUrl) { + let url = config.homeserver.federationUrl; + if (url.endsWith("/")) { + url = url.substring(0, url.length - 1); + } + + LogService.info("matrix", "Using configured federation URL for " + serverName); + Cache.for(CACHE_FEDERATION).put(serverName, url); + return url; + } + let serverUrl = null; let expirationMs = 4 * 60 * 60 * 1000; // default is 4 hours @@ -49,7 +61,33 @@ export async function doFederatedApiCall(method: string, serverName: string, end LogService.error("matrix", err); reject(err); } else if (res.statusCode !== 200) { - LogService.error("matrix", "Got status code " + res.statusCode + " while calling " + endpoint); + LogService.error("matrix", "Got status code " + res.statusCode + " while calling federated endpoint " + endpoint); + reject(new Error("Error in request: invalid status code")); + } else { + if (typeof(res.body) === "string") res.body = JSON.parse(res.body); + resolve(res.body); + } + }); + }); +} + +export async function doClientApiCall(method: string, endpoint: string, query?: object, body?: object): Promise { + let url = config.homeserver.clientServerUrl; + if (url.endsWith("/")) url = url.substring(0, url.length - 1); + + return new Promise((resolve, reject) => { + request({ + method: method, + url: url + endpoint, + qs: query, + json: body, + }, (err, res, _body) => { + if (err) { + LogService.error("matrix", "Error calling " + endpoint); + LogService.error("matrix", err); + reject(err); + } else if (res.statusCode !== 200) { + LogService.error("matrix", "Got status code " + res.statusCode + " while calling client endpoint " + endpoint); reject(new Error("Error in request: invalid status code")); } else { if (typeof(res.body) === "string") res.body = JSON.parse(res.body); diff --git a/src/neb/NebClient.ts b/src/neb/NebClient.ts index 6a606ba..634af7f 100644 --- a/src/neb/NebClient.ts +++ b/src/neb/NebClient.ts @@ -2,7 +2,6 @@ import { NebConfig } from "../models/neb"; import { AppserviceStore } from "../db/AppserviceStore"; import { Client } from "./models/client"; import config from "../config"; -import { getFederationUrl } from "../matrix/helpers"; import { LogService } from "matrix-js-snippets"; import { Service } from "./models/service"; import * as request from "request"; @@ -19,7 +18,7 @@ export class NebClient { public async updateUser(userId: string, isEnabled: boolean, sync = true, autoAcceptInvites = true): Promise { const nebRequest: Client = { UserID: userId, - HomeserverURL: await getFederationUrl(config.homeserver.name), + HomeserverURL: config.homeserver.clientServerUrl, AccessToken: (isEnabled ? await this.getAccessToken(userId) : "DISABLED"), Sync: isEnabled ? sync : false, AutoJoinRooms: autoAcceptInvites diff --git a/web/app/admin/home/home.component.html b/web/app/admin/home/home.component.html index 98c9a8a..6d035ff 100644 --- a/web/app/admin/home/home.component.html +++ b/web/app/admin/home/home.component.html @@ -23,9 +23,8 @@ Homeserver
Name: {{ config.homeserver.name }}
Federation URL: {{ config.homeserver.federationUrl }}
- - Client/Server URL: {{ config.homeserver.federationUrl }}
- User ID: {{ config.homeserver.userId }} + Client/Server URL: {{ config.homeserver.clientServerUrl }}
+ Utility User ID: {{ config.homeserver.userId }} diff --git a/web/app/shared/models/admin_responses.ts b/web/app/shared/models/admin_responses.ts index 134ae51..dc7f93f 100644 --- a/web/app/shared/models/admin_responses.ts +++ b/web/app/shared/models/admin_responses.ts @@ -7,6 +7,7 @@ export interface FE_DimensionConfig { name: string; userId: string; federationUrl: string; + clientServerUrl: string; }; }