commit 96c43309f1969a5e5e8bf458f233dabf0aa6fd12
parent 5661c8cdd07cb4237050e743e6a7453f8500d09b
Author: MTRNord <mtrnord1@gmail.com>
Date: Tue, 22 Feb 2022 21:06:13 +0100
Add some form validation and move correct files in the correct folders
Diffstat:
7 files changed, 314 insertions(+), 296 deletions(-)
diff --git a/src/components/App.tsx b/src/components/App.tsx
@@ -1,5 +1,5 @@
import { PureComponent } from 'react';
-import BanList from './forms/Banlist';
+import BanList from './Banlist';
import Home from './Home';
type Pages = "banlist" | "home";
diff --git a/src/components/BanForm.tsx b/src/components/BanForm.tsx
@@ -1,132 +0,0 @@
-import { PureComponent } from "react";
-import {
- CanonicalAliasEvent,
- CANONICAL_ALIAS,
- M_POLICY_RULE_SERVER,
- M_POLICY_RULE_SERVER_ALT,
- M_POLICY_RULE_SERVER_OLD,
- M_POLICY_RULE_USER,
- M_POLICY_RULE_USER_ALT,
- M_POLICY_RULE_USER_OLD,
- ORG_MATRIX_MJOLNIR_SHORTCODE,
- ServerRuleEvent,
- ShortcodeEvent,
- UserRuleEvent
-} from "../windowExt";
-
-type Props = Record<string, unknown>;
-type State = {
- glob: string;
- reason: string;
- roomId?: string;
- aliases_shortcodes: Map<string, string>;
- banlist?: string;
- bantype?: "user" | "server";
-};
-
-class BanForm extends PureComponent<Props, State> {
- constructor(props: Props | Readonly<Props>) {
- super(props);
- const urlParams = (new URL(window.location.href)).searchParams;
- const roomId = urlParams.get("room_id") ?? undefined;
- this.state = {
- glob: "",
- reason: "",
- roomId: roomId,
- aliases_shortcodes: new Map()
- };
- }
-
- async componentDidMount() {
- const user_rules = await window.widget_api.readStateEvents(M_POLICY_RULE_USER, 250_000_000_000, undefined, ["*"]) as UserRuleEvent[];
- const server_rules = await window.widget_api.readStateEvents(M_POLICY_RULE_SERVER, 250_000_000_000, undefined, ["*"]) as ServerRuleEvent[];
- const user_rules_old = await window.widget_api.readStateEvents(M_POLICY_RULE_USER_OLD, 250_000_000_000, undefined, ["*"]) as UserRuleEvent[];
- const server_rules_old = await window.widget_api.readStateEvents(M_POLICY_RULE_SERVER_OLD, 250_000_000_000, undefined, ["*"]) as ServerRuleEvent[];
- const user_rules_alt = await window.widget_api.readStateEvents(M_POLICY_RULE_USER_ALT, 250_000_000_000, undefined, ["*"]) as UserRuleEvent[];
- const server_rules_alt = await window.widget_api.readStateEvents(M_POLICY_RULE_SERVER_ALT, 250_000_000_000, undefined, ["*"]) as ServerRuleEvent[];
- const user_rules_all = [...user_rules, ...user_rules_old, ...user_rules_alt];
- const server_rules_all = [...server_rules, ...server_rules_old, ...server_rules_alt];
- const listrooms = [...new Set([...user_rules_all.map(element => element.room_id), ...server_rules_all.map(element => element.room_id)])];
- const aliases = await window.widget_api.readStateEvents(CANONICAL_ALIAS, listrooms.length, undefined, listrooms) as CanonicalAliasEvent[];
- const shortcodes = await window.widget_api.readStateEvents(ORG_MATRIX_MJOLNIR_SHORTCODE, listrooms.length, undefined, listrooms) as ShortcodeEvent[];
- const aliases_shortcodes = new Map();
-
- for (const event of aliases) {
- if (event.content?.alias) {
- aliases_shortcodes.set(event.content?.alias, shortcodes.find(shortcode_event => shortcode_event.room_id === event.room_id)?.content?.shortcode);
- }
- }
-
- this.setState({
- aliases_shortcodes
- });
- }
-
- handleInputChange(event: { target: { type: string, checked?: boolean, value: string | boolean, name: string; }; }) {
- const target = event.target;
- const value = target.type === 'checkbox' ? target.checked : target.value;
- const name = target.name;
- this.setState({
- [name]: value
- } as unknown as State);
- }
-
- async handleSubmit(ev: { preventDefault: () => void; }) {
- ev.preventDefault();
- await window.widget_api.sendRoomEvent("m.room.message", {
- msgtype: "m.text",
- body: `!mjolnir ban ${this.state.banlist} ${this.state.bantype} ${this.state.glob} ${this.state.reason}`,
- }, this.state.roomId);
- }
-
- render() {
- const { glob, banlist, aliases_shortcodes, bantype, reason } = this.state;
- return (
- <>
- <h3 className="text-2xl font-bold text-gray-900 dark:text-gray-200 mb-2">Ban</h3>
- <form onSubmit={this.handleSubmit.bind(this)} className="grid grid-cols-1 gap-4">
- <label className="inner-flex flex-col">
- <span className="text-gray-900 dark:text-gray-200 visually-hidden mb-2">Bantype</span>
- <h4 className="text-gray-900 dark:text-gray-200 text-base font-thin mb-2 w-96 italic">(Warning: This doesn't check if the banlist can be written to or the bot if watches it)</h4>
- <div className="w-96">
- <select required name="banlist" value={banlist ?? ""} className="max-w-full min-w-full placeholder:text-gray-900 text-gray-900 rounded py-1.5 px-2" onChange={this.handleInputChange.bind(this)}>
- <option value="" disabled>Select an Banlist</option>
- {
- [...aliases_shortcodes].map(([alias, shortcode]) => {
- return <option key={alias} value={shortcode}>{alias}</option>;
- })
- }
- </select>
- </div>
- </label>
- <label className="inner-flex flex-col w-96">
- <span className="text-gray-900 dark:text-gray-200 visually-hidden mb-2">Bantype</span>
- <div className="w-96">
- <select defaultValue="" required name="bantype" value={bantype ?? ""} className="max-w-full min-w-full placeholder:text-gray-900 text-gray-900 rounded py-1.5 px-2" onChange={this.handleInputChange.bind(this)}>
- <option value="" disabled>Select an Bantype</option>
- <option value="user">User</option>
- <option value="server">Server</option>
- </select>
- </div>
- </label>
- <label className="block w-96">
- <span className="text-gray-900 dark:text-gray-200 visually-hidden mb-2">Glob</span>
- <div className="mt-1 w-full flex flex-row box-border items-center cursor-text duration-300 max-w-full">
- <input placeholder="Glob" className="rounded py-1.5 px-2 min-w-[1.25rem] flex-[1] border-none placeholder:text-gray-900 text-gray-900" type="text" name="glob" value={glob} onChange={this.handleInputChange.bind(this)} />
- </div>
- </label>
- <label className="block w-96">
- <span className="text-gray-900 dark:text-gray-200 visually-hidden mb-2">Reason</span>
- <div className="mt-1 w-full flex flex-row box-border items-center cursor-text duration-300 max-w-full">
- <input placeholder="Reason" className="rounded py-1.5 px-2 min-w-[1.25rem] flex-[1] border-none placeholder:text-gray-900 text-gray-900" type="text" name="reason" value={reason} onChange={this.handleInputChange.bind(this)} />
- </div>
- </label>
-
- <input className="bg-red-400 hover:bg-red-500 cursor-pointer h-10 rounded dark:text-gray-900 text-gray-200 w-96" type="submit" value="Ban" />
- </form>
- </>
- );
- }
-}
-
-export default BanForm;
-\ No newline at end of file
diff --git a/src/components/Banlist.tsx b/src/components/Banlist.tsx
@@ -0,0 +1,156 @@
+import { PureComponent } from 'react';
+import {
+ MembershipEvent,
+ M_POLICY_RULE_SERVER,
+ M_POLICY_RULE_SERVER_ALT,
+ M_POLICY_RULE_SERVER_OLD,
+ M_POLICY_RULE_USER,
+ M_POLICY_RULE_USER_ALT,
+ M_POLICY_RULE_USER_OLD,
+ ServerRuleEvent,
+ UserRuleEvent
+} from '../windowExt';
+
+type Props = Record<string, unknown>;
+type State = {
+ user_rules: UserRuleEvent[];
+ server_rules: ServerRuleEvent[];
+ roomId?: string;
+ filter?: string;
+ memberships: MembershipEvent[];
+};
+
+class BanList extends PureComponent<Props, State> {
+ constructor(props: Props) {
+ super(props);
+ const urlParams = (new URL(window.location.href)).searchParams;
+ const roomId = urlParams.get("room_id") ?? undefined;
+ this.state = {
+ roomId: roomId,
+ user_rules: [],
+ server_rules: [],
+ memberships: []
+ };
+ }
+
+ async componentDidMount() {
+ const user_rules = await window.widget_api.readStateEvents(M_POLICY_RULE_USER, 250_000_000_000, undefined, ["*"]) as UserRuleEvent[];
+ const server_rules = await window.widget_api.readStateEvents(M_POLICY_RULE_SERVER, 250_000_000_000, undefined, ["*"]) as ServerRuleEvent[];
+ const user_rules_old = await window.widget_api.readStateEvents(M_POLICY_RULE_USER_OLD, 250_000_000_000, undefined, ["*"]) as UserRuleEvent[];
+ const server_rules_old = await window.widget_api.readStateEvents(M_POLICY_RULE_SERVER_OLD, 250_000_000_000, undefined, ["*"]) as ServerRuleEvent[];
+ const user_rules_alt = await window.widget_api.readStateEvents(M_POLICY_RULE_USER_ALT, 250_000_000_000, undefined, ["*"]) as UserRuleEvent[];
+ const server_rules_alt = await window.widget_api.readStateEvents(M_POLICY_RULE_SERVER_ALT, 250_000_000_000, undefined, ["*"]) as ServerRuleEvent[];
+ const user_rules_all = [...user_rules, ...user_rules_old, ...user_rules_alt];
+ const server_rules_all = [...server_rules, ...server_rules_old, ...server_rules_alt];
+ const list_rooms = [...new Set([...user_rules_all.map(element => element.room_id), ...server_rules_all.map(element => element.room_id)])];
+ const sender = new Set([...user_rules_all.map(element => element.sender), ...server_rules_all.map(element => element.sender)]);
+ const memberships = await window.widget_api.readStateEvents("m.room.member", 250_000_000_000, undefined, list_rooms) as MembershipEvent[];
+ const memberships_needed = memberships.filter(member => sender.has(member.state_key));
+
+ this.setState({
+ user_rules: user_rules_all,
+ server_rules: server_rules_all,
+ memberships: memberships_needed
+ });
+ }
+
+ onSearch(ev: { target: { value: string; }; }) {
+ this.setState({
+ filter: ev.target.value
+ });
+ }
+
+ render() {
+ const { user_rules, server_rules, filter, memberships } = this.state;
+ const filtered_user_rules = filter ? user_rules.filter(element => element.content && Object.keys(element.content).length > 0 && element.content?.entity.includes(filter)) : user_rules;
+ const filtered_server_rules = filter ? server_rules.filter(element => element.content && Object.keys(element.content).length > 0 && element.content?.entity.includes(filter)) : server_rules;
+ return (
+ <main className="m-8 flex items-center flex-col justify-center">
+ <div className='flex flex-row justify-between content-between w-full'>
+ <h1 className="text-3xl font-bold underline text-gray-900 dark:text-gray-200 mb-4">Banlist data</h1>
+ <input onChange={this.onSearch.bind(this)} value={filter} placeholder="Search for user or server" className='py-1.5 px-2 rounded border-none placeholder:text-gray-900 text-gray-9000'></input>
+ </div>
+ <div className='flex flex-row justify-between content-between w-full'>
+ <section className='mr-2'>
+ <h3 className="text-2xl font-bold text-gray-900 dark:text-gray-200 mb-2">User Bans ({user_rules.length})</h3>
+ <table className='table-auto border-collapse border-2 border-slate-500 text-gray-900 dark:text-gray-200 text-base font-normal break-words'>
+ <thead>
+ <tr>
+ <th className='border-2 border-slate-600 p-1'>Entity</th>
+ <th className='border-2 border-slate-600 p-1'>Recommendation</th>
+ <th className='border-2 border-slate-600 p-1'>Reason</th>
+ <th className='border-2 border-slate-600 p-1'>Sender</th>
+ </tr>
+ </thead>
+ <tbody>
+ {
+ filtered_user_rules.length > 0 ?
+ filtered_user_rules.map(element => {
+ if (element.content && Object.keys(element.content).length > 0) {
+ const recommendation = element.content.recommendation === "m.ban" || element.content.recommendation === "org.matrix.mjolnir.ban" ? "Ban" : element.content.recommendation;
+
+ // Entity is intentionally left as a mxid
+ const sender_dp = memberships.find(membership => membership.state_key === element.sender)?.content?.displayname ?? element.sender;
+ return (
+ <tr key={`${element.event_id}`} className='border-2 border-slate-600'>
+ <td className='p-1 min-w-[8rem] max-w-[14rem]'>{element.content.entity}</td>
+ <td className='p-1 min-w-[1rem] max-w-[14rem]'>{recommendation}</td>
+ <td className='p-1 min-w-[8rem] max-w-[14rem]'>{element.content.reason}</td>
+ <td className='p-1 min-w-[12rem] max-w-[14rem]'>{sender_dp}</td>
+ </tr>
+ );
+ }
+ }) : (
+ <tr className='border-2 border-slate-600'>
+ <td className='p-1'>No user ban found</td>
+ </tr>
+ )
+ }
+ </tbody>
+ </table>
+ </section>
+ <section>
+ <h3 className="text-2xl font-bold text-gray-900 dark:text-gray-200 mb-2">Server Bans ({server_rules.length})</h3>
+ <table className='table-auto border-collapse border-2 border-slate-500 text-gray-900 dark:text-gray-200 text-base font-normal break-words'>
+ <thead>
+ <tr>
+ <th className='border-2 border-slate-600 p-2'>Entity</th>
+ <th className='border-2 border-slate-600 p-2'>Recommendation</th>
+ <th className='border-2 border-slate-600 p-2'>Reason</th>
+ <th className='border-2 border-slate-600 p-1'>Sender</th>
+ </tr>
+ </thead>
+ <tbody>
+ {
+ filtered_server_rules.length > 0 ?
+ filtered_server_rules.map(element => {
+ if (element.content && Object.keys(element.content).length > 0) {
+ const recommendation = element.content.recommendation === "m.ban" || element.content.recommendation === "org.matrix.mjolnir.ban" ? "Ban" : element.content.recommendation;
+
+ // Entity is intentionally left as a mxid
+ const sender_dp = memberships.find(membership => membership.state_key === element.sender)?.content?.displayname ?? element.sender;
+ return (
+ <tr key={`${element.event_id}`} className='border-2 border-slate-600'>
+ <td className='p-1 min-w-[8rem] max-w-[14rem]'>{element.content.entity}</td>
+ <td className='p-1 min-w-[1rem] max-w-[14rem]'>{recommendation}</td>
+ <td className='p-1 min-w-[8rem] max-w-[14rem]'>{element.content.reason}</td>
+ <td className='p-1 min-w-[12rem] max-w-[14rem]'>{sender_dp}</td>
+ </tr>
+ );
+ }
+ }) : (
+ <tr className='border-2 border-slate-600'>
+ <td className='p-1'>No server ban found</td>
+ </tr>
+ )
+ }
+ </tbody>
+ </table>
+ </section>
+ </div>
+ </main>
+ );
+ }
+}
+
+export default BanList;
+\ No newline at end of file
diff --git a/src/components/Home.tsx b/src/components/Home.tsx
@@ -1,5 +1,5 @@
import { PureComponent } from 'react';
-import BanForm from './BanForm';
+import BanForm from './forms/BanForm';
import RedactForm from './forms/RedactForm';
type Props = Record<string, unknown>;
diff --git a/src/components/forms/BanForm.tsx b/src/components/forms/BanForm.tsx
@@ -0,0 +1,149 @@
+import { PureComponent } from "react";
+import {
+ CanonicalAliasEvent,
+ CANONICAL_ALIAS,
+ M_POLICY_RULE_SERVER,
+ M_POLICY_RULE_SERVER_ALT,
+ M_POLICY_RULE_SERVER_OLD,
+ M_POLICY_RULE_USER,
+ M_POLICY_RULE_USER_ALT,
+ M_POLICY_RULE_USER_OLD,
+ ORG_MATRIX_MJOLNIR_SHORTCODE,
+ ServerRuleEvent,
+ ShortcodeEvent,
+ UserRuleEvent
+} from "../../windowExt";
+
+type Props = Record<string, unknown>;
+type State = {
+ glob: string;
+ reason: string;
+ roomId?: string;
+ aliases_shortcodes: Map<string, string>;
+ banlist: string;
+ bantype: "user" | "server" | "";
+};
+
+class BanForm extends PureComponent<Props, State> {
+ constructor(props: Props | Readonly<Props>) {
+ super(props);
+ const urlParams = (new URL(window.location.href)).searchParams;
+ const roomId = urlParams.get("room_id") ?? undefined;
+ this.state = {
+ glob: "",
+ reason: "",
+ roomId: roomId,
+ banlist: "",
+ bantype: "",
+ aliases_shortcodes: new Map()
+ };
+ }
+
+ async componentDidMount() {
+ const user_rules = await window.widget_api.readStateEvents(M_POLICY_RULE_USER, 250_000_000_000, undefined, ["*"]) as UserRuleEvent[];
+ const server_rules = await window.widget_api.readStateEvents(M_POLICY_RULE_SERVER, 250_000_000_000, undefined, ["*"]) as ServerRuleEvent[];
+ const user_rules_old = await window.widget_api.readStateEvents(M_POLICY_RULE_USER_OLD, 250_000_000_000, undefined, ["*"]) as UserRuleEvent[];
+ const server_rules_old = await window.widget_api.readStateEvents(M_POLICY_RULE_SERVER_OLD, 250_000_000_000, undefined, ["*"]) as ServerRuleEvent[];
+ const user_rules_alt = await window.widget_api.readStateEvents(M_POLICY_RULE_USER_ALT, 250_000_000_000, undefined, ["*"]) as UserRuleEvent[];
+ const server_rules_alt = await window.widget_api.readStateEvents(M_POLICY_RULE_SERVER_ALT, 250_000_000_000, undefined, ["*"]) as ServerRuleEvent[];
+ const user_rules_all = [...user_rules, ...user_rules_old, ...user_rules_alt];
+ const server_rules_all = [...server_rules, ...server_rules_old, ...server_rules_alt];
+ const listrooms = [...new Set([...user_rules_all.map(element => element.room_id), ...server_rules_all.map(element => element.room_id)])];
+ const aliases = await window.widget_api.readStateEvents(CANONICAL_ALIAS, listrooms.length, undefined, listrooms) as CanonicalAliasEvent[];
+ const shortcodes = await window.widget_api.readStateEvents(ORG_MATRIX_MJOLNIR_SHORTCODE, listrooms.length, undefined, listrooms) as ShortcodeEvent[];
+ const aliases_shortcodes = new Map();
+
+ for (const event of aliases) {
+ if (event.content?.alias) {
+ aliases_shortcodes.set(event.content?.alias, shortcodes.find(shortcode_event => shortcode_event.room_id === event.room_id)?.content?.shortcode);
+ }
+ }
+
+ this.setState({
+ aliases_shortcodes
+ });
+ }
+
+ handleInputChange(event: { target: { type: string, checked?: boolean, value: string | boolean, name: string; }; }) {
+ const target = event.target;
+ const value = target.type === 'checkbox' ? target.checked : target.value;
+ const name = target.name;
+ this.setState({
+ [name]: value
+ } as unknown as State);
+ }
+
+ async handleSubmit(ev: { preventDefault: () => void; }) {
+ ev.preventDefault();
+
+ const { glob, banlist, bantype, reason, roomId } = this.state;
+
+ if (glob === "" || banlist === "" || bantype === "") {
+ // TODO display warning
+ return;
+ } else {
+ if (reason === "") {
+ await window.widget_api.sendRoomEvent("m.room.message", {
+ msgtype: "m.text",
+ body: `!mjolnir ban ${banlist} ${bantype} ${glob}`,
+ }, roomId);
+ } else {
+ await window.widget_api.sendRoomEvent("m.room.message", {
+ msgtype: "m.text",
+ body: `!mjolnir ban ${banlist} ${bantype} ${glob} ${reason}`,
+ }, roomId);
+ }
+ }
+ }
+
+ render() {
+ const { glob, banlist, aliases_shortcodes, bantype, reason } = this.state;
+ return (
+ <>
+ <h3 className="text-2xl font-bold text-gray-900 dark:text-gray-200 mb-2">Ban</h3>
+ <form onSubmit={this.handleSubmit.bind(this)} className="grid grid-cols-1 gap-4">
+ <label className="inner-flex flex-col">
+ <span className="text-gray-900 dark:text-gray-200 visually-hidden mb-2">Banlist</span>
+ <h4 className="text-gray-900 dark:text-gray-200 text-base font-thin mb-2 w-96 italic">(Warning: This doesn't check if the banlist can be written to or the bot if watches it)</h4>
+ <div className="w-96">
+ <select required name="banlist" value={banlist} className="max-w-full min-w-full placeholder:text-gray-900 text-gray-900 rounded py-1.5 px-2" onChange={this.handleInputChange.bind(this)}>
+ <option value="" disabled>Select an Banlist</option>
+ {
+ [...aliases_shortcodes].map(([alias, shortcode]) => {
+ return <option key={alias} value={shortcode}>{alias}</option>;
+ })
+ }
+ </select>
+ </div>
+ </label>
+ <label className="inner-flex flex-col w-96">
+ <span className="text-gray-900 dark:text-gray-200 visually-hidden mb-2">Bantype</span>
+ <div className="w-96">
+ <select required defaultValue="" name="bantype" value={bantype} className="max-w-full min-w-full placeholder:text-gray-900 text-gray-900 rounded py-1.5 px-2" onChange={this.handleInputChange.bind(this)}>
+ <option value="" disabled>Select an Bantype</option>
+ <option value="user">User</option>
+ <option value="server">Server</option>
+ </select>
+ </div>
+ </label>
+ <label className="block w-96">
+ <span className="text-gray-900 dark:text-gray-200 visually-hidden mb-2">Glob</span>
+ <div className="mt-1 w-full flex flex-row box-border items-center cursor-text duration-300 max-w-full">
+ <input required placeholder="Glob" className="rounded py-1.5 px-2 min-w-[1.25rem] flex-[1] border-none placeholder:text-gray-900 text-gray-900" type="text" name="glob" value={glob} onChange={this.handleInputChange.bind(this)} />
+ </div>
+ </label>
+ <label className="block w-96">
+ <span className="text-gray-900 dark:text-gray-200 visually-hidden mb-2">Reason</span>
+ <div className="mt-1 w-full flex flex-row box-border items-center cursor-text duration-300 max-w-full">
+ <input placeholder="Reason" className="rounded py-1.5 px-2 min-w-[1.25rem] flex-[1] border-none placeholder:text-gray-900 text-gray-900" type="text" name="reason" value={reason} onChange={this.handleInputChange.bind(this)} />
+ </div>
+ </label>
+
+ <input className="bg-red-400 hover:bg-red-500 cursor-pointer h-10 rounded dark:text-gray-900 text-gray-200 w-96" type="submit" value="Ban" />
+ </form>
+ </>
+ );
+ }
+}
+
+export default BanForm;
+\ No newline at end of file
diff --git a/src/components/forms/Banlist.tsx b/src/components/forms/Banlist.tsx
@@ -1,156 +0,0 @@
-import { PureComponent } from 'react';
-import {
- MembershipEvent,
- M_POLICY_RULE_SERVER,
- M_POLICY_RULE_SERVER_ALT,
- M_POLICY_RULE_SERVER_OLD,
- M_POLICY_RULE_USER,
- M_POLICY_RULE_USER_ALT,
- M_POLICY_RULE_USER_OLD,
- ServerRuleEvent,
- UserRuleEvent
-} from '../../windowExt';
-
-type Props = Record<string, unknown>;
-type State = {
- user_rules: UserRuleEvent[];
- server_rules: ServerRuleEvent[];
- roomId?: string;
- filter?: string;
- memberships: MembershipEvent[];
-};
-
-class BanList extends PureComponent<Props, State> {
- constructor(props: Props) {
- super(props);
- const urlParams = (new URL(window.location.href)).searchParams;
- const roomId = urlParams.get("room_id") ?? undefined;
- this.state = {
- roomId: roomId,
- user_rules: [],
- server_rules: [],
- memberships: []
- };
- }
-
- async componentDidMount() {
- const user_rules = await window.widget_api.readStateEvents(M_POLICY_RULE_USER, 250_000_000_000, undefined, ["*"]) as UserRuleEvent[];
- const server_rules = await window.widget_api.readStateEvents(M_POLICY_RULE_SERVER, 250_000_000_000, undefined, ["*"]) as ServerRuleEvent[];
- const user_rules_old = await window.widget_api.readStateEvents(M_POLICY_RULE_USER_OLD, 250_000_000_000, undefined, ["*"]) as UserRuleEvent[];
- const server_rules_old = await window.widget_api.readStateEvents(M_POLICY_RULE_SERVER_OLD, 250_000_000_000, undefined, ["*"]) as ServerRuleEvent[];
- const user_rules_alt = await window.widget_api.readStateEvents(M_POLICY_RULE_USER_ALT, 250_000_000_000, undefined, ["*"]) as UserRuleEvent[];
- const server_rules_alt = await window.widget_api.readStateEvents(M_POLICY_RULE_SERVER_ALT, 250_000_000_000, undefined, ["*"]) as ServerRuleEvent[];
- const user_rules_all = [...user_rules, ...user_rules_old, ...user_rules_alt];
- const server_rules_all = [...server_rules, ...server_rules_old, ...server_rules_alt];
- const list_rooms = [...new Set([...user_rules_all.map(element => element.room_id), ...server_rules_all.map(element => element.room_id)])];
- const sender = new Set([...user_rules_all.map(element => element.sender), ...server_rules_all.map(element => element.sender)]);
- const memberships = await window.widget_api.readStateEvents("m.room.member", 250_000_000_000, undefined, list_rooms) as MembershipEvent[];
- const memberships_needed = memberships.filter(member => sender.has(member.state_key));
-
- this.setState({
- user_rules: user_rules_all,
- server_rules: server_rules_all,
- memberships: memberships_needed
- });
- }
-
- onSearch(ev: { target: { value: string; }; }) {
- this.setState({
- filter: ev.target.value
- });
- }
-
- render() {
- const { user_rules, server_rules, filter, memberships } = this.state;
- const filtered_user_rules = filter ? user_rules.filter(element => element.content && Object.keys(element.content).length > 0 && element.content?.entity.includes(filter)) : user_rules;
- const filtered_server_rules = filter ? server_rules.filter(element => element.content && Object.keys(element.content).length > 0 && element.content?.entity.includes(filter)) : server_rules;
- return (
- <main className="m-8 flex items-center flex-col justify-center">
- <div className='flex flex-row justify-between content-between w-full'>
- <h1 className="text-3xl font-bold underline text-gray-900 dark:text-gray-200 mb-4">Banlist data</h1>
- <input onChange={this.onSearch.bind(this)} value={filter} placeholder="Search for user or server" className='py-1.5 px-2 rounded border-none placeholder:text-gray-900 text-gray-9000'></input>
- </div>
- <div className='flex flex-row justify-between content-between w-full'>
- <section className='mr-2'>
- <h3 className="text-2xl font-bold text-gray-900 dark:text-gray-200 mb-2">User Bans ({user_rules.length})</h3>
- <table className='table-auto border-collapse border-2 border-slate-500 text-gray-900 dark:text-gray-200 text-base font-normal break-words'>
- <thead>
- <tr>
- <th className='border-2 border-slate-600 p-1'>Entity</th>
- <th className='border-2 border-slate-600 p-1'>Recommendation</th>
- <th className='border-2 border-slate-600 p-1'>Reason</th>
- <th className='border-2 border-slate-600 p-1'>Sender</th>
- </tr>
- </thead>
- <tbody>
- {
- filtered_user_rules.length > 0 ?
- filtered_user_rules.map(element => {
- if (element.content && Object.keys(element.content).length > 0) {
- const recommendation = element.content.recommendation === "m.ban" || element.content.recommendation === "org.matrix.mjolnir.ban" ? "Ban" : element.content.recommendation;
-
- // Entity is intentionally left as a mxid
- const sender_dp = memberships.find(membership => membership.state_key === element.sender)?.content?.displayname ?? element.sender;
- return (
- <tr key={`${element.event_id}`} className='border-2 border-slate-600'>
- <td className='p-1 min-w-[8rem] max-w-[14rem]'>{element.content.entity}</td>
- <td className='p-1 min-w-[1rem] max-w-[14rem]'>{recommendation}</td>
- <td className='p-1 min-w-[8rem] max-w-[14rem]'>{element.content.reason}</td>
- <td className='p-1 min-w-[12rem] max-w-[14rem]'>{sender_dp}</td>
- </tr>
- );
- }
- }) : (
- <tr className='border-2 border-slate-600'>
- <td className='p-1'>No user ban found</td>
- </tr>
- )
- }
- </tbody>
- </table>
- </section>
- <section>
- <h3 className="text-2xl font-bold text-gray-900 dark:text-gray-200 mb-2">Server Bans ({server_rules.length})</h3>
- <table className='table-auto border-collapse border-2 border-slate-500 text-gray-900 dark:text-gray-200 text-base font-normal break-words'>
- <thead>
- <tr>
- <th className='border-2 border-slate-600 p-2'>Entity</th>
- <th className='border-2 border-slate-600 p-2'>Recommendation</th>
- <th className='border-2 border-slate-600 p-2'>Reason</th>
- <th className='border-2 border-slate-600 p-1'>Sender</th>
- </tr>
- </thead>
- <tbody>
- {
- filtered_server_rules.length > 0 ?
- filtered_server_rules.map(element => {
- if (element.content && Object.keys(element.content).length > 0) {
- const recommendation = element.content.recommendation === "m.ban" || element.content.recommendation === "org.matrix.mjolnir.ban" ? "Ban" : element.content.recommendation;
-
- // Entity is intentionally left as a mxid
- const sender_dp = memberships.find(membership => membership.state_key === element.sender)?.content?.displayname ?? element.sender;
- return (
- <tr key={`${element.event_id}`} className='border-2 border-slate-600'>
- <td className='p-1 min-w-[8rem] max-w-[14rem]'>{element.content.entity}</td>
- <td className='p-1 min-w-[1rem] max-w-[14rem]'>{recommendation}</td>
- <td className='p-1 min-w-[8rem] max-w-[14rem]'>{element.content.reason}</td>
- <td className='p-1 min-w-[12rem] max-w-[14rem]'>{sender_dp}</td>
- </tr>
- );
- }
- }) : (
- <tr className='border-2 border-slate-600'>
- <td className='p-1'>No server ban found</td>
- </tr>
- )
- }
- </tbody>
- </table>
- </section>
- </div>
- </main>
- );
- }
-}
-
-export default BanList;
-\ No newline at end of file
diff --git a/src/components/forms/RedactForm.tsx b/src/components/forms/RedactForm.tsx
@@ -32,6 +32,7 @@ class RedactForm extends PureComponent<Props, State> {
async handleSubmit(ev: { preventDefault: () => void; }) {
ev.preventDefault();
+
let command = "";
if (this.state.event !== "" && this.state.user === "" && this.state.room === "" && this.state.limit === "") {
command = `!mjolnir redact ${this.state.event}`;
@@ -63,26 +64,26 @@ class RedactForm extends PureComponent<Props, State> {
<label className="block w-96">
<span className="text-gray-900 dark:text-gray-200 visually-hidden mb-2">User ID (required if Event Permalink empty)</span>
<div className="mt-1 w-full flex flex-row box-border items-center cursor-text duration-300 max-w-full">
- <input placeholder="User ID (required if Permalink empty)" className="rounded py-1.5 px-2 min-w-[1.25rem] flex-[1] border-none placeholder:text-gray-900 text-gray-900" type="text" name="user" value={user} onChange={this.handleInputChange.bind(this)} />
+ <input disabled={event !== ""} required={event === ""} placeholder="User ID (required if Permalink empty)" className="rounded py-1.5 px-2 min-w-[1.25rem] flex-[1] border-none placeholder:text-gray-900 text-gray-900" type="text" name="user" value={user} onChange={this.handleInputChange.bind(this)} />
</div>
</label>
<label className="block w-96">
<span className="text-gray-900 dark:text-gray-200 visually-hidden mb-2">Room (optional)</span>
<div className="mt-1 w-full flex flex-row box-border items-center cursor-text duration-300 max-w-full">
- <input placeholder="Room (optional)" className="rounded py-1.5 px-2 min-w-[1.25rem] flex-[1] border-none placeholder:text-gray-900 text-gray-900" type="text" name="room" value={room} onChange={this.handleInputChange.bind(this)} />
+ <input disabled={event !== ""} placeholder="Room (optional)" className="rounded py-1.5 px-2 min-w-[1.25rem] flex-[1] border-none placeholder:text-gray-900 text-gray-900" type="text" name="room" value={room} onChange={this.handleInputChange.bind(this)} />
</div>
</label>
<label className="block w-96">
<span className="text-gray-900 dark:text-gray-200 visually-hidden mb-2">Limit (optional)</span>
<div className="mt-1 w-full flex flex-row box-border items-center cursor-text duration-300 max-w-full">
- <input placeholder="Limit (optional)" className="rounded py-1.5 px-2 min-w-[1.25rem] flex-[1] border-none placeholder:text-gray-900 text-gray-900" type="text" name="limit" value={limit} onChange={this.handleInputChange.bind(this)} />
+ <input disabled={event !== ""} placeholder="Limit (optional)" className="rounded py-1.5 px-2 min-w-[1.25rem] flex-[1] border-none placeholder:text-gray-900 text-gray-900" type="text" name="limit" value={limit} onChange={this.handleInputChange.bind(this)} />
</div>
</label>
<h4 className="text-gray-900 dark:text-gray-200 text-lg font-normal mb-1 w-96">Redacting an event</h4>
<label className="block w-96">
<span className="text-gray-900 dark:text-gray-200 visually-hidden mb-2">Event Permalink (required if User ID empty)</span>
<div className="mt-1 w-full flex flex-row box-border items-center cursor-text duration-300 max-w-full">
- <input placeholder="Event Permalink (required if User ID empty)" className="rounded py-1.5 px-2 min-w-[1.25rem] flex-[1] border-none placeholder:text-gray-900 text-gray-900" type="text" name="event" value={event} onChange={this.handleInputChange.bind(this)} />
+ <input disabled={user !== ""} required={user === ""} placeholder="Event Permalink (required if User ID empty)" className="rounded py-1.5 px-2 min-w-[1.25rem] flex-[1] border-none placeholder:text-gray-900 text-gray-900" type="text" name="event" value={event} onChange={this.handleInputChange.bind(this)} />
</div>
</label>