From 3d02c72401ddfa75327fdb59911e428774b64133 Mon Sep 17 00:00:00 2001
From: Gnuxie <50846879+Gnuxie@users.noreply.github.com>
Date: Thu, 18 Apr 2024 17:32:27 +0100
Subject: [PATCH] Gnuxie/consequence renderer clarity (#356)
* Allow span attributes to be rendered.
* Update for MPS 0.18.0.
* Add some consistency to capability renderers.
---
package.json | 4 +-
src/capabilities/CommonRenderers.tsx | 15 +++-
.../ServerACLConsequencesRenderer.tsx | 19 ++---
.../StandardEventConsequencesRenderer.tsx | 5 +-
.../StandardUserConsequencesRenderer.tsx | 69 +++++++++++++------
.../interface-manager/DeadDocumentHtml.ts | 2 +-
yarn.lock | 18 ++---
7 files changed, 85 insertions(+), 47 deletions(-)
diff --git a/package.json b/package.json
index 915df266..b1afb33f 100644
--- a/package.json
+++ b/package.json
@@ -63,8 +63,8 @@
"js-yaml": "^4.1.0",
"jsdom": "^24.0.0",
"matrix-appservice-bridge": "^9.0.1",
- "matrix-protection-suite": "npm:@gnuxie/matrix-protection-suite@0.17.1",
- "matrix-protection-suite-for-matrix-bot-sdk": "npm:@gnuxie/matrix-protection-suite-for-matrix-bot-sdk@0.17.1",
+ "matrix-protection-suite": "npm:@gnuxie/matrix-protection-suite@0.18.0",
+ "matrix-protection-suite-for-matrix-bot-sdk": "npm:@gnuxie/matrix-protection-suite-for-matrix-bot-sdk@0.18.0",
"parse-duration": "^1.0.2",
"pg": "^8.8.0",
"shell-quote": "^1.7.3",
diff --git a/src/capabilities/CommonRenderers.tsx b/src/capabilities/CommonRenderers.tsx
index 76d6634e..917425e6 100644
--- a/src/capabilities/CommonRenderers.tsx
+++ b/src/capabilities/CommonRenderers.tsx
@@ -44,11 +44,13 @@ export function renderExceptionTrail(error: ActionError): DocumentNode {
export function renderFailedSingularConsequence(
description: DescriptionMeta,
+ title: DocumentNode,
error: ActionError
): DocumentNode {
return
- {description.name}
: {error.mostRelevantElaboration}
+ {description.name}
: {title} - {renderOutcome(false)}
+ {error.mostRelevantElaboration}
{renderDetailsNotice(error)}
{renderElaborationTrail(error)}
{renderExceptionTrail(error)}
@@ -56,13 +58,20 @@ export function renderFailedSingularConsequence(
}
+export function renderOutcome(isOutcomeOk: boolean): DocumentNode {
+ const colour = isOutcomeOk ? '#7cfc00' : '#E01F2B';
+ return
+ {isOutcomeOk ? 'OK' : 'Failed'}
+
+}
+
function renderRoomOutcomeOk(roomID: StringRoomID): DocumentNode {
- return {renderRoomPill(MatrixRoomReference.fromRoomID(roomID))} - OK
+ return {renderRoomPill(MatrixRoomReference.fromRoomID(roomID))} - {renderOutcome(true)}
}
function renderRoomOutcomeError(roomID: StringRoomID, error: ActionError): DocumentNode {
return
- {renderRoomPill(MatrixRoomReference.fromRoomID(roomID))} - Error: {error.mostRelevantElaboration}
+ {renderRoomPill(MatrixRoomReference.fromRoomID(roomID))} - {renderOutcome(false)}: {error.mostRelevantElaboration}
{renderDetailsNotice(error)}
{renderElaborationTrail(error)}
{renderExceptionTrail(error)}
diff --git a/src/capabilities/ServerACLConsequencesRenderer.tsx b/src/capabilities/ServerACLConsequencesRenderer.tsx
index 16533ccd..339cec2d 100644
--- a/src/capabilities/ServerACLConsequencesRenderer.tsx
+++ b/src/capabilities/ServerACLConsequencesRenderer.tsx
@@ -26,37 +26,40 @@ class StandardServerConsequencesRenderer implements ServerConsequences {
public readonly requiredPermissions = this.capability.requiredPermissions;
public async consequenceForServerInRoom(roomID: StringRoomID, revision: PolicyListRevision): Promise> {
const capabilityResult = await this.capability.consequenceForServerInRoom(roomID, revision);
+ const title =
+ Setting server ACL in {Permalinks.forRoom(roomID)} as it is out of sync with watched policies.
+ ;
if (isError(capabilityResult)) {
- this.messageCollector.addMessage(this.description, renderFailedSingularConsequence(this.description, capabilityResult.error))
+ this.messageCollector.addMessage(this.description, renderFailedSingularConsequence(this.description, title, capabilityResult.error))
return capabilityResult;
}
- this.messageCollector.addOneliner(this.description,
- Setting server ACL in {Permalinks.forRoom(roomID)} as it is out of sync with watched policies.
- )
+ this.messageCollector.addOneliner(this.description, title);
return Ok(undefined);
}
public async consequenceForServerInRoomSet(revision: PolicyListRevision): Promise> {
const capabilityResult = await this.capability.consequenceForServerInRoomSet(revision);
+ const title = Updating server ACL in protected rooms.;
if (isError(capabilityResult)) {
- this.messageCollector.addMessage(this.description, renderFailedSingularConsequence(this.description, capabilityResult.error))
+ this.messageCollector.addMessage(this.description, renderFailedSingularConsequence(this.description, title, capabilityResult.error))
return capabilityResult;
}
this.messageCollector.addMessage(
this.description, renderRoomSetResult(capabilityResult.ok, {
- summary: {this.description.name}
: Updating server ACL in protected rooms.
+ summary: {this.description.name}
: {title}
})
);
return capabilityResult;
}
public async unbanServerFromRoomSet(serverName: string, reason: string): Promise> {
const capabilityResult = await this.capability.unbanServerFromRoomSet(serverName, reason);
+ const title = Removing {serverName} from denied servers in protected rooms.;
if (isError(capabilityResult)) {
- this.messageCollector.addMessage(this.description, renderFailedSingularConsequence(this.description, capabilityResult.error));
+ this.messageCollector.addMessage(this.description, renderFailedSingularConsequence(this.description, title, capabilityResult.error));
return capabilityResult;
}
this.messageCollector.addMessage(
this.description, renderRoomSetResult(capabilityResult.ok, {
- summary: {this.description.name}
: Removing {serverName} from denied servers in protected rooms.
+ summary: {this.description.name}
: {title}
})
);
return capabilityResult;
diff --git a/src/capabilities/StandardEventConsequencesRenderer.tsx b/src/capabilities/StandardEventConsequencesRenderer.tsx
index d17876c6..4b29beb9 100644
--- a/src/capabilities/StandardEventConsequencesRenderer.tsx
+++ b/src/capabilities/StandardEventConsequencesRenderer.tsx
@@ -26,11 +26,12 @@ class StandardEventConsequencesRenderer implements EventConsequences {
public readonly requiredPermissions = this.capability.requiredPermissions;
public async consequenceForEvent(roomID: StringRoomID, eventID: StringEventID, reason: string): Promise> {
const capabilityResult = await this.capability.consequenceForEvent(roomID, eventID, reason);
+ const title = Redacting {Permalinks.forEvent(roomID, eventID)}.;
if (isError(capabilityResult)) {
- this.messageCollector.addOneliner(this.description, renderFailedSingularConsequence(this.description, capabilityResult.error))
+ this.messageCollector.addOneliner(this.description, renderFailedSingularConsequence(this.description, title, capabilityResult.error))
return capabilityResult;
}
- this.messageCollector.addOneliner(this.description, Redacting {Permalinks.forEvent(roomID, eventID)}.)
+ this.messageCollector.addOneliner(this.description, title)
return capabilityResult;
}
}
diff --git a/src/capabilities/StandardUserConsequencesRenderer.tsx b/src/capabilities/StandardUserConsequencesRenderer.tsx
index c1e62e4e..4e8732db 100644
--- a/src/capabilities/StandardUserConsequencesRenderer.tsx
+++ b/src/capabilities/StandardUserConsequencesRenderer.tsx
@@ -9,14 +9,14 @@
//
import { JSXFactory } from "../commands/interface-manager/JSXFactory";
-import { ActionResult, Capability, DescriptionMeta, Ok, Permalinks, PolicyListRevision, ResultForUserInSetMap, StandardUserConsequencesContext, StringRoomID, StringUserID, UserConsequences, describeCapabilityContextGlue, describeCapabilityRenderer, isError } from "matrix-protection-suite";
+import { ActionResult, Capability, DescriptionMeta, Ok, Permalinks, PolicyListRevision, ResultForUsersInSet, RoomSetResult, StandardUserConsequencesContext, StringRoomID, StringUserID, UserConsequences, describeCapabilityContextGlue, describeCapabilityRenderer, isError } from "matrix-protection-suite";
import { RendererMessageCollector } from "./RendererMessageCollector";
-import { renderFailedSingularConsequence, renderRoomSetResult } from "./CommonRenderers";
+import { renderFailedSingularConsequence, renderOutcome, renderRoomSetResult } from "./CommonRenderers";
import { DocumentNode } from "../commands/interface-manager/DeadDocument";
import { Draupnir } from "../Draupnir";
// yeah i know this is a bit insane but whatever, it can be our secret.
-function renderResultForUserInSetMap(usersInSetMap: ResultForUserInSetMap, {
+function renderResultForUserInSetMap(usersInSetMap: ResultForUsersInSet, {
ingword,
nnedword,
description
@@ -26,13 +26,34 @@ function renderResultForUserInSetMap(usersInSetMap: ResultForUserInSetMap, {
description: DescriptionMeta,
}): DocumentNode {
return
- {description.name}
: {ingword} {usersInSetMap.size} {usersInSetMap.size === 1 ? 'user' : 'users'} from protected rooms.
- {[...usersInSetMap.entries()].map(([userID, roomResults]) => {
- return renderRoomSetResult(roomResults, { summary: {userID} will be {nnedword} from {roomResults.map.size} rooms. })
- })}
+
+ {description.name}
: {ingword} {usersInSetMap.map.size}
+ {usersInSetMap.map.size === 1 ? 'user' : 'users'} from protected rooms -
+ {renderOutcome(usersInSetMap.isEveryResultOk)}.
+
+ {[...usersInSetMap.map.entries()].map(([userID, roomResults]) =>
+ renderRoomSetResultForUser(roomResults, userID, nnedword, {}))}
}
+function renderRoomSetResultForUser(
+ roomResults: RoomSetResult,
+ userID: StringUserID,
+ nnedword: string,
+ { description }: { description?: DescriptionMeta }
+): DocumentNode {
+ return renderRoomSetResult(
+ roomResults,
+ {
+ summary:
+ {description === undefined ? '' : {description.name}
:}
+ {userID} will be {nnedword} from {roomResults.map.size} rooms -
+ {renderOutcome(roomResults.isEveryResultOk)}.
+
+ }
+ )
+}
+
class StandardUserConsequencesRenderer implements UserConsequences {
constructor(
@@ -47,24 +68,26 @@ class StandardUserConsequencesRenderer implements UserConsequences {
public async consequenceForUserInRoom(roomID: StringRoomID, userID: StringUserID, reason: string): Promise> {
const capabilityResult = await this.capability.consequenceForUserInRoom(roomID, userID, reason);
+ const title =
+ Banning user {userID} in {Permalinks.forRoom(roomID)} for {reason}.
+ ;
if (isError(capabilityResult)) {
- this.messageCollector.addMessage(this.description, renderFailedSingularConsequence(this.description, capabilityResult.error))
+ this.messageCollector.addMessage(this.description, renderFailedSingularConsequence(this.description, title, capabilityResult.error))
return capabilityResult;
}
- this.messageCollector.addOneliner(this.description,
- Banning user {userID} in {Permalinks.forRoom(roomID)} for {reason}.
- )
+ this.messageCollector.addOneliner(this.description, title)
return Ok(undefined);
}
- public async consequenceForUserInRoomSet(revision: PolicyListRevision): Promise> {
+ public async consequenceForUserInRoomSet(revision: PolicyListRevision): Promise> {
const capabilityResult = await this.capability.consequenceForUserInRoomSet(revision);
if (isError(capabilityResult)) {
- this.messageCollector.addMessage(this.description, renderFailedSingularConsequence(this.description, capabilityResult.error))
+ const title = Applying policy revision to protected rooms
+ this.messageCollector.addMessage(this.description, renderFailedSingularConsequence(this.description, title, capabilityResult.error))
return capabilityResult;
}
const usersInSetMap = capabilityResult.ok;
- if (usersInSetMap.size === 0) {
+ if (usersInSetMap.map.size === 0) {
return capabilityResult;
}
this.messageCollector.addMessage(this.description, renderResultForUserInSetMap(usersInSetMap, {
@@ -75,21 +98,23 @@ class StandardUserConsequencesRenderer implements UserConsequences {
return capabilityResult;
}
- public async unbanUserFromRoomSet(userID: StringUserID, reason: string): Promise> {
+ public async unbanUserFromRoomSet(userID: StringUserID, reason: string): Promise> {
const capabilityResult = await this.capability.unbanUserFromRoomSet(userID, reason);
if (isError(capabilityResult)) {
- this.messageCollector.addMessage(this.description, renderFailedSingularConsequence(this.description, capabilityResult.error))
+ const title = Unbanning {userID} from protected rooms
+ this.messageCollector.addMessage(this.description, renderFailedSingularConsequence(this.description, title, capabilityResult.error))
return capabilityResult;
}
const usersInSetMap = capabilityResult.ok;
- if (usersInSetMap.size === 0) {
+ if (usersInSetMap.map.size === 0) {
return capabilityResult;
}
- this.messageCollector.addMessage(this.description, renderResultForUserInSetMap(usersInSetMap, {
- ingword: 'Unbanning',
- nnedword: 'unbanned',
- description: this.description,
- }));
+ this.messageCollector.addMessage(this.description, renderRoomSetResultForUser(
+ usersInSetMap,
+ userID,
+ 'unbanned',
+ { description: this.description },
+ ));
return capabilityResult;
}
diff --git a/src/commands/interface-manager/DeadDocumentHtml.ts b/src/commands/interface-manager/DeadDocumentHtml.ts
index 5f5a13fc..1f840c45 100644
--- a/src/commands/interface-manager/DeadDocumentHtml.ts
+++ b/src/commands/interface-manager/DeadDocumentHtml.ts
@@ -84,5 +84,5 @@ HTML_RENDERER.registerRenderer'),
staticString('')
).registerInnerNode(NodeTag.Span,
- staticString(''),
+ attributableNode('span'),
staticString(''));
diff --git a/yarn.lock b/yarn.lock
index dba5e1fb..f8bce5e4 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2505,15 +2505,15 @@ matrix-appservice@^2.0.0:
request-promise "^4.2.6"
sanitize-html "^2.8.0"
-"matrix-protection-suite-for-matrix-bot-sdk@npm:@gnuxie/matrix-protection-suite-for-matrix-bot-sdk@0.17.1":
- version "0.17.1"
- resolved "https://registry.yarnpkg.com/@gnuxie/matrix-protection-suite-for-matrix-bot-sdk/-/matrix-protection-suite-for-matrix-bot-sdk-0.17.1.tgz#925363e0282879156c9f9b7673a8e6acd78e1a71"
- integrity sha512-8vIu51ZLlVDUqRgz6K7bQMSjp/DEY+q1AO2mqvO/cSnHly/XKaflszwxN9zySAj6JjFXgPt+z1WkqV5omWE9NA==
-
-"matrix-protection-suite@npm:@gnuxie/matrix-protection-suite@0.17.1":
- version "0.17.1"
- resolved "https://registry.yarnpkg.com/@gnuxie/matrix-protection-suite/-/matrix-protection-suite-0.17.1.tgz#7c4330a029461652d61d89ba5461c99324cfc3a1"
- integrity sha512-3p9OqHf1JKymD1igceA5qy008Bqf9hSXC6mhPlLPqL7JGLFyE5FHa3eJcJJorZAfq54TH+KVmgpL0Es+E/wxfQ==
+"matrix-protection-suite-for-matrix-bot-sdk@npm:@gnuxie/matrix-protection-suite-for-matrix-bot-sdk@0.18.0":
+ version "0.18.0"
+ resolved "https://registry.yarnpkg.com/@gnuxie/matrix-protection-suite-for-matrix-bot-sdk/-/matrix-protection-suite-for-matrix-bot-sdk-0.18.0.tgz#b08994638fad6d0f668d405f8bcd2760c641a569"
+ integrity sha512-Py6KNAYE0DZ/68xBEBdQVXOfyjUgHLS93vxoV+91d9sMyUuvfUmmjxvaPOzOUHoOeB6GLGAIc3lWkr3opU+upQ==
+
+"matrix-protection-suite@npm:@gnuxie/matrix-protection-suite@0.18.0":
+ version "0.18.0"
+ resolved "https://registry.yarnpkg.com/@gnuxie/matrix-protection-suite/-/matrix-protection-suite-0.18.0.tgz#68f7898974f7a60530926c4af83999680b95706b"
+ integrity sha512-3tCKGatmMkyKOfbnG+VSYqs59F2S2ttuptlMC6XpmAFfaSVuR2v7ThAXp3OCVAKUykG3EY+8ypnhmtsV0JuMsQ==
dependencies:
await-lock "^2.2.2"
crypto-js "^4.1.1"