mirror of
https://github.com/turt2live/matrix-dimension.git
synced 2024-10-01 01:05:53 -04:00
Support explicit setting of the federation/client URLs
The client/server URL is needed for go-neb to work correctly, and to remove our complete dependence on federation. The federation URL is also configurable so servers that don't wish to federate can specify a local address.
This commit is contained in:
parent
cc921779ae
commit
8cdae3359d
@ -3,9 +3,23 @@ web:
|
|||||||
port: 8184
|
port: 8184
|
||||||
address: '0.0.0.0'
|
address: '0.0.0.0'
|
||||||
|
|
||||||
# Homeserver configuration (used to proxy some requests to the homeserver for processing)
|
# Homeserver configuration
|
||||||
homeserver:
|
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"
|
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"
|
accessToken: "something"
|
||||||
|
|
||||||
# These users can modify the integrations this Dimension supports.
|
# 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.
|
# 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.
|
# Note: Widgets may still be embedded with restricted content, although not through Dimension directly.
|
||||||
widgetBlacklist:
|
widgetBlacklist:
|
||||||
- 10.0.0.0/8
|
- 10.0.0.0/8
|
||||||
- 172.16.0.0/12
|
- 172.16.0.0/12
|
||||||
- 192.168.0.0/16
|
- 192.168.0.0/16
|
||||||
- 127.0.0.0/8
|
- 127.0.0.0/8
|
||||||
|
|
||||||
# Where the database for Dimension is
|
# Where the database for Dimension is
|
||||||
database:
|
database:
|
||||||
|
@ -4,7 +4,6 @@ import AppService from "../../db/models/AppService";
|
|||||||
import { AppserviceStore } from "../../db/AppserviceStore";
|
import { AppserviceStore } from "../../db/AppserviceStore";
|
||||||
import { ApiError } from "../ApiError";
|
import { ApiError } from "../ApiError";
|
||||||
import { MatrixAppserviceClient } from "../../matrix/MatrixAppserviceClient";
|
import { MatrixAppserviceClient } from "../../matrix/MatrixAppserviceClient";
|
||||||
import config from "../../config";
|
|
||||||
import { LogService } from "matrix-js-snippets";
|
import { LogService } from "matrix-js-snippets";
|
||||||
|
|
||||||
interface AppserviceResponse {
|
interface AppserviceResponse {
|
||||||
@ -67,7 +66,7 @@ export class AdminAppserviceService {
|
|||||||
await AdminService.validateAndGetAdminTokenOwner(scalarToken);
|
await AdminService.validateAndGetAdminTokenOwner(scalarToken);
|
||||||
|
|
||||||
const appservice = await AppserviceStore.getAppservice(asId);
|
const appservice = await AppserviceStore.getAppservice(asId);
|
||||||
const client = new MatrixAppserviceClient(config.homeserver.name, appservice);
|
const client = new MatrixAppserviceClient(appservice);
|
||||||
const userId = await client.whoAmI();
|
const userId = await client.whoAmI();
|
||||||
|
|
||||||
if (userId.startsWith("@" + appservice.userPrefix)) return {}; // 200 OK
|
if (userId.startsWith("@" + appservice.userPrefix)) return {}; // 200 OK
|
||||||
|
@ -4,6 +4,7 @@ import config from "../../config";
|
|||||||
import { ApiError } from "../ApiError";
|
import { ApiError } from "../ApiError";
|
||||||
import { MatrixLiteClient } from "../../matrix/MatrixLiteClient";
|
import { MatrixLiteClient } from "../../matrix/MatrixLiteClient";
|
||||||
import { CURRENT_VERSION } from "../../version";
|
import { CURRENT_VERSION } from "../../version";
|
||||||
|
import { getFederationUrl } from "../../matrix/helpers";
|
||||||
|
|
||||||
interface DimensionVersionResponse {
|
interface DimensionVersionResponse {
|
||||||
version: string;
|
version: string;
|
||||||
@ -16,6 +17,7 @@ interface DimensionConfigResponse {
|
|||||||
name: string;
|
name: string;
|
||||||
userId: string;
|
userId: string;
|
||||||
federationUrl: string;
|
federationUrl: string;
|
||||||
|
clientServerUrl: string;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,14 +54,15 @@ export class AdminService {
|
|||||||
public async getConfig(@QueryParam("scalar_token") scalarToken: string): Promise<DimensionConfigResponse> {
|
public async getConfig(@QueryParam("scalar_token") scalarToken: string): Promise<DimensionConfigResponse> {
|
||||||
await AdminService.validateAndGetAdminTokenOwner(scalarToken);
|
await AdminService.validateAndGetAdminTokenOwner(scalarToken);
|
||||||
|
|
||||||
const client = new MatrixLiteClient(config.homeserver.name, config.homeserver.accessToken);
|
const client = new MatrixLiteClient(config.homeserver.accessToken);
|
||||||
return {
|
return {
|
||||||
admins: config.admins,
|
admins: config.admins,
|
||||||
widgetBlacklist: config.widgetBlacklist,
|
widgetBlacklist: config.widgetBlacklist,
|
||||||
homeserver: {
|
homeserver: {
|
||||||
name: config.homeserver.name,
|
name: config.homeserver.name,
|
||||||
userId: await client.whoAmI(),
|
userId: await client.whoAmI(),
|
||||||
federationUrl: await client.getFederationUrl(),
|
federationUrl: await getFederationUrl(config.homeserver.name),
|
||||||
|
clientServerUrl: config.homeserver.clientServerUrl,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ export class ScalarWidgetService {
|
|||||||
return cachedResult;
|
return cachedResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
const client = new MatrixLiteClient(config.homeserver.name, config.homeserver.accessToken);
|
const client = new MatrixLiteClient(config.homeserver.accessToken);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const preview = await client.getUrlPreview(url);
|
const preview = await client.getUrlPreview(url);
|
||||||
|
@ -9,6 +9,8 @@ export interface DimensionConfig {
|
|||||||
homeserver: {
|
homeserver: {
|
||||||
name: string;
|
name: string;
|
||||||
accessToken: string;
|
accessToken: string;
|
||||||
|
clientServerUrl: string;
|
||||||
|
federationUrl: string;
|
||||||
};
|
};
|
||||||
widgetBlacklist: string[];
|
widgetBlacklist: string[];
|
||||||
database: {
|
database: {
|
||||||
|
@ -2,7 +2,6 @@ import AppService from "./models/AppService";
|
|||||||
import AppServiceUser from "./models/AppServiceUser";
|
import AppServiceUser from "./models/AppServiceUser";
|
||||||
import * as randomString from "random-string";
|
import * as randomString from "random-string";
|
||||||
import { MatrixAppserviceClient } from "../matrix/MatrixAppserviceClient";
|
import { MatrixAppserviceClient } from "../matrix/MatrixAppserviceClient";
|
||||||
import config from "../config";
|
|
||||||
|
|
||||||
export class AppserviceStore {
|
export class AppserviceStore {
|
||||||
|
|
||||||
@ -49,7 +48,7 @@ export class AppserviceStore {
|
|||||||
const appservice = await AppService.findOne({where: {id: appserviceId}});
|
const appservice = await AppService.findOne({where: {id: appserviceId}});
|
||||||
if (!appservice) throw new Error("Appservice not found");
|
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 localpart = AppserviceStore.getSafeUserId(userId.substring(1).split(":")[0]);
|
||||||
const response = await client.registerUser(localpart);
|
const response = await client.registerUser(localpart);
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { doFederatedApiCall } from "./helpers";
|
import { doClientApiCall } from "./helpers";
|
||||||
import AppService from "../db/models/AppService";
|
import AppService from "../db/models/AppService";
|
||||||
|
|
||||||
export interface MatrixUserResponse {
|
export interface MatrixUserResponse {
|
||||||
@ -10,13 +10,12 @@ export interface MatrixUserResponse {
|
|||||||
|
|
||||||
export class MatrixAppserviceClient {
|
export class MatrixAppserviceClient {
|
||||||
|
|
||||||
constructor(private homeserverName: string, private appservice: AppService) {
|
constructor(private appservice: AppService) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async registerUser(localpart: string): Promise<MatrixUserResponse> {
|
public async registerUser(localpart: string): Promise<MatrixUserResponse> {
|
||||||
return doFederatedApiCall(
|
return doClientApiCall(
|
||||||
"POST",
|
"POST",
|
||||||
this.homeserverName,
|
|
||||||
"/_matrix/client/r0/register",
|
"/_matrix/client/r0/register",
|
||||||
{access_token: this.appservice.asToken},
|
{access_token: this.appservice.asToken},
|
||||||
{type: "m.login.application_service", username: localpart},
|
{type: "m.login.application_service", username: localpart},
|
||||||
@ -24,9 +23,8 @@ export class MatrixAppserviceClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async whoAmI(): Promise<string> {
|
public async whoAmI(): Promise<string> {
|
||||||
const response = await doFederatedApiCall(
|
const response = await doClientApiCall(
|
||||||
"GET",
|
"GET",
|
||||||
this.homeserverName,
|
|
||||||
"/_matrix/client/r0/account/whoami",
|
"/_matrix/client/r0/account/whoami",
|
||||||
{access_token: this.appservice.asToken},
|
{access_token: this.appservice.asToken},
|
||||||
);
|
);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { doFederatedApiCall, getFederationUrl as getFedUrl } from "./helpers";
|
import { doClientApiCall } from "./helpers";
|
||||||
|
|
||||||
export interface MatrixUrlPreview {
|
export interface MatrixUrlPreview {
|
||||||
// This is really the only parameter we care about
|
// This is really the only parameter we care about
|
||||||
@ -7,26 +7,20 @@ export interface MatrixUrlPreview {
|
|||||||
|
|
||||||
export class MatrixLiteClient {
|
export class MatrixLiteClient {
|
||||||
|
|
||||||
constructor(private homeserverName: string, private accessToken: string) {
|
constructor(private accessToken: string) {
|
||||||
}
|
|
||||||
|
|
||||||
public async getFederationUrl(): Promise<string> {
|
|
||||||
return getFedUrl(this.homeserverName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getUrlPreview(url: string): Promise<MatrixUrlPreview> {
|
public async getUrlPreview(url: string): Promise<MatrixUrlPreview> {
|
||||||
return doFederatedApiCall(
|
return doClientApiCall(
|
||||||
"GET",
|
"GET",
|
||||||
this.homeserverName,
|
|
||||||
"/_matrix/media/r0/preview_url",
|
"/_matrix/media/r0/preview_url",
|
||||||
{access_token: this.accessToken, url: url}
|
{access_token: this.accessToken, url: url}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async whoAmI(): Promise<string> {
|
public async whoAmI(): Promise<string> {
|
||||||
const response = await doFederatedApiCall(
|
const response = await doClientApiCall(
|
||||||
"GET",
|
"GET",
|
||||||
this.homeserverName,
|
|
||||||
"/_matrix/client/r0/account/whoami",
|
"/_matrix/client/r0/account/whoami",
|
||||||
{access_token: this.accessToken}
|
{access_token: this.accessToken}
|
||||||
);
|
);
|
||||||
|
@ -7,6 +7,8 @@ export class MatrixOpenIdClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async getUserId(): Promise<string> {
|
public async getUserId(): Promise<string> {
|
||||||
|
// 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(
|
const response = await doFederatedApiCall(
|
||||||
"GET",
|
"GET",
|
||||||
this.openId.matrix_server_name,
|
this.openId.matrix_server_name,
|
||||||
|
@ -2,6 +2,7 @@ import * as dns from "dns-then";
|
|||||||
import { LogService } from "matrix-js-snippets";
|
import { LogService } from "matrix-js-snippets";
|
||||||
import { Cache, CACHE_FEDERATION } from "../MemoryCache";
|
import { Cache, CACHE_FEDERATION } from "../MemoryCache";
|
||||||
import * as request from "request";
|
import * as request from "request";
|
||||||
|
import config from "../config";
|
||||||
|
|
||||||
export async function getFederationUrl(serverName: string): Promise<string> {
|
export async function getFederationUrl(serverName: string): Promise<string> {
|
||||||
const cachedUrl = Cache.for(CACHE_FEDERATION).get(serverName);
|
const cachedUrl = Cache.for(CACHE_FEDERATION).get(serverName);
|
||||||
@ -10,6 +11,17 @@ export async function getFederationUrl(serverName: string): Promise<string> {
|
|||||||
return cachedUrl;
|
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 serverUrl = null;
|
||||||
let expirationMs = 4 * 60 * 60 * 1000; // default is 4 hours
|
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);
|
LogService.error("matrix", err);
|
||||||
reject(err);
|
reject(err);
|
||||||
} else if (res.statusCode !== 200) {
|
} 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<any> {
|
||||||
|
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"));
|
reject(new Error("Error in request: invalid status code"));
|
||||||
} else {
|
} else {
|
||||||
if (typeof(res.body) === "string") res.body = JSON.parse(res.body);
|
if (typeof(res.body) === "string") res.body = JSON.parse(res.body);
|
||||||
|
@ -2,7 +2,6 @@ import { NebConfig } from "../models/neb";
|
|||||||
import { AppserviceStore } from "../db/AppserviceStore";
|
import { AppserviceStore } from "../db/AppserviceStore";
|
||||||
import { Client } from "./models/client";
|
import { Client } from "./models/client";
|
||||||
import config from "../config";
|
import config from "../config";
|
||||||
import { getFederationUrl } from "../matrix/helpers";
|
|
||||||
import { LogService } from "matrix-js-snippets";
|
import { LogService } from "matrix-js-snippets";
|
||||||
import { Service } from "./models/service";
|
import { Service } from "./models/service";
|
||||||
import * as request from "request";
|
import * as request from "request";
|
||||||
@ -19,7 +18,7 @@ export class NebClient {
|
|||||||
public async updateUser(userId: string, isEnabled: boolean, sync = true, autoAcceptInvites = true): Promise<any> {
|
public async updateUser(userId: string, isEnabled: boolean, sync = true, autoAcceptInvites = true): Promise<any> {
|
||||||
const nebRequest: Client = {
|
const nebRequest: Client = {
|
||||||
UserID: userId,
|
UserID: userId,
|
||||||
HomeserverURL: await getFederationUrl(config.homeserver.name),
|
HomeserverURL: config.homeserver.clientServerUrl,
|
||||||
AccessToken: (isEnabled ? await this.getAccessToken(userId) : "DISABLED"),
|
AccessToken: (isEnabled ? await this.getAccessToken(userId) : "DISABLED"),
|
||||||
Sync: isEnabled ? sync : false,
|
Sync: isEnabled ? sync : false,
|
||||||
AutoJoinRooms: autoAcceptInvites
|
AutoJoinRooms: autoAcceptInvites
|
||||||
|
@ -23,9 +23,8 @@
|
|||||||
<strong>Homeserver</strong><br />
|
<strong>Homeserver</strong><br />
|
||||||
Name: {{ config.homeserver.name }}<br />
|
Name: {{ config.homeserver.name }}<br />
|
||||||
Federation URL: {{ config.homeserver.federationUrl }}<br />
|
Federation URL: {{ config.homeserver.federationUrl }}<br />
|
||||||
<!-- Dimension makes no distinction for the csapi -->
|
Client/Server URL: {{ config.homeserver.clientServerUrl }}<br />
|
||||||
Client/Server URL: {{ config.homeserver.federationUrl }}<br />
|
Utility User ID: {{ config.homeserver.userId }}
|
||||||
User ID: {{ config.homeserver.userId }}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -7,6 +7,7 @@ export interface FE_DimensionConfig {
|
|||||||
name: string;
|
name: string;
|
||||||
userId: string;
|
userId: string;
|
||||||
federationUrl: string;
|
federationUrl: string;
|
||||||
|
clientServerUrl: string;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user