mirror of
https://github.com/matrix-org/mjolnir.git
synced 2024-09-29 20:56:23 +00:00
Tidy up documentation and test utils
This commit is contained in:
parent
a86afd3cc8
commit
0a6b122f5c
@ -41,7 +41,7 @@ if (config.health.healthz.enabled) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
(async function () {
|
(async function () {
|
||||||
const storagePath = path.isAbsolute(config.dataPath) ? config.dataPath : path.join(__dirname, '../', config.dataPath)
|
const storagePath = path.isAbsolute(config.dataPath) ? config.dataPath : path.join(__dirname, '../', config.dataPath);
|
||||||
const storage = new SimpleFsStorageProvider(path.join(storagePath, "bot.json"));
|
const storage = new SimpleFsStorageProvider(path.join(storagePath, "bot.json"));
|
||||||
|
|
||||||
let client: MatrixClient;
|
let client: MatrixClient;
|
||||||
|
@ -23,14 +23,14 @@ import { Mjolnir } from "./Mjolnir";
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a listener to the client that will automatically accept invitations.
|
* Adds a listener to the client that will automatically accept invitations.
|
||||||
* @param {MatrixClient} client
|
* @param {MatrixClient} client
|
||||||
* @param options By default accepts invites from anyone.
|
* @param options By default accepts invites from anyone.
|
||||||
* @param {string} options.managementRoom The room to report ignored invitations to if `recordIgnoredInvites` is true.
|
* @param {string} options.managementRoom The room to report ignored invitations to if `recordIgnoredInvites` is true.
|
||||||
* @param {boolean} options.recordIgnoredInvites Whether to report invites that will be ignored to the `managementRoom`.
|
* @param {boolean} options.recordIgnoredInvites Whether to report invites that will be ignored to the `managementRoom`.
|
||||||
* @param {boolean} options.autojoinOnlyIfManager Whether to only accept an invitation by a user present in the `managementRoom`.
|
* @param {boolean} options.autojoinOnlyIfManager Whether to only accept an invitation by a user present in the `managementRoom`.
|
||||||
* @param {string} options.acceptInvitesFromGroup A group of users to accept invites from, ignores invites form users not in this group.
|
* @param {string} options.acceptInvitesFromGroup A group of users to accept invites from, ignores invites form users not in this group.
|
||||||
*/
|
*/
|
||||||
export function addJoinOnInviteListener(client: MatrixClient, options) {
|
function addJoinOnInviteListener(client: MatrixClient, options) {
|
||||||
client.on("room.invite", async (roomId: string, inviteEvent: any) => {
|
client.on("room.invite", async (roomId: string, inviteEvent: any) => {
|
||||||
const membershipEvent = new MembershipEvent(inviteEvent);
|
const membershipEvent = new MembershipEvent(inviteEvent);
|
||||||
|
|
||||||
@ -92,4 +92,4 @@ export async function setupMjolnir(client, config): Promise<Mjolnir> {
|
|||||||
await logMessage(LogLevel.INFO, "index", "Mjolnir is starting up. Use !mjolnir to query status.");
|
await logMessage(LogLevel.INFO, "index", "Mjolnir is starting up. Use !mjolnir to query status.");
|
||||||
|
|
||||||
return new Mjolnir(client, protectedRooms, banLists);
|
return new Mjolnir(client, protectedRooms, banLists);
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,16 @@ import { HmacSHA1 } from "crypto-js";
|
|||||||
import { MatrixClient, MemoryStorageProvider, PantalaimonClient } from "matrix-bot-sdk";
|
import { MatrixClient, MemoryStorageProvider, PantalaimonClient } from "matrix-bot-sdk";
|
||||||
import config from "../../src/config";
|
import config from "../../src/config";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a user using the synapse admin api that requires the use of a registration secret rather than an admin user.
|
||||||
|
* This should only be used by test code and should not be included from any file in the source directory
|
||||||
|
* either by explicit imports or copy pasting.
|
||||||
|
* @param username The username to give the user.
|
||||||
|
* @param displayname The displayname to give the user.
|
||||||
|
* @param password The password to use.
|
||||||
|
* @param admin True to make the user an admin, false otherwise.
|
||||||
|
* @returns The response from synapse.
|
||||||
|
*/
|
||||||
export async function registerUser(username: string, displayname: string, password: string, admin: boolean) {
|
export async function registerUser(username: string, displayname: string, password: string, admin: boolean) {
|
||||||
let registerUrl = `${config.homeserverUrl}/_synapse/admin/v1/register`
|
let registerUrl = `${config.homeserverUrl}/_synapse/admin/v1/register`
|
||||||
let { data } = await axios.get(registerUrl);
|
let { data } = await axios.get(registerUrl);
|
||||||
@ -27,9 +37,9 @@ export async function registerNewTestUser(isAdmin: boolean) {
|
|||||||
let isUserValid = false;
|
let isUserValid = false;
|
||||||
let username;
|
let username;
|
||||||
do {
|
do {
|
||||||
username = `test-user-${Math.floor(Math.random() * 100000)}`
|
username = `mjolnir-test-user-${Math.floor(Math.random() * 100000)}`
|
||||||
await registerUser(username, username, username, isAdmin).then(_ => isUserValid = true).catch(e => {
|
await registerUser(username, username, username, isAdmin).then(_ => isUserValid = true).catch(e => {
|
||||||
if (e.isAxiosError && e.response.data.errcode === 'M_USER_IN_USE') {
|
if (e.isAxiosError && e?.response?.data?.errcode === 'M_USER_IN_USE') {
|
||||||
// FIXME: Replace with the real logging service.
|
// FIXME: Replace with the real logging service.
|
||||||
console.log(`${username} already registered, trying another`);
|
console.log(`${username} already registered, trying another`);
|
||||||
false // continue and try again
|
false // continue and try again
|
||||||
@ -42,16 +52,27 @@ export async function registerNewTestUser(isAdmin: boolean) {
|
|||||||
return username;
|
return username;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function newTestUser(isAdmin?: boolean): Promise<MatrixClient> {
|
/**
|
||||||
|
* Registers a unique test user and returns a `MatrixClient` logged in and ready to use.
|
||||||
|
* @param isAdmin Whether to make the user an admin.
|
||||||
|
* @returns A new `MatrixClient` session for a unique test user.
|
||||||
|
*/
|
||||||
|
export async function newTestUser(isAdmin : boolean = false): Promise<MatrixClient> {
|
||||||
const username = await registerNewTestUser(isAdmin);
|
const username = await registerNewTestUser(isAdmin);
|
||||||
const pantalaimon = new PantalaimonClient(config.homeserverUrl, new MemoryStorageProvider());
|
const pantalaimon = new PantalaimonClient(config.homeserverUrl, new MemoryStorageProvider());
|
||||||
return await pantalaimon.createClientWithCredentials(username, username);
|
return await pantalaimon.createClientWithCredentials(username, username);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility to create an event listener for m.notice msgtype m.room.messages.
|
||||||
|
* @param targetRoomdId The roomId to listen into.
|
||||||
|
* @param cb The callback when a m.notice event is found in targetRoomId.
|
||||||
|
* @returns The callback to pass to `MatrixClient.on('room.message', cb)`
|
||||||
|
*/
|
||||||
export function noticeListener(targetRoomdId: string, cb) {
|
export function noticeListener(targetRoomdId: string, cb) {
|
||||||
return (roomId, event) => {
|
return (roomId, event) => {
|
||||||
if (roomId !== targetRoomdId) return;
|
if (roomId !== targetRoomdId) return;
|
||||||
if (event?.content?.msgtype !== "m.notice") return;
|
if (event?.content?.msgtype !== "m.notice") return;
|
||||||
cb(event);
|
cb(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
import config from "../../src/config";
|
import config from "../../src/config";
|
||||||
import { Mjolnir } from "../../src/Mjolnir";
|
|
||||||
import { makeMjolnir, teardownManagementRoom } from "./mjolnirSetupUtils";
|
import { makeMjolnir, teardownManagementRoom } from "./mjolnirSetupUtils";
|
||||||
|
|
||||||
// when mjolnir starts it clobbers the config, which is cached between runs,
|
// When Mjolnir starts (src/index.ts) it clobbers the config by resolving the management room
|
||||||
// by resolving the alias and setting it to a roomid.
|
// alias specified in the config (config.managementRoom) and overwriting that with the room ID.
|
||||||
|
// Unfortunately every piece of code importing that config imports the same instance, including
|
||||||
|
// testing code, which is problematic when we want to create a fresh management room for each test.
|
||||||
|
// So there is some code in here to "undo" the mutation after we stop Mjolnir syncing.
|
||||||
export const mochaHooks = {
|
export const mochaHooks = {
|
||||||
beforeEach: [
|
beforeEach: [
|
||||||
async function() {
|
async function() {
|
||||||
@ -16,12 +18,12 @@ export const mochaHooks = {
|
|||||||
async function() {
|
async function() {
|
||||||
console.log("stopping mjolnir");
|
console.log("stopping mjolnir");
|
||||||
await this.mjolnir.stop();
|
await this.mjolnir.stop();
|
||||||
// unclobber mjolnir's dirty work, i thought the config was being cached
|
// Mjolnir resolves config.managementRoom and overwrites it, so we undo this here
|
||||||
// and was global, but that might have just been supersitiion, needs confirming.
|
// after stopping Mjolnir for the next time we setup a Mjolnir and a management room.
|
||||||
let managementRoomId = config.managementRoom;
|
let managementRoomId = config.managementRoom;
|
||||||
config.managementRoom = this.managementRoomAlias;
|
config.managementRoom = this.managementRoomAlias;
|
||||||
// remove alias from management room and leave it.
|
// remove alias from management room and leave it.
|
||||||
await teardownManagementRoom(this.mjolnir.client, managementRoomId, this.managementRoomAlias);
|
await teardownManagementRoom(this.mjolnir.client, managementRoomId, this.managementRoomAlias);
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
@ -3,7 +3,6 @@ import { assert } from "console";
|
|||||||
import config from "../../src/config";
|
import config from "../../src/config";
|
||||||
import { newTestUser, noticeListener } from "./clientHelper"
|
import { newTestUser, noticeListener } from "./clientHelper"
|
||||||
|
|
||||||
// need the start and newTestUser and then the stop call to be in setup and tear down.
|
|
||||||
describe("help command", () => {
|
describe("help command", () => {
|
||||||
let client;
|
let client;
|
||||||
before(async function () {
|
before(async function () {
|
||||||
|
@ -27,27 +27,20 @@ import * as fs from 'fs/promises';
|
|||||||
import { setupMjolnir } from '../../src/setup';
|
import { setupMjolnir } from '../../src/setup';
|
||||||
import { registerUser } from "./clientHelper";
|
import { registerUser } from "./clientHelper";
|
||||||
|
|
||||||
export async function createManagementRoom(client: MatrixClient) {
|
/**
|
||||||
let roomId = await client.createRoom();
|
* Ensures that a room exists with the alias, if it does not exist we create it.
|
||||||
return await client.createRoomAlias(config.managementRoom, roomId);
|
* @param client The MatrixClient to use to resolve or create the aliased room.
|
||||||
}
|
* @param alias The alias of the room.
|
||||||
|
* @returns The room ID of the aliased room.
|
||||||
export async function ensureManagementRoomExists(client: MatrixClient): Promise<string> {
|
*/
|
||||||
return await client.resolveRoom(config.managementRoom).catch(async e => {
|
export async function ensureAliasedRoomExists(client: MatrixClient, alias: string): Promise<string> {
|
||||||
if (e?.body?.errcode === 'M_NOT_FOUND') {
|
return await client.resolveRoom(alias)
|
||||||
console.info("moderation room hasn't been created yet, so we're making it now.")
|
.catch(async e => {
|
||||||
return await createManagementRoom(client);
|
|
||||||
}
|
|
||||||
throw e;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function ensureLobbyRoomExists(client: MatrixClient): Promise<string> {
|
|
||||||
const alias = Permalinks.parseUrl(config.protectedRooms[0]).roomIdOrAlias;
|
|
||||||
return await client.resolveRoom(alias).catch(async e => {
|
|
||||||
if (e?.body?.errcode === 'M_NOT_FOUND') {
|
if (e?.body?.errcode === 'M_NOT_FOUND') {
|
||||||
console.info(`${alias} hasn't been created yet, so we're making it now.`)
|
console.info(`${alias} hasn't been created yet, so we're making it now.`)
|
||||||
return await client.createRoomAlias(alias, await client.createRoom());
|
let roomId = await client.createRoom();
|
||||||
|
await client.createRoomAlias(config.managementRoom, roomId);
|
||||||
|
return roomId
|
||||||
}
|
}
|
||||||
throw e;
|
throw e;
|
||||||
});
|
});
|
||||||
@ -64,20 +57,23 @@ async function configureMjolnir() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// it actually might make sense to give mjolnir a clean plate each time we setup and teardown a test.
|
|
||||||
// the only issues with this might be e.g. if we need to delete a community or something
|
|
||||||
// that mjolnir sets up each time, but tbh we should probably just avoid setting things like that and tearing it down.
|
|
||||||
// One thing that probably should not be persisted between tests is the management room, subscribed lists and protected rooms.
|
|
||||||
export async function makeMjolnir() {
|
export async function makeMjolnir() {
|
||||||
await configureMjolnir();
|
await configureMjolnir();
|
||||||
console.info('starting mjolnir');
|
console.info('starting mjolnir');
|
||||||
const pantalaimon = new PantalaimonClient(config.homeserverUrl, new MemoryStorageProvider());
|
const pantalaimon = new PantalaimonClient(config.homeserverUrl, new MemoryStorageProvider());
|
||||||
const client = await pantalaimon.createClientWithCredentials(config.pantalaimon.username, config.pantalaimon.password);
|
const client = await pantalaimon.createClientWithCredentials(config.pantalaimon.username, config.pantalaimon.password);
|
||||||
await ensureManagementRoomExists(client);
|
await ensureAliasedRoomExists(client, config.managementRoom);
|
||||||
return await setupMjolnir(client, config);
|
return await setupMjolnir(client, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the alias and leave the room, can't be implicitly provided from the config because Mjolnir currently mutates it.
|
||||||
|
* @param client The client to use to leave the room.
|
||||||
|
* @param roomId The roomId of the room to leave.
|
||||||
|
* @param alias The alias to remove from the room.
|
||||||
|
*/
|
||||||
export async function teardownManagementRoom(client: MatrixClient, roomId: string, alias: string) {
|
export async function teardownManagementRoom(client: MatrixClient, roomId: string, alias: string) {
|
||||||
await client.deleteRoomAlias(alias);
|
await client.deleteRoomAlias(alias);
|
||||||
await client.leaveRoom(roomId);
|
await client.leaveRoom(roomId);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user