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"