mirror of
https://github.com/Novaloop-AG/healthchat-web.git
synced 2026-10-31 08:15:07 +00:00
feat(permalinks): point Share links/QR at to.healthchat.ch
Add a config-driven matrix_to_url option so Share dialog links and QR codes resolve against a matrix.to-compatible resolver instead of the hardcoded public matrix.to. MatrixToPermalinkConstructor now reads the base URL lazily from config (default https://matrix.to), keeping the matrix.to URL format. HealthChat configs point it at the in-house fork https://to.healthchat.ch and drop the conflicting permalink_prefix (which routes to the Element-format constructor a matrix.to fork can't parse).
This commit is contained in:
@@ -33,7 +33,7 @@
|
||||
"preferred_domain": "jitsi.healthchat.ch"
|
||||
},
|
||||
"logout_redirect_url": "",
|
||||
"permalink_prefix": "https://matrix.to",
|
||||
"matrix_to_url": "https://to.healthchat.ch",
|
||||
"room_directory": {
|
||||
"servers": ["matrix.org"]
|
||||
},
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
"preferred_domain": "jitsi.healthchat.ch"
|
||||
},
|
||||
"logout_redirect_url": "",
|
||||
"permalink_prefix": "https://matrix.to",
|
||||
"matrix_to_url": "https://to.healthchat.ch",
|
||||
"room_directory": {
|
||||
"servers": [
|
||||
"matrix.org"
|
||||
|
||||
@@ -70,6 +70,12 @@ export interface IConfigOptions {
|
||||
};
|
||||
|
||||
permalink_prefix?: string;
|
||||
/**
|
||||
* Base URL of a matrix.to-compatible resolver to use for Share links and QR codes,
|
||||
* instead of the public `https://matrix.to`. Must use the matrix.to URL format
|
||||
* (`/#/<entity>`), e.g. a self-hosted matrix.to fork.
|
||||
*/
|
||||
matrix_to_url?: string;
|
||||
|
||||
update_base_url?: string;
|
||||
desktop_builds: {
|
||||
|
||||
@@ -7,10 +7,27 @@ Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import PermalinkConstructor, { PermalinkParts } from "./PermalinkConstructor";
|
||||
import SdkConfig from "../../SdkConfig";
|
||||
|
||||
export const host = "matrix.to";
|
||||
export const baseUrl = `https://${host}`;
|
||||
export const baseUrlPattern = `^(?:https?://)?${host.replace(".", "\\.")}/#/(.*)`;
|
||||
const DEFAULT_BASE_URL = "https://matrix.to";
|
||||
|
||||
/**
|
||||
* The base URL of the matrix.to-compatible resolver to generate permalinks against.
|
||||
* Defaults to the public `https://matrix.to`, but can be pointed at a self-hosted
|
||||
* matrix.to fork via the `matrix_to_url` config option. Read lazily so the value
|
||||
* reflects the runtime config rather than module-load time.
|
||||
*/
|
||||
export function baseUrl(): string {
|
||||
return SdkConfig.get("matrix_to_url") ?? DEFAULT_BASE_URL;
|
||||
}
|
||||
|
||||
export function host(): string {
|
||||
return new URL(baseUrl()).host;
|
||||
}
|
||||
|
||||
export function baseUrlPattern(): string {
|
||||
return `^(?:https?://)?${host().replaceAll(".", "\\.")}/#/(.*)`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates matrix.to permalinks
|
||||
@@ -21,23 +38,23 @@ export default class MatrixToPermalinkConstructor extends PermalinkConstructor {
|
||||
}
|
||||
|
||||
public forEvent(roomId: string, eventId: string, serverCandidates: string[]): string {
|
||||
return `${baseUrl}/#/${roomId}/${eventId}${this.encodeServerCandidates(serverCandidates)}`;
|
||||
return `${baseUrl()}/#/${roomId}/${eventId}${this.encodeServerCandidates(serverCandidates)}`;
|
||||
}
|
||||
|
||||
public forRoom(roomIdOrAlias: string, serverCandidates: string[]): string {
|
||||
return `${baseUrl}/#/${roomIdOrAlias}${this.encodeServerCandidates(serverCandidates)}`;
|
||||
return `${baseUrl()}/#/${roomIdOrAlias}${this.encodeServerCandidates(serverCandidates)}`;
|
||||
}
|
||||
|
||||
public forUser(userId: string): string {
|
||||
return `${baseUrl}/#/${userId}`;
|
||||
return `${baseUrl()}/#/${userId}`;
|
||||
}
|
||||
|
||||
public forEntity(entityId: string): string {
|
||||
return `${baseUrl}/#/${entityId}`;
|
||||
return `${baseUrl()}/#/${entityId}`;
|
||||
}
|
||||
|
||||
public isPermalinkHost(testHost: string): boolean {
|
||||
return testHost === host;
|
||||
return testHost === host();
|
||||
}
|
||||
|
||||
public encodeServerCandidates(candidates: string[]): string {
|
||||
@@ -52,7 +69,7 @@ export default class MatrixToPermalinkConstructor extends PermalinkConstructor {
|
||||
throw new Error("Does not appear to be a permalink");
|
||||
}
|
||||
|
||||
const matches = [...fullUrl.matchAll(new RegExp(baseUrlPattern, "gi"))][0];
|
||||
const matches = [...fullUrl.matchAll(new RegExp(baseUrlPattern(), "gi"))][0];
|
||||
|
||||
if (!matches || matches.length < 2) {
|
||||
throw new Error("Does not appear to be a permalink");
|
||||
|
||||
@@ -16,6 +16,7 @@ import MatrixToPermalinkConstructor, {
|
||||
baseUrl as matrixtoBaseUrl,
|
||||
baseUrlPattern as matrixToBaseUrlPattern,
|
||||
} from "./MatrixToPermalinkConstructor";
|
||||
// `matrixtoBaseUrl` and `matrixToBaseUrlPattern` are functions (config-driven); call them at use sites.
|
||||
import { type PermalinkParts } from "./PermalinkConstructor";
|
||||
import type PermalinkConstructor from "./PermalinkConstructor";
|
||||
import ElementPermalinkConstructor from "./ElementPermalinkConstructor";
|
||||
@@ -342,13 +343,13 @@ export function tryTransformEntityToPermalink(matrixClient: MatrixClient, entity
|
||||
if (permalinkParts) {
|
||||
if (permalinkParts.roomIdOrAlias) {
|
||||
const eventIdPart = permalinkParts.eventId ? `/${permalinkParts.eventId}` : "";
|
||||
let pl = matrixtoBaseUrl + `/#/${permalinkParts.roomIdOrAlias}${eventIdPart}`;
|
||||
let pl = matrixtoBaseUrl() + `/#/${permalinkParts.roomIdOrAlias}${eventIdPart}`;
|
||||
if (permalinkParts.viaServers?.length) {
|
||||
pl += new MatrixToPermalinkConstructor().encodeServerCandidates(permalinkParts.viaServers);
|
||||
}
|
||||
return pl;
|
||||
} else if (permalinkParts.userId) {
|
||||
return matrixtoBaseUrl + `/#/${permalinkParts.userId}`;
|
||||
return matrixtoBaseUrl() + `/#/${permalinkParts.userId}`;
|
||||
}
|
||||
}
|
||||
} catch {}
|
||||
@@ -437,7 +438,7 @@ export function getPrimaryPermalinkEntity(permalink: string): string | null {
|
||||
*/
|
||||
function getPermalinkConstructor(isPill = false): PermalinkConstructor {
|
||||
const elementPrefix = SdkConfig.get("permalink_prefix");
|
||||
if (elementPrefix && elementPrefix !== matrixtoBaseUrl && !isPill) {
|
||||
if (elementPrefix && elementPrefix !== matrixtoBaseUrl() && !isPill) {
|
||||
return new ElementPermalinkConstructor(elementPrefix);
|
||||
}
|
||||
|
||||
@@ -448,7 +449,7 @@ export function parsePermalink(fullUrl: string): PermalinkParts | null {
|
||||
try {
|
||||
const elementPrefix = SdkConfig.get("permalink_prefix");
|
||||
const decodedUrl = decodeURIComponent(fullUrl);
|
||||
if (new RegExp(matrixToBaseUrlPattern, "i").test(decodedUrl)) {
|
||||
if (new RegExp(matrixToBaseUrlPattern(), "i").test(decodedUrl)) {
|
||||
return new MatrixToPermalinkConstructor().parsePermalink(decodedUrl);
|
||||
} else if (fullUrl.startsWith("matrix:")) {
|
||||
return new MatrixSchemePermalinkConstructor().parsePermalink(fullUrl);
|
||||
|
||||
@@ -8,6 +8,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import MatrixToPermalinkConstructor from "../../../../src/utils/permalinks/MatrixToPermalinkConstructor";
|
||||
import { PermalinkParts } from "../../../../src/utils/permalinks/PermalinkConstructor";
|
||||
import SdkConfig from "../../../../src/SdkConfig";
|
||||
|
||||
describe("MatrixToPermalinkConstructor", () => {
|
||||
const peramlinkConstructor = new MatrixToPermalinkConstructor();
|
||||
@@ -49,4 +50,32 @@ describe("MatrixToPermalinkConstructor", () => {
|
||||
).toEqual("https://matrix.to/#/!myroom:example.com/$event4?via=one.example.com&via=two.example.com");
|
||||
});
|
||||
});
|
||||
|
||||
describe("with a custom matrix_to_url config", () => {
|
||||
beforeEach(() => {
|
||||
SdkConfig.add({ matrix_to_url: "https://to.healthchat.ch" });
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
SdkConfig.reset();
|
||||
});
|
||||
|
||||
it("generates links against the configured host", () => {
|
||||
const constructor = new MatrixToPermalinkConstructor();
|
||||
expect(constructor.forUser("@user:example.com")).toEqual("https://to.healthchat.ch/#/@user:example.com");
|
||||
expect(constructor.forRoom("!myroom:example.com", [])).toEqual(
|
||||
"https://to.healthchat.ch/#/!myroom:example.com",
|
||||
);
|
||||
});
|
||||
|
||||
it("parses links from the configured host and rejects matrix.to links", () => {
|
||||
const constructor = new MatrixToPermalinkConstructor();
|
||||
expect(constructor.parsePermalink("https://to.healthchat.ch/#/@user:example.com")).toEqual(
|
||||
new PermalinkParts(null, null, "@user:example.com", null),
|
||||
);
|
||||
expect(() => constructor.parsePermalink("https://matrix.to/#/@user:example.com")).toThrow(
|
||||
new Error("Does not appear to be a permalink"),
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user