mjolnir/test/appservice/integration/webAPITest.ts

61 lines
3.0 KiB
TypeScript
Raw Normal View History

manymjolnir appservice (#364) Mjolnir can now be run as an application service, meaning it will host multiple independent mjolnirs that can be requested by users. If the user is on the same homeserver as the appservice is deployed on, then they can provision a mjolnir via a widget https://github.com/matrix-org/mjolnir-widget. Otherwise they can invite the appservice bot to a room they want to protect. This will create them a mjolnir, a management room and a policy list. The appservice shares the same docker image as the bot, but is started slightly differently by specifying "appservice" as the first argument to docker run (this s managed by `mjolnir-entrypoint.sh`. We could have used another Dockerfile for the appservice, extending the existing one but we decided not to because there would have been lots of fiddling around the entrypoint and logistics involved around adding a tag for it via github actions. Not to mention that this would be duplicating the image just to run it with a different binary. A list of followup issues can be found here https://github.com/issues?q=is%3Aopen+is%3Aissue+author%3AGnuxie+archived%3Afalse+label%3AA-Appservice. Somewhat relevant and squashed commit messages(regrettably squashing because frankly these won't make sense in isolation): * draft widget backend * add `managementRoomId` to `provisionNewMjolnir` * remove ratelimits from appservice mjolnirs * add /join endpoint to api backend * tighter guard around room type in PolicyList matrix-bot-sdk imporved the types for this * enable esModuleInterop * launch and use postgres in a container whilst using mx-tester * limited access control policy list used for access control * Redesign initialization API of many mjolnir. It's much harder to forget to initialize the components now that you have to in order to construct them in the first place. * Ammend config not to clash with existing CI this means that the appsrvice bot is now called 'mjolnir-bot' by default which was easier than going through old code base and renaming * Change entrypoint in Dockerfile so that we can start the appservice. We could have used another Dockerfile for the appservice, extending the exising one but we decided not to because there would have been lots of fiddling around the entrypoint and logistics involved around adding a tag for it via github actions. Not to mention that this would be duplicating the image just to run it with a different binary. This solution is much simpler, backwards compatible, and conscious about the future. Co-authored-by: gnuxie <gnuxie@element.io>
2022-11-15 18:03:06 +00:00
import { MjolnirAppService } from "../../../src/appservice/AppService";
import { newTestUser } from "../../integration/clientHelper";
import { isPolicyRoom, readTestConfig, setupHarness } from "../utils/harness";
import { CreateMjolnirResponse, MjolnirWebAPIClient } from "../utils/webAPIClient";
import { MatrixClient } from "matrix-bot-sdk";
import { getFirstReply } from "../../integration/commands/commandUtils";
import expect from "expect";
import dns from 'node:dns';
manymjolnir appservice (#364) Mjolnir can now be run as an application service, meaning it will host multiple independent mjolnirs that can be requested by users. If the user is on the same homeserver as the appservice is deployed on, then they can provision a mjolnir via a widget https://github.com/matrix-org/mjolnir-widget. Otherwise they can invite the appservice bot to a room they want to protect. This will create them a mjolnir, a management room and a policy list. The appservice shares the same docker image as the bot, but is started slightly differently by specifying "appservice" as the first argument to docker run (this s managed by `mjolnir-entrypoint.sh`. We could have used another Dockerfile for the appservice, extending the existing one but we decided not to because there would have been lots of fiddling around the entrypoint and logistics involved around adding a tag for it via github actions. Not to mention that this would be duplicating the image just to run it with a different binary. A list of followup issues can be found here https://github.com/issues?q=is%3Aopen+is%3Aissue+author%3AGnuxie+archived%3Afalse+label%3AA-Appservice. Somewhat relevant and squashed commit messages(regrettably squashing because frankly these won't make sense in isolation): * draft widget backend * add `managementRoomId` to `provisionNewMjolnir` * remove ratelimits from appservice mjolnirs * add /join endpoint to api backend * tighter guard around room type in PolicyList matrix-bot-sdk imporved the types for this * enable esModuleInterop * launch and use postgres in a container whilst using mx-tester * limited access control policy list used for access control * Redesign initialization API of many mjolnir. It's much harder to forget to initialize the components now that you have to in order to construct them in the first place. * Ammend config not to clash with existing CI this means that the appsrvice bot is now called 'mjolnir-bot' by default which was easier than going through old code base and renaming * Change entrypoint in Dockerfile so that we can start the appservice. We could have used another Dockerfile for the appservice, extending the exising one but we decided not to because there would have been lots of fiddling around the entrypoint and logistics involved around adding a tag for it via github actions. Not to mention that this would be duplicating the image just to run it with a different binary. This solution is much simpler, backwards compatible, and conscious about the future. Co-authored-by: gnuxie <gnuxie@element.io>
2022-11-15 18:03:06 +00:00
interface Context extends Mocha.Context {
appservice?: MjolnirAppService
moderator?: MatrixClient
}
// Necessary for CI: Node 17+ defaults to using ipv6 first, but Github Actions does not support ipv6
dns.setDefaultResultOrder('ipv4first');
manymjolnir appservice (#364) Mjolnir can now be run as an application service, meaning it will host multiple independent mjolnirs that can be requested by users. If the user is on the same homeserver as the appservice is deployed on, then they can provision a mjolnir via a widget https://github.com/matrix-org/mjolnir-widget. Otherwise they can invite the appservice bot to a room they want to protect. This will create them a mjolnir, a management room and a policy list. The appservice shares the same docker image as the bot, but is started slightly differently by specifying "appservice" as the first argument to docker run (this s managed by `mjolnir-entrypoint.sh`. We could have used another Dockerfile for the appservice, extending the existing one but we decided not to because there would have been lots of fiddling around the entrypoint and logistics involved around adding a tag for it via github actions. Not to mention that this would be duplicating the image just to run it with a different binary. A list of followup issues can be found here https://github.com/issues?q=is%3Aopen+is%3Aissue+author%3AGnuxie+archived%3Afalse+label%3AA-Appservice. Somewhat relevant and squashed commit messages(regrettably squashing because frankly these won't make sense in isolation): * draft widget backend * add `managementRoomId` to `provisionNewMjolnir` * remove ratelimits from appservice mjolnirs * add /join endpoint to api backend * tighter guard around room type in PolicyList matrix-bot-sdk imporved the types for this * enable esModuleInterop * launch and use postgres in a container whilst using mx-tester * limited access control policy list used for access control * Redesign initialization API of many mjolnir. It's much harder to forget to initialize the components now that you have to in order to construct them in the first place. * Ammend config not to clash with existing CI this means that the appsrvice bot is now called 'mjolnir-bot' by default which was easier than going through old code base and renaming * Change entrypoint in Dockerfile so that we can start the appservice. We could have used another Dockerfile for the appservice, extending the exising one but we decided not to because there would have been lots of fiddling around the entrypoint and logistics involved around adding a tag for it via github actions. Not to mention that this would be duplicating the image just to run it with a different binary. This solution is much simpler, backwards compatible, and conscious about the future. Co-authored-by: gnuxie <gnuxie@element.io>
2022-11-15 18:03:06 +00:00
describe("Test that the app service can provision a mjolnir when requested from the web API", function () {
afterEach(function(this: Context) {
this.moderator?.stop();
if (this.appservice) {
return this.appservice.close();
} else {
console.warn("Missing Appservice in this context, so cannot stop it.")
return Promise.resolve(); // TS7030: Not all code paths return a value.
manymjolnir appservice (#364) Mjolnir can now be run as an application service, meaning it will host multiple independent mjolnirs that can be requested by users. If the user is on the same homeserver as the appservice is deployed on, then they can provision a mjolnir via a widget https://github.com/matrix-org/mjolnir-widget. Otherwise they can invite the appservice bot to a room they want to protect. This will create them a mjolnir, a management room and a policy list. The appservice shares the same docker image as the bot, but is started slightly differently by specifying "appservice" as the first argument to docker run (this s managed by `mjolnir-entrypoint.sh`. We could have used another Dockerfile for the appservice, extending the existing one but we decided not to because there would have been lots of fiddling around the entrypoint and logistics involved around adding a tag for it via github actions. Not to mention that this would be duplicating the image just to run it with a different binary. A list of followup issues can be found here https://github.com/issues?q=is%3Aopen+is%3Aissue+author%3AGnuxie+archived%3Afalse+label%3AA-Appservice. Somewhat relevant and squashed commit messages(regrettably squashing because frankly these won't make sense in isolation): * draft widget backend * add `managementRoomId` to `provisionNewMjolnir` * remove ratelimits from appservice mjolnirs * add /join endpoint to api backend * tighter guard around room type in PolicyList matrix-bot-sdk imporved the types for this * enable esModuleInterop * launch and use postgres in a container whilst using mx-tester * limited access control policy list used for access control * Redesign initialization API of many mjolnir. It's much harder to forget to initialize the components now that you have to in order to construct them in the first place. * Ammend config not to clash with existing CI this means that the appsrvice bot is now called 'mjolnir-bot' by default which was easier than going through old code base and renaming * Change entrypoint in Dockerfile so that we can start the appservice. We could have used another Dockerfile for the appservice, extending the exising one but we decided not to because there would have been lots of fiddling around the entrypoint and logistics involved around adding a tag for it via github actions. Not to mention that this would be duplicating the image just to run it with a different binary. This solution is much simpler, backwards compatible, and conscious about the future. Co-authored-by: gnuxie <gnuxie@element.io>
2022-11-15 18:03:06 +00:00
}
});
it("A moderator that requests a mjolnir via a matrix invitation will be invited to a new policy and management room", async function (this: Context) {
const config = readTestConfig();
this.appservice = await setupHarness();
// create a moderator
const moderator = await newTestUser(config.homeserver.url, { name: { contains: "test" } });
const apiClient = await MjolnirWebAPIClient.makeClient(moderator, "http://localhost:9001");
const roomToProtectId = await moderator.createRoom({ preset: "public_chat" });
// have the moderator invite the appservice bot in order to request a new mjolnir
this.moderator = moderator;
const roomsInvitedTo: string[] = [];
const mjolnirDetails: CreateMjolnirResponse = await new Promise(async resolve => {
const mjolnirDetailsPromise = apiClient.createMjolnir(roomToProtectId);
moderator.on('room.invite', (roomId: string) => {
roomsInvitedTo.push(roomId)
// the appservice should invite it to a policy room and a management room.
if (roomsInvitedTo.length === 2) {
mjolnirDetailsPromise.then(resolve);
}
});
await moderator.start();
});
await Promise.all(roomsInvitedTo.map(roomId => moderator.joinRoom(roomId)));
const managementRoomId = roomsInvitedTo.filter(async roomId => !(await isPolicyRoom(moderator, roomId)))[0];
expect(managementRoomId).toBe(mjolnirDetails.managementRoomId);
// Check that the newly provisioned mjolnir is actually responsive.
const event = await getFirstReply(moderator, managementRoomId, () => {
return moderator.sendMessage(managementRoomId, { body: `!mjolnir status`, msgtype: 'm.text' });
})
expect(event.sender).toBe(mjolnirDetails.mjolnirUserId);
})
})