mirror of
https://github.com/matrix-org/mjolnir.git
synced 2024-10-01 01:36:06 -04:00
Don't cause panic if the bot can't protect a ban list it didn't create
This only affects users with `protectAllJoinedRooms` enabled, as the bot can't possibly protect ban lists it did not create itself.
This commit is contained in:
parent
697ada6592
commit
ba7ea90fcb
@ -81,6 +81,9 @@ protectedRooms:
|
|||||||
#
|
#
|
||||||
# Note: the management room is *excluded* from this condition. Add it to the
|
# Note: the management room is *excluded* from this condition. Add it to the
|
||||||
# protected rooms to protect it.
|
# protected rooms to protect it.
|
||||||
|
#
|
||||||
|
# Note: ban list rooms the bot is watching but didn't create will not be protected.
|
||||||
|
# Manually add these rooms to the protected rooms list if you want them protected.
|
||||||
protectAllJoinedRooms: false
|
protectAllJoinedRooms: false
|
||||||
|
|
||||||
# An optional server for the Synapse Mjolnir plugin to connect to. This is
|
# An optional server for the Synapse Mjolnir plugin to connect to. This is
|
||||||
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { LogLevel, LogService, MatrixClient, MatrixGlob, Permalinks } from "matrix-bot-sdk";
|
import { CreateEvent, LogLevel, LogService, MatrixClient, MatrixGlob, Permalinks } from "matrix-bot-sdk";
|
||||||
import BanList, { ALL_RULE_TYPES } from "./models/BanList";
|
import BanList, { ALL_RULE_TYPES } from "./models/BanList";
|
||||||
import { applyServerAcls } from "./actions/ApplyAcl";
|
import { applyServerAcls } from "./actions/ApplyAcl";
|
||||||
import { RoomUpdateError } from "./models/RoomUpdateError";
|
import { RoomUpdateError } from "./models/RoomUpdateError";
|
||||||
@ -35,6 +35,7 @@ export const STATE_RUNNING = "running";
|
|||||||
const WATCHED_LISTS_EVENT_TYPE = "org.matrix.mjolnir.watched_lists";
|
const WATCHED_LISTS_EVENT_TYPE = "org.matrix.mjolnir.watched_lists";
|
||||||
const ENABLED_PROTECTIONS_EVENT_TYPE = "org.matrix.mjolnir.enabled_protections";
|
const ENABLED_PROTECTIONS_EVENT_TYPE = "org.matrix.mjolnir.enabled_protections";
|
||||||
const PROTECTED_ROOMS_EVENT_TYPE = "org.matrix.mjolnir.protected_rooms";
|
const PROTECTED_ROOMS_EVENT_TYPE = "org.matrix.mjolnir.protected_rooms";
|
||||||
|
const WARN_UNPROTECTED_ROOM_EVENT_PREFIX = "org.matrix.mjolnir.unprotected_room_warning.for.";
|
||||||
|
|
||||||
export class Mjolnir {
|
export class Mjolnir {
|
||||||
|
|
||||||
@ -45,12 +46,16 @@ export class Mjolnir {
|
|||||||
private redactionQueue = new AutomaticRedactionQueue();
|
private redactionQueue = new AutomaticRedactionQueue();
|
||||||
private automaticRedactionReasons: MatrixGlob[] = [];
|
private automaticRedactionReasons: MatrixGlob[] = [];
|
||||||
private protectedJoinedRoomIds: string[] = [];
|
private protectedJoinedRoomIds: string[] = [];
|
||||||
|
private explicitlyProtectedRoomIds: string[] = [];
|
||||||
|
private knownUnprotectedRooms: string[] = [];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public readonly client: MatrixClient,
|
public readonly client: MatrixClient,
|
||||||
public readonly protectedRooms: { [roomId: string]: string },
|
public readonly protectedRooms: { [roomId: string]: string },
|
||||||
private banLists: BanList[],
|
private banLists: BanList[],
|
||||||
) {
|
) {
|
||||||
|
this.explicitlyProtectedRoomIds = Object.keys(this.protectedRooms);
|
||||||
|
|
||||||
for (const reason of config.automaticallyRedactForReasons) {
|
for (const reason of config.automaticallyRedactForReasons) {
|
||||||
this.automaticRedactionReasons.push(new MatrixGlob(reason.toLowerCase()));
|
this.automaticRedactionReasons.push(new MatrixGlob(reason.toLowerCase()));
|
||||||
}
|
}
|
||||||
@ -134,27 +139,31 @@ export class Mjolnir {
|
|||||||
public start() {
|
public start() {
|
||||||
return this.client.start().then(async () => {
|
return this.client.start().then(async () => {
|
||||||
this.currentState = STATE_CHECKING_PERMISSIONS;
|
this.currentState = STATE_CHECKING_PERMISSIONS;
|
||||||
|
|
||||||
|
await logMessage(LogLevel.DEBUG, "Mjolnir@startup", "Loading protected rooms...");
|
||||||
|
await this.resyncJoinedRooms(false);
|
||||||
|
try {
|
||||||
|
const data = await this.client.getAccountData(PROTECTED_ROOMS_EVENT_TYPE);
|
||||||
|
if (data && data['rooms']) {
|
||||||
|
for (const roomId of data['rooms']) {
|
||||||
|
this.protectedRooms[roomId] = Permalinks.forRoom(roomId);
|
||||||
|
this.explicitlyProtectedRoomIds.push(roomId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
LogService.warn("Mjolnir", e);
|
||||||
|
}
|
||||||
|
await this.buildWatchedBanLists();
|
||||||
|
this.applyUnprotectedRooms();
|
||||||
|
|
||||||
if (config.verifyPermissionsOnStartup) {
|
if (config.verifyPermissionsOnStartup) {
|
||||||
await logMessage(LogLevel.INFO, "Mjolnir@startup", "Checking permissions...");
|
await logMessage(LogLevel.INFO, "Mjolnir@startup", "Checking permissions...");
|
||||||
await this.verifyPermissions(config.verboseLogging);
|
await this.verifyPermissions(config.verboseLogging);
|
||||||
}
|
}
|
||||||
}).then(async () => {
|
}).then(async () => {
|
||||||
this.currentState = STATE_SYNCING;
|
this.currentState = STATE_SYNCING;
|
||||||
await logMessage(LogLevel.DEBUG, "Mjolnir@startup", "Loading protected rooms...");
|
|
||||||
await this.resyncJoinedRooms(false);
|
|
||||||
try {
|
|
||||||
const data = await this.client.getAccountData(PROTECTED_ROOMS_EVENT_TYPE);
|
|
||||||
if (data && data['rooms']) {
|
|
||||||
for (const roomId of data['rooms']) {
|
|
||||||
this.protectedRooms[roomId] = Permalinks.forRoom(roomId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
LogService.warn("Mjolnir", e);
|
|
||||||
}
|
|
||||||
if (config.syncOnStartup) {
|
if (config.syncOnStartup) {
|
||||||
await logMessage(LogLevel.INFO, "Mjolnir@startup", "Syncing lists...");
|
await logMessage(LogLevel.INFO, "Mjolnir@startup", "Syncing lists...");
|
||||||
await this.buildWatchedBanLists();
|
|
||||||
await this.syncLists(config.verboseLogging);
|
await this.syncLists(config.verboseLogging);
|
||||||
await this.enableProtections();
|
await this.enableProtections();
|
||||||
}
|
}
|
||||||
@ -167,6 +176,10 @@ export class Mjolnir {
|
|||||||
public async addProtectedRoom(roomId: string) {
|
public async addProtectedRoom(roomId: string) {
|
||||||
this.protectedRooms[roomId] = Permalinks.forRoom(roomId);
|
this.protectedRooms[roomId] = Permalinks.forRoom(roomId);
|
||||||
|
|
||||||
|
const unprotectedIdx = this.knownUnprotectedRooms.indexOf(roomId);
|
||||||
|
if (unprotectedIdx >= 0) this.knownUnprotectedRooms.splice(unprotectedIdx, 1);
|
||||||
|
this.explicitlyProtectedRoomIds.push(roomId);
|
||||||
|
|
||||||
let additionalProtectedRooms;
|
let additionalProtectedRooms;
|
||||||
try {
|
try {
|
||||||
additionalProtectedRooms = await this.client.getAccountData(PROTECTED_ROOMS_EVENT_TYPE);
|
additionalProtectedRooms = await this.client.getAccountData(PROTECTED_ROOMS_EVENT_TYPE);
|
||||||
@ -182,6 +195,9 @@ export class Mjolnir {
|
|||||||
public async removeProtectedRoom(roomId: string) {
|
public async removeProtectedRoom(roomId: string) {
|
||||||
delete this.protectedRooms[roomId];
|
delete this.protectedRooms[roomId];
|
||||||
|
|
||||||
|
const idx = this.explicitlyProtectedRoomIds.indexOf(roomId);
|
||||||
|
if (idx >= 0) this.explicitlyProtectedRoomIds.splice(idx, 1);
|
||||||
|
|
||||||
let additionalProtectedRooms;
|
let additionalProtectedRooms;
|
||||||
try {
|
try {
|
||||||
additionalProtectedRooms = await this.client.getAccountData(PROTECTED_ROOMS_EVENT_TYPE);
|
additionalProtectedRooms = await this.client.getAccountData(PROTECTED_ROOMS_EVENT_TYPE);
|
||||||
@ -205,6 +221,8 @@ export class Mjolnir {
|
|||||||
this.protectedRooms[roomId] = Permalinks.forRoom(roomId);
|
this.protectedRooms[roomId] = Permalinks.forRoom(roomId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.applyUnprotectedRooms();
|
||||||
|
|
||||||
if (withSync) {
|
if (withSync) {
|
||||||
await this.syncLists(config.verboseLogging);
|
await this.syncLists(config.verboseLogging);
|
||||||
}
|
}
|
||||||
@ -277,6 +295,8 @@ export class Mjolnir {
|
|||||||
references: this.banLists.map(b => b.roomRef),
|
references: this.banLists.map(b => b.roomRef),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await this.warnAboutUnprotectedBanListRoom(roomId);
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -295,6 +315,33 @@ export class Mjolnir {
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async warnAboutUnprotectedBanListRoom(roomId: string) {
|
||||||
|
if (!config.protectAllJoinedRooms) return; // doesn't matter
|
||||||
|
if (this.explicitlyProtectedRoomIds.includes(roomId)) return; // explicitly protected
|
||||||
|
|
||||||
|
const createEvent = new CreateEvent(await this.client.getRoomStateEvent(roomId, "m.room.create", ""));
|
||||||
|
if (createEvent.creator === await this.client.getUserId()) return; // we created it
|
||||||
|
|
||||||
|
if (!this.knownUnprotectedRooms.includes(roomId)) this.knownUnprotectedRooms.push(roomId);
|
||||||
|
this.applyUnprotectedRooms();
|
||||||
|
|
||||||
|
try {
|
||||||
|
const accountData = await this.client.getAccountData(WARN_UNPROTECTED_ROOM_EVENT_PREFIX + roomId);
|
||||||
|
if (accountData && accountData['warned']) return; // already warned
|
||||||
|
} catch (e) {
|
||||||
|
// Ignore - probably haven't warned about it yet
|
||||||
|
}
|
||||||
|
|
||||||
|
await logMessage(LogLevel.WARN, "Mjolnir", `Not protecting ${roomId} - it is a ban list that this bot did not create. Add the room as protected if it is supposed to be protected. This warning will not appear again.`);
|
||||||
|
await this.client.setAccountData(WARN_UNPROTECTED_ROOM_EVENT_PREFIX + roomId, {warned: true});
|
||||||
|
}
|
||||||
|
|
||||||
|
private applyUnprotectedRooms() {
|
||||||
|
for (const roomId of this.knownUnprotectedRooms) {
|
||||||
|
delete this.protectedRooms[roomId];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async buildWatchedBanLists() {
|
public async buildWatchedBanLists() {
|
||||||
const banLists: BanList[] = [];
|
const banLists: BanList[] = [];
|
||||||
const joinedRooms = await this.client.getJoinedRooms();
|
const joinedRooms = await this.client.getJoinedRooms();
|
||||||
@ -315,6 +362,8 @@ export class Mjolnir {
|
|||||||
await this.client.joinRoom(permalink.roomIdOrAlias, permalink.viaServers);
|
await this.client.joinRoom(permalink.roomIdOrAlias, permalink.viaServers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await this.warnAboutUnprotectedBanListRoom(roomId);
|
||||||
|
|
||||||
const list = new BanList(roomId, roomRef, this.client);
|
const list = new BanList(roomId, roomRef, this.client);
|
||||||
await list.updateList();
|
await list.updateList();
|
||||||
banLists.push(list);
|
banLists.push(list);
|
||||||
|
Loading…
Reference in New Issue
Block a user