mirror of
https://github.com/matrix-org/mjolnir.git
synced 2024-10-01 01:36:06 -04:00
WIP: Part deux
This commit is contained in:
parent
829e1bd0aa
commit
570845a7ec
@ -27,7 +27,7 @@ import {
|
||||
TextualMessageEventContent
|
||||
} from "matrix-bot-sdk";
|
||||
|
||||
import { ALL_RULE_TYPES as ALL_BAN_LIST_RULE_TYPES, RULE_ROOM, RULE_SERVER, RULE_USER } from "./models/ListRule";
|
||||
import { ALL_RULE_TYPES as ALL_BAN_LIST_RULE_TYPES, RULE_ROOM, RULE_SERVER, RULE_USER } from "./models/PolicyRule";
|
||||
import { applyServerAcls } from "./actions/ApplyAcl";
|
||||
import { RoomUpdateError } from "./models/RoomUpdateError";
|
||||
import { COMMAND_PREFIX, handleCommand } from "./commands/CommandHandler";
|
||||
@ -50,7 +50,7 @@ import RuleServer from "./models/RuleServer";
|
||||
import { RoomMemberManager } from "./RoomMembers";
|
||||
import { ProtectedRoomActivityTracker } from "./queues/ProtectedRoomActivityTracker";
|
||||
import { ThrottlingQueue } from "./queues/ThrottlingQueue";
|
||||
import PolicyList, { ListRuleChange } from "./models/PolicyList";
|
||||
import PolicyList, { PolicyRuleChange } from "./models/PolicyList";
|
||||
|
||||
const levelToFn = {
|
||||
[LogLevel.DEBUG.toString()]: LogService.debug,
|
||||
@ -1052,7 +1052,7 @@ export class Mjolnir {
|
||||
* @param ignoreSelf Whether to exclude changes that have been made by Mjolnir.
|
||||
* @returns true if the message was sent, false if it wasn't (because there there were no changes to report).
|
||||
*/
|
||||
private async printBanlistChanges(changes: ListRuleChange[], list: PolicyList, ignoreSelf = false): Promise<boolean> {
|
||||
private async printBanlistChanges(changes: PolicyRuleChange[], list: PolicyList, ignoreSelf = false): Promise<boolean> {
|
||||
if (ignoreSelf) {
|
||||
const sender = await this.client.getUserId();
|
||||
changes = changes.filter(change => change.sender !== sender);
|
||||
|
@ -16,7 +16,7 @@ limitations under the License.
|
||||
|
||||
import { RichReply } from "matrix-bot-sdk";
|
||||
import { Mjolnir } from "../Mjolnir";
|
||||
import { EntityType } from "../models/ListRule";
|
||||
import { EntityType } from "../models/PolicyRule";
|
||||
import { htmlEscape } from "../utils";
|
||||
|
||||
/**
|
||||
|
@ -16,7 +16,7 @@ limitations under the License.
|
||||
|
||||
import { Mjolnir } from "../Mjolnir";
|
||||
import { RichReply } from "matrix-bot-sdk";
|
||||
import { EntityType, Recommendation } from "../models/ListRule";
|
||||
import { EntityType, Recommendation } from "../models/PolicyRule";
|
||||
|
||||
// !mjolnir import <room ID> <shortcode>
|
||||
export async function execImportCommand(roomId: string, event: any, mjolnir: Mjolnir, parts: string[]) {
|
||||
|
@ -17,7 +17,7 @@ limitations under the License.
|
||||
import { Mjolnir } from "../Mjolnir";
|
||||
import PolicyList from "../models/PolicyList";
|
||||
import { extractRequestError, LogLevel, LogService, MatrixGlob, RichReply } from "matrix-bot-sdk";
|
||||
import { Recommendation, RULE_ROOM, RULE_SERVER, RULE_USER, USER_RULE_TYPES } from "../models/ListRule";
|
||||
import { Recommendation, RULE_ROOM, RULE_SERVER, RULE_USER, USER_RULE_TYPES } from "../models/PolicyRule";
|
||||
import config from "../config";
|
||||
import { DEFAULT_LIST_EVENT_TYPE } from "./SetDefaultBanListCommand";
|
||||
|
||||
|
@ -16,7 +16,7 @@ limitations under the License.
|
||||
|
||||
import { extractRequestError, LogService, MatrixClient, UserID } from "matrix-bot-sdk";
|
||||
import { EventEmitter } from "events";
|
||||
import { ALL_RULE_TYPES, EntityType, ListRule, Recommendation, ROOM_RULE_TYPES, RULE_ROOM, RULE_SERVER, RULE_USER, SERVER_RULE_TYPES, USER_RULE_TYPES } from "./ListRule";
|
||||
import { ALL_RULE_TYPES, EntityType, PolicyRule, Recommendation, ROOM_RULE_TYPES, RULE_ROOM, RULE_SERVER, RULE_USER, SERVER_RULE_TYPES, USER_RULE_TYPES } from "./PolicyRule";
|
||||
|
||||
export const SHORTCODE_EVENT_TYPE = "org.matrix.mjolnir.shortcode";
|
||||
|
||||
@ -26,7 +26,7 @@ export enum ChangeType {
|
||||
Modified = "MODIFIED"
|
||||
}
|
||||
|
||||
export interface ListRuleChange {
|
||||
export interface PolicyRuleChange {
|
||||
readonly changeType: ChangeType,
|
||||
/**
|
||||
* State event that caused the change.
|
||||
@ -43,7 +43,7 @@ export interface ListRuleChange {
|
||||
* The current rule represented by the event.
|
||||
* If the rule has been removed, then this will show what the rule was.
|
||||
*/
|
||||
readonly rule: ListRule,
|
||||
readonly rule: PolicyRule,
|
||||
/**
|
||||
* The previous state that has been changed. Only (and always) provided when the change type is `ChangeType.Removed` or `Modified`.
|
||||
* This will be a copy of the same event as `event` when a redaction has occurred and this will show its unredacted state.
|
||||
@ -53,8 +53,8 @@ export interface ListRuleChange {
|
||||
|
||||
declare interface PolicyList {
|
||||
// PolicyList.update is emitted when the PolicyList has pulled new rules from Matrix and informs listeners of any changes.
|
||||
on(event: 'PolicyList.update', listener: (list: PolicyList, changes: ListRuleChange[]) => void): this
|
||||
emit(event: 'PolicyList.update', list: PolicyList, changes: ListRuleChange[]): boolean
|
||||
on(event: 'PolicyList.update', listener: (list: PolicyList, changes: PolicyRuleChange[]) => void): this
|
||||
emit(event: 'PolicyList.update', list: PolicyList, changes: PolicyRuleChange[]): boolean
|
||||
// PolicyList.batch is emitted when the PolicyList has created a batch from the events provided by `updateForEvent`.
|
||||
on(event: 'PolicyList.batch', listener: (list: PolicyList) => void): this
|
||||
emit(event: 'PolicyList.batch', list: PolicyList): boolean
|
||||
@ -118,10 +118,10 @@ class PolicyList extends EventEmitter {
|
||||
/**
|
||||
* Return all the active rules of a given kind.
|
||||
* @param kind e.g. RULE_SERVER (m.policy.rule.server). Rule types are always normalised when they are interned into the PolicyList.
|
||||
* @returns The active ListRules for the ban list of that kind.
|
||||
* @returns The active PolicyRules for the ban list of that kind.
|
||||
*/
|
||||
private rulesOfKind(kind: string): ListRule[] {
|
||||
const rules: ListRule[] = []
|
||||
private rulesOfKind(kind: string): PolicyRule[] {
|
||||
const rules: PolicyRule[] = []
|
||||
const stateKeyMap = this.state.get(kind);
|
||||
if (stateKeyMap) {
|
||||
for (const event of stateKeyMap.values()) {
|
||||
@ -146,19 +146,19 @@ class PolicyList extends EventEmitter {
|
||||
});
|
||||
}
|
||||
|
||||
public get serverRules(): ListRule[] {
|
||||
public get serverRules(): PolicyRule[] {
|
||||
return this.rulesOfKind(RULE_SERVER);
|
||||
}
|
||||
|
||||
public get userRules(): ListRule[] {
|
||||
public get userRules(): PolicyRule[] {
|
||||
return this.rulesOfKind(RULE_USER);
|
||||
}
|
||||
|
||||
public get roomRules(): ListRule[] {
|
||||
public get roomRules(): PolicyRule[] {
|
||||
return this.rulesOfKind(RULE_ROOM);
|
||||
}
|
||||
|
||||
public get allRules(): ListRule[] {
|
||||
public get allRules(): PolicyRule[] {
|
||||
return [...this.serverRules, ...this.userRules, ...this.roomRules];
|
||||
}
|
||||
|
||||
@ -169,7 +169,7 @@ class PolicyList extends EventEmitter {
|
||||
* @param entity The entity to test e.g. the user id, server name or a room id.
|
||||
* @returns All of the rules that match this entity.
|
||||
*/
|
||||
public rulesMatchingEntity(entity: string, ruleKind?: string): ListRule[] {
|
||||
public rulesMatchingEntity(entity: string, ruleKind?: string): PolicyRule[] {
|
||||
const ruleTypeOf: (entityPart: string) => string = (entityPart: string) => {
|
||||
if (ruleKind) {
|
||||
return ruleKind;
|
||||
@ -233,8 +233,8 @@ class PolicyList extends EventEmitter {
|
||||
* and updating the model to reflect the room.
|
||||
* @returns A description of any rules that were added, modified or removed from the list as a result of this update.
|
||||
*/
|
||||
public async updateList(): Promise<ListRuleChange[]> {
|
||||
let changes: ListRuleChange[] = [];
|
||||
public async updateList(): Promise<PolicyRuleChange[]> {
|
||||
let changes: PolicyRuleChange[] = [];
|
||||
|
||||
const state = await this.client.getRoomState(this.roomId);
|
||||
for (const event of state) {
|
||||
@ -313,11 +313,11 @@ class PolicyList extends EventEmitter {
|
||||
changeType, event, sender, rule: previousState.unsigned.rule,
|
||||
...previousState ? { previousState } : {}
|
||||
});
|
||||
// Event has no content and cannot be parsed as a ListRule.
|
||||
// Event has no content and cannot be parsed as a PolicyRule.
|
||||
continue;
|
||||
}
|
||||
// It's a rule - parse it
|
||||
const rule = ListRule.parse(event);
|
||||
const rule = PolicyRule.parse(event);
|
||||
if (!rule) {
|
||||
// Invalid/unknown rule, just skip it.
|
||||
continue;
|
||||
|
@ -51,9 +51,9 @@ export enum Recommendation {
|
||||
|
||||
/// The rule specifies an "opinion", as a number in [-100, +100],
|
||||
/// where -100 represents a user who is considered absolutely toxic
|
||||
/// by whoever issued this ListRule and +100 represents a user who
|
||||
/// by whoever issued this PolicyRule and +100 represents a user who
|
||||
/// is considered absolutely absolutely perfect by whoever issued
|
||||
/// this ListRule.
|
||||
/// this PolicyRule.
|
||||
Opinion = "org.matrix.msc3845.opinion",
|
||||
}
|
||||
|
||||
@ -81,7 +81,7 @@ export const OPINION_MAX = +100;
|
||||
/**
|
||||
* Representation of a rule within a Policy List.
|
||||
*/
|
||||
export abstract class ListRule {
|
||||
export abstract class PolicyRule {
|
||||
/**
|
||||
* A glob for `entity`.
|
||||
*/
|
||||
@ -115,12 +115,12 @@ export abstract class ListRule {
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate and parse an event into a ListRule.
|
||||
* Validate and parse an event into a PolicyRule.
|
||||
*
|
||||
* @param event An *untrusted* event.
|
||||
* @returns null if the ListRule is invalid or not recognized by Mjölnir.
|
||||
* @returns null if the PolicyRule is invalid or not recognized by Mjölnir.
|
||||
*/
|
||||
public static parse(event: {type: string, content: any}): ListRule | null {
|
||||
public static parse(event: {type: string, content: any}): PolicyRule | null {
|
||||
// Parse common fields.
|
||||
// If a field is ill-formed, discard the rule.
|
||||
const content = event['content'];
|
||||
@ -155,17 +155,17 @@ export abstract class ListRule {
|
||||
|
||||
// From this point, we may need specific fields.
|
||||
if (RECOMMENDATION_BAN_VARIANTS.includes(recommendation)) {
|
||||
return new ListRuleBan(entity, reason, kind);
|
||||
return new PolicyRuleBan(entity, reason, kind);
|
||||
} else if (RECOMMENDATION_OPINION_VARIANTS.includes(recommendation)) {
|
||||
let opinion = content['opinion'];
|
||||
if (!Number.isInteger(opinion)) {
|
||||
return null;
|
||||
}
|
||||
return new ListRuleOpinion(entity, reason, kind, opinion);
|
||||
return new PolicyRuleOpinion(entity, reason, kind, opinion);
|
||||
} else {
|
||||
// As long as the `recommendation` is defined, we assume
|
||||
// that the rule is correct, just unknown.
|
||||
return new ListRuleUnknown(entity, reason, kind, content);
|
||||
return new PolicyRuleUnknown(entity, reason, kind, content);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -173,7 +173,7 @@ export abstract class ListRule {
|
||||
/**
|
||||
* A rule representing a "ban".
|
||||
*/
|
||||
export class ListRuleBan extends ListRule {
|
||||
export class PolicyRuleBan extends PolicyRule {
|
||||
constructor(
|
||||
/**
|
||||
* The entity covered by this rule, e.g. a glob user ID, a room ID, a server domain.
|
||||
@ -195,7 +195,7 @@ export class ListRuleBan extends ListRule {
|
||||
/**
|
||||
* A rule representing an "opinion"
|
||||
*/
|
||||
export class ListRuleOpinion extends ListRule {
|
||||
export class PolicyRuleOpinion extends PolicyRule {
|
||||
constructor(
|
||||
/**
|
||||
* The entity covered by this rule, e.g. a glob user ID, a room ID, a server domain.
|
||||
@ -229,7 +229,7 @@ export class ListRuleOpinion extends ListRule {
|
||||
/**
|
||||
* Any list rule that we do not understand.
|
||||
*/
|
||||
export class ListRuleUnknown extends ListRule {
|
||||
export class PolicyRuleUnknown extends PolicyRule {
|
||||
constructor(
|
||||
/**
|
||||
* The entity covered by this rule, e.g. a glob user ID, a room ID, a server domain.
|
@ -13,10 +13,10 @@ 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 BanList, { ChangeType, ListRuleChange } from "./PolicyList"
|
||||
import BanList, { ChangeType, PolicyRuleChange } from "./PolicyList"
|
||||
import * as crypto from "crypto";
|
||||
import { LogService } from "matrix-bot-sdk";
|
||||
import { EntityType, ListRule } from "./ListRule";
|
||||
import { EntityType, PolicyRule } from "./PolicyRule";
|
||||
import PolicyList from "./PolicyList";
|
||||
|
||||
export const USER_MAY_INVITE = 'user_may_invite';
|
||||
@ -149,10 +149,10 @@ export default class RuleServer {
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the rule server to reflect a ListRule change.
|
||||
* @param change A ListRuleChange sourced from a BanList.
|
||||
* Update the rule server to reflect a PolicyRule change.
|
||||
* @param change A PolicyRuleChange sourced from a BanList.
|
||||
*/
|
||||
private applyRuleChange(change: ListRuleChange): void {
|
||||
private applyRuleChange(change: PolicyRuleChange): void {
|
||||
if (change.changeType === ChangeType.Added) {
|
||||
const eventRules = new EventRules(change.event.event_id, change.event.room_id, toRuleServerFormat(change.rule), this.currentToken);
|
||||
this.addEventRules(eventRules);
|
||||
@ -208,9 +208,9 @@ export default class RuleServer {
|
||||
* Process the changes that have been made to a BanList.
|
||||
* This will ususally be called as a callback from `BanList.onChange`.
|
||||
* @param banList The BanList that the changes happened in.
|
||||
* @param changes An array of ListRuleChanges.
|
||||
* @param changes An array of PolicyRuleChanges.
|
||||
*/
|
||||
private update(banList: BanList, changes: ListRuleChange[]) {
|
||||
private update(banList: BanList, changes: PolicyRuleChange[]) {
|
||||
if (changes.length > 0) {
|
||||
this.nextToken();
|
||||
changes.forEach(this.applyRuleChange, this);
|
||||
@ -257,11 +257,11 @@ export default class RuleServer {
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a ListRule into the format that can be served by the rule server.
|
||||
* @param policyRule A ListRule to convert.
|
||||
* Convert a PolicyRule into the format that can be served by the rule server.
|
||||
* @param policyRule A PolicyRule to convert.
|
||||
* @returns An array of rules that can be served from the rule server.
|
||||
*/
|
||||
function toRuleServerFormat(policyRule: ListRule): RuleServerRule[] {
|
||||
function toRuleServerFormat(policyRule: PolicyRule): RuleServerRule[] {
|
||||
function makeLiteral(literal: string) {
|
||||
return { literal }
|
||||
}
|
||||
|
@ -3,11 +3,11 @@ import { strict as assert } from "assert";
|
||||
import config from "../../src/config";
|
||||
import { newTestUser } from "./clientHelper";
|
||||
import { LogService, MatrixClient, Permalinks, UserID } from "matrix-bot-sdk";
|
||||
import PolicyList, { ChangeType, ListRuleChange } from "../../src/models/PolicyList";
|
||||
import PolicyList, { ChangeType, PolicyRuleChange } from "../../src/models/PolicyList";
|
||||
import { ServerAcl } from "../../src/models/ServerAcl";
|
||||
import { getFirstReaction } from "./commands/commandUtils";
|
||||
import { getMessagesByUserIn } from "../../src/utils";
|
||||
import { ALL_RULE_TYPES, RULE_SERVER, RULE_USER, SERVER_RULE_TYPES } from "../../src/models/ListRule";
|
||||
import { ALL_RULE_TYPES, RULE_SERVER, RULE_USER, SERVER_RULE_TYPES } from "../../src/models/PolicyRule";
|
||||
|
||||
/**
|
||||
* Create a policy rule in a policy room.
|
||||
@ -40,7 +40,7 @@ describe("Test: Updating the PolicyList", function() {
|
||||
|
||||
// Test adding a new rule
|
||||
await createPolicyRule(mjolnir, banListId, RULE_USER, '@added:localhost:9999', '');
|
||||
let changes: ListRuleChange[] = await banList.updateList();
|
||||
let changes: PolicyRuleChange[] = await banList.updateList();
|
||||
assert.equal(changes.length, 1, 'There should only be one change');
|
||||
assert.equal(changes[0].changeType, ChangeType.Added);
|
||||
assert.equal(changes[0].sender, await mjolnir.getUserId());
|
||||
@ -187,7 +187,7 @@ describe("Test: Updating the PolicyList", function() {
|
||||
for (let i = 0; i < ALL_RULE_TYPES.length; i++) {
|
||||
await createPolicyRule(mjolnir, banListId, ALL_RULE_TYPES[i], `*${i}*`, '');
|
||||
}
|
||||
let changes: ListRuleChange[] = await banList.updateList();
|
||||
let changes: PolicyRuleChange[] = await banList.updateList();
|
||||
assert.equal(changes.length, ALL_RULE_TYPES.length);
|
||||
assert.equal(banList.allRules.length, ALL_RULE_TYPES.length);
|
||||
})
|
||||
@ -199,7 +199,7 @@ describe('Test: We do not respond to recommendations other than m.ban in the ban
|
||||
const banListId = await mjolnir.createRoom();
|
||||
const banList = new PolicyList(banListId, banListId, mjolnir);
|
||||
await createPolicyRule(mjolnir, banListId, RULE_SERVER, 'exmaple.org', '', { recommendation: 'something that is not m.ban' });
|
||||
let changes: ListRuleChange[] = await banList.updateList();
|
||||
let changes: PolicyRuleChange[] = await banList.updateList();
|
||||
assert.equal(changes.length, 1, 'There should only be one change');
|
||||
assert.equal(changes[0].changeType, ChangeType.Added);
|
||||
assert.equal(changes[0].sender, await mjolnir.getUserId());
|
||||
@ -219,7 +219,7 @@ describe('Test: We will not be able to ban ourselves via ACL.', function() {
|
||||
await createPolicyRule(mjolnir, banListId, RULE_SERVER, 'evil.com', '');
|
||||
await createPolicyRule(mjolnir, banListId, RULE_SERVER, '*', '');
|
||||
// We should still intern the matching rules rule.
|
||||
let changes: ListRuleChange[] = await banList.updateList();
|
||||
let changes: PolicyRuleChange[] = await banList.updateList();
|
||||
assert.equal(banList.serverRules.length, 3);
|
||||
// But when we construct an ACL, we should be safe.
|
||||
const acl = new ServerAcl(serverName)
|
||||
|
Loading…
Reference in New Issue
Block a user