Move spec permalinks into their own class

This allows for Riot permalinks to be introduced without if-else ladders everywhere.
pull/21833/head
Travis Ralston 2019-09-30 12:51:17 -06:00
parent f9d5e89017
commit 926e1146f9
4 changed files with 93 additions and 31 deletions

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import {baseUrl} from "./utils/permalinks/SpecPermalinks";
import {baseUrl} from "./utils/permalinks/SpecPermalinkConstructor";
function matrixLinkify(linkify) {
// Text tokens

View File

@ -14,15 +14,24 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
export const host = "matrix.to";
export const baseUrl = `https://${host}`;
/**
* Generates matrix.to permalinks
* Interface for classes that actually produce permalinks (strings).
* TODO: Convert this to a real TypeScript interface
*/
export default class SpecPermalinks {
constructor() {
export default class PermalinkConstructor {
forEvent(roomId: string, eventId: string, serverCandidates: string[]): string {
throw new Error("Not implemented");
}
// TODO: The class
forRoom(roomIdOrAlias: string, serverCandidates: string[]): string {
throw new Error("Not implemented");
}
forGroup(groupId: string): string {
throw new Error("Not implemented");
}
forUser(userId: string): string {
throw new Error("Not implemented");
}
}

View File

@ -17,7 +17,13 @@ limitations under the License.
import MatrixClientPeg from "../../MatrixClientPeg";
import isIp from "is-ip";
import utils from 'matrix-js-sdk/lib/utils';
import {host as matrixtoHost, baseUrl as matrixtoBaseUrl} from "SpecPermalinks";
import SpecPermalinkConstructor, {
baseUrl as matrixtoBaseUrl,
host as matrixtoHost
} from "./SpecPermalinkConstructor";
import PermalinkConstructor from "./PermalinkConstructor";
const SdkConfig = require("../../SdkConfig");
// The maximum number of servers to pick when working out which servers
// to add to permalinks. The servers are appended as ?via=example.org
@ -71,7 +77,7 @@ export class RoomPermalinkCreator {
// We support being given a roomId as a fallback in the event the `room` object
// doesn't exist or is not healthy for us to rely on. For example, loading a
// permalink to a room which the MatrixClient doesn't know about.
constructor(room, roomId=null) {
constructor(room, roomId = null) {
this._room = room;
this._roomId = room ? room.roomId : roomId;
this._highestPlUserId = null;
@ -126,15 +132,11 @@ export class RoomPermalinkCreator {
}
forEvent(eventId) {
const roomId = this._roomId;
const permalinkBase = `${matrixtoBaseUrl}/#/${roomId}/${eventId}`;
return `${permalinkBase}${encodeServerCandidates(this._serverCandidates)}`;
return getPermalinkConstructor().forEvent(this._roomId, eventId, this._serverCandidates);
}
forRoom() {
const roomId = this._roomId;
const permalinkBase = `${matrixtoBaseUrl}/#/${roomId}`;
return `${permalinkBase}${encodeServerCandidates(this._serverCandidates)}`;
return getPermalinkConstructor().forRoom(this._roomId, this._serverCandidates);
}
onRoomState(event) {
@ -184,8 +186,8 @@ export class RoomPermalinkCreator {
}
const serverName = getServerName(userId);
return !isHostnameIpAddress(serverName) &&
!isHostInRegex(serverName, this._bannedHostsRegexps) &&
isHostInRegex(serverName, this._allowedHostsRegexps);
!isHostInRegex(serverName, this._bannedHostsRegexps) &&
isHostInRegex(serverName, this._allowedHostsRegexps);
});
const maxEntry = allowedEntries.reduce((max, entry) => {
return (entry[1] > max[1]) ? entry : max;
@ -223,7 +225,7 @@ export class RoomPermalinkCreator {
}
_updatePopulationMap() {
const populationMap: {[server:string]:number} = {};
const populationMap: { [server: string]: number } = {};
for (const member of this._room.getJoinedMembers()) {
const serverName = getServerName(member.userId);
if (!populationMap[serverName]) {
@ -244,9 +246,9 @@ export class RoomPermalinkCreator {
.sort((a, b) => this._populationMap[b] - this._populationMap[a])
.filter(a => {
return !candidates.includes(a) &&
!isHostnameIpAddress(a) &&
!isHostInRegex(a, this._bannedHostsRegexps) &&
isHostInRegex(a, this._allowedHostsRegexps);
!isHostnameIpAddress(a) &&
!isHostInRegex(a, this._bannedHostsRegexps) &&
isHostInRegex(a, this._allowedHostsRegexps);
});
const remainingServers = serversByPopulation.slice(0, MAX_SERVER_CANDIDATES - candidates.length);
@ -257,24 +259,22 @@ export class RoomPermalinkCreator {
}
export function makeUserPermalink(userId) {
return `${matrixtoBaseUrl}/#/${userId}`;
return getPermalinkConstructor().forUser(userId);
}
export function makeRoomPermalink(roomId) {
const permalinkBase = `${matrixtoBaseUrl}/#/${roomId}`;
if (!roomId) {
throw new Error("can't permalink a falsey roomId");
}
// If the roomId isn't actually a room ID, don't try to list the servers.
// Aliases are already routable, and don't need extra information.
if (roomId[0] !== '!') return permalinkBase;
if (roomId[0] !== '!') return getPermalinkConstructor().forRoom(roomId, []);
const client = MatrixClientPeg.get();
const room = client.getRoom(roomId);
if (!room) {
return permalinkBase;
return getPermalinkConstructor().forRoom(roomId, []);
}
const permalinkCreator = new RoomPermalinkCreator(room);
permalinkCreator.load();
@ -282,12 +282,15 @@ export function makeRoomPermalink(roomId) {
}
export function makeGroupPermalink(groupId) {
return `${matrixtoBaseUrl}/#/${groupId}`;
return getPermalinkConstructor().forGroup(groupId);
}
export function encodeServerCandidates(candidates) {
if (!candidates || candidates.length === 0) return '';
return `?via=${candidates.map(c => encodeURIComponent(c)).join("&via=")}`;
function getPermalinkConstructor(): PermalinkConstructor {
if (SdkConfig.get()['useRiotToCreatePermalinks']) {
// TODO: Return a RiotPermalinkConstructor
}
return new SpecPermalinkConstructor();
}
function getServerName(userId) {

View File

@ -0,0 +1,50 @@
/*
Copyright 2019 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import PermalinkConstructor from "./PermalinkConstructor";
export const host = "matrix.to";
export const baseUrl = `https://${host}`;
/**
* Generates matrix.to permalinks
*/
export default class SpecPermalinkConstructor extends PermalinkConstructor {
constructor() {
super();
}
forEvent(roomId: string, eventId: string, serverCandidates: string[]): string {
return `${baseUrl}/#/${roomId}/${eventId}${this.encodeServerCandidates(serverCandidates)}`;
}
forRoom(roomIdOrAlias: string, serverCandidates: string[]): string {
return `${baseUrl}/#/${roomIdOrAlias}${this.encodeServerCandidates(serverCandidates)}`;
}
forUser(userId: string): string {
return `${baseUrl}/#/${userId}`;
}
forGroup(groupId: string): string {
return `${baseUrl}/#/${groupId}`;
}
encodeServerCandidates(candidates: string[]) {
if (!candidates || candidates.length === 0) return '';
return `?via=${candidates.map(c => encodeURIComponent(c)).join("&via=")}`;
}
}