mirror of
https://github.com/matrix-org/mjolnir.git
synced 2024-10-01 01:36:06 -04:00
Refactor list creation with MSC3784 support. (#386)
https://github.com/matrix-org/matrix-spec-proposals/pull/3784 This was extracted from the appservice mjolnir work to reduce review burden.
This commit is contained in:
parent
5bd23ced9b
commit
da084328a9
@ -15,7 +15,7 @@ limitations under the License.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Mjolnir } from "../Mjolnir";
|
import { Mjolnir } from "../Mjolnir";
|
||||||
import { SHORTCODE_EVENT_TYPE } from "../models/PolicyList";
|
import PolicyList from "../models/PolicyList";
|
||||||
import { Permalinks, RichReply } from "matrix-bot-sdk";
|
import { Permalinks, RichReply } from "matrix-bot-sdk";
|
||||||
|
|
||||||
// !mjolnir list create <shortcode> <alias localpart>
|
// !mjolnir list create <shortcode> <alias localpart>
|
||||||
@ -23,34 +23,12 @@ export async function execCreateListCommand(roomId: string, event: any, mjolnir:
|
|||||||
const shortcode = parts[3];
|
const shortcode = parts[3];
|
||||||
const aliasLocalpart = parts[4];
|
const aliasLocalpart = parts[4];
|
||||||
|
|
||||||
const powerLevels: { [key: string]: any } = {
|
const listRoomId = await PolicyList.createList(
|
||||||
"ban": 50,
|
mjolnir.client,
|
||||||
"events": {
|
shortcode,
|
||||||
"m.room.name": 100,
|
[event['sender']],
|
||||||
"m.room.power_levels": 100,
|
{ room_alias_name: aliasLocalpart }
|
||||||
},
|
);
|
||||||
"events_default": 50, // non-default
|
|
||||||
"invite": 0,
|
|
||||||
"kick": 50,
|
|
||||||
"notifications": {
|
|
||||||
"room": 20,
|
|
||||||
},
|
|
||||||
"redact": 50,
|
|
||||||
"state_default": 50,
|
|
||||||
"users": {
|
|
||||||
[await mjolnir.client.getUserId()]: 100,
|
|
||||||
[event["sender"]]: 50
|
|
||||||
},
|
|
||||||
"users_default": 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
const listRoomId = await mjolnir.client.createRoom({
|
|
||||||
preset: "public_chat",
|
|
||||||
room_alias_name: aliasLocalpart,
|
|
||||||
invite: [event['sender']],
|
|
||||||
initial_state: [{ type: SHORTCODE_EVENT_TYPE, state_key: "", content: { shortcode: shortcode } }],
|
|
||||||
power_level_content_override: powerLevels,
|
|
||||||
});
|
|
||||||
|
|
||||||
const roomRef = Permalinks.forRoom(listRoomId);
|
const roomRef = Permalinks.forRoom(listRoomId);
|
||||||
await mjolnir.watchList(roomRef);
|
await mjolnir.watchList(roomRef);
|
||||||
|
@ -86,6 +86,10 @@ class PolicyList extends EventEmitter {
|
|||||||
// Events that we have already informed the batcher about, that we haven't loaded from the room state yet.
|
// Events that we have already informed the batcher about, that we haven't loaded from the room state yet.
|
||||||
private batchedEvents = new Set<string /* event id */>();
|
private batchedEvents = new Set<string /* event id */>();
|
||||||
|
|
||||||
|
/** MSC3784 support. Please note that policy lists predate room types. So there will be lists in the wild without this type. */
|
||||||
|
public static readonly ROOM_TYPE = "support.feline.policy.lists.msc.v1";
|
||||||
|
public static readonly ROOM_TYPE_VARIANTS = [PolicyList.ROOM_TYPE]
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is used to annotate state events we store with the rule they are associated with.
|
* This is used to annotate state events we store with the rule they are associated with.
|
||||||
* If we refactor this, it is important to also refactor any listeners to 'PolicyList.update'
|
* If we refactor this, it is important to also refactor any listeners to 'PolicyList.update'
|
||||||
@ -105,6 +109,65 @@ class PolicyList extends EventEmitter {
|
|||||||
this.batcher = new UpdateBatcher(this);
|
this.batcher = new UpdateBatcher(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new policy list.
|
||||||
|
* @param client A MatrixClient that will be used to create the list.
|
||||||
|
* @param shortcode A shortcode to refer to the list with.
|
||||||
|
* @param invite A list of users to invite to the list and make moderator.
|
||||||
|
* @param createRoomOptions Additional room create options such as an alias.
|
||||||
|
* @returns The room id for the newly created policy list.
|
||||||
|
*/
|
||||||
|
public static async createList(
|
||||||
|
client: MatrixClient,
|
||||||
|
shortcode: string,
|
||||||
|
invite: string[],
|
||||||
|
createRoomOptions = {}
|
||||||
|
): Promise<string /* room id */> {
|
||||||
|
const powerLevels: { [key: string]: any } = {
|
||||||
|
"ban": 50,
|
||||||
|
"events": {
|
||||||
|
"m.room.name": 100,
|
||||||
|
"m.room.power_levels": 100,
|
||||||
|
},
|
||||||
|
"events_default": 50, // non-default
|
||||||
|
"invite": 0,
|
||||||
|
"kick": 50,
|
||||||
|
"notifications": {
|
||||||
|
"room": 20,
|
||||||
|
},
|
||||||
|
"redact": 50,
|
||||||
|
"state_default": 50,
|
||||||
|
"users": {
|
||||||
|
[await client.getUserId()]: 100,
|
||||||
|
...invite.reduce((users, mxid) => ({...users, [mxid]: 50 }), {}),
|
||||||
|
},
|
||||||
|
"users_default": 0,
|
||||||
|
};
|
||||||
|
const finalRoomCreateOptions = {
|
||||||
|
// Support for MSC3784.
|
||||||
|
creation_content: {
|
||||||
|
type: PolicyList.ROOM_TYPE
|
||||||
|
},
|
||||||
|
preset: "public_chat",
|
||||||
|
invite,
|
||||||
|
initial_state: [
|
||||||
|
{
|
||||||
|
type: SHORTCODE_EVENT_TYPE,
|
||||||
|
state_key: "",
|
||||||
|
content: {shortcode: shortcode}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
power_level_content_override: powerLevels,
|
||||||
|
...createRoomOptions
|
||||||
|
};
|
||||||
|
// Guard room type in case someone overwrites it when declaring custom creation_content in future code.
|
||||||
|
if (!PolicyList.ROOM_TYPE_VARIANTS.includes(finalRoomCreateOptions.creation_content.type)) {
|
||||||
|
throw new TypeError(`Creating a policy room with a type other than the policy room type is not supported, you probably don't want to do this.`);
|
||||||
|
}
|
||||||
|
const listRoomId = await client.createRoom(finalRoomCreateOptions);
|
||||||
|
return listRoomId
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The code that can be used to refer to this banlist in Mjolnir commands.
|
* The code that can be used to refer to this banlist in Mjolnir commands.
|
||||||
*/
|
*/
|
||||||
|
@ -8,6 +8,7 @@ import { getMessagesByUserIn } from "../../src/utils";
|
|||||||
import { Mjolnir } from "../../src/Mjolnir";
|
import { Mjolnir } from "../../src/Mjolnir";
|
||||||
import { ALL_RULE_TYPES, Recommendation, RULE_SERVER, RULE_USER, SERVER_RULE_TYPES } from "../../src/models/ListRule";
|
import { ALL_RULE_TYPES, Recommendation, RULE_SERVER, RULE_USER, SERVER_RULE_TYPES } from "../../src/models/ListRule";
|
||||||
import AccessControlUnit, { Access, EntityAccess } from "../../src/models/AccessControlUnit";
|
import AccessControlUnit, { Access, EntityAccess } from "../../src/models/AccessControlUnit";
|
||||||
|
import { randomUUID } from "crypto";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a policy rule in a policy room.
|
* Create a policy rule in a policy room.
|
||||||
@ -564,3 +565,31 @@ describe('Test: AccessControlUnit interaction with policy lists.', function() {
|
|||||||
assertAccess(Access.Allowed, aclUnit.getAccessForServer(banMeServer), "Should not longer be any rules");
|
assertAccess(Access.Allowed, aclUnit.getAccessForServer(banMeServer), "Should not longer be any rules");
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('Test: Creating policy lists.', function() {
|
||||||
|
it('Will automatically invite and op users from invites', async function() {
|
||||||
|
const mjolnir: Mjolnir = this.mjolnir;
|
||||||
|
const testUsers = await Promise.all([...Array(2)].map(_ => newTestUser(this.config.homeserverUrl, { name: { contains: "moderator" } })))
|
||||||
|
const invite = await Promise.all(testUsers.map(client => client.getUserId()));
|
||||||
|
const policyListId = await PolicyList.createList(
|
||||||
|
mjolnir.client,
|
||||||
|
randomUUID(),
|
||||||
|
invite
|
||||||
|
);
|
||||||
|
// Check power levels are right.
|
||||||
|
const powerLevelEvent = await mjolnir.client.getRoomStateEvent(policyListId, "m.room.power_levels", "");
|
||||||
|
assert.equal(Object.keys(powerLevelEvent.users ?? {}).length, invite.length + 1);
|
||||||
|
// Check create event for MSC3784 support.
|
||||||
|
const createEvent = await mjolnir.client.getRoomStateEvent(policyListId, "m.room.create", "");
|
||||||
|
assert.equal(createEvent.type, PolicyList.ROOM_TYPE);
|
||||||
|
// We can't create rooms without forgetting the type.
|
||||||
|
await assert.rejects(
|
||||||
|
async () => {
|
||||||
|
await PolicyList.createList(mjolnir.client, randomUUID(), [], {
|
||||||
|
creation_content: {}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
TypeError
|
||||||
|
);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user