From ef7109e32113730da97ad339693a59e6363c4a79 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Wed, 19 Feb 2025 19:52:50 -0500 Subject: [PATCH] replace instance and software groups with ban group --- relay/cli/__init__.py | 1 + relay/cli/ban.py | 186 ++++++++++++++++++++++++++++++++++++++ relay/cli/instance_ban.py | 14 ++- relay/cli/software_ban.py | 14 ++- 4 files changed, 213 insertions(+), 2 deletions(-) create mode 100644 relay/cli/ban.py diff --git a/relay/cli/__init__.py b/relay/cli/__init__.py index b3bcab7..ba3aa68 100644 --- a/relay/cli/__init__.py +++ b/relay/cli/__init__.py @@ -58,6 +58,7 @@ def main() -> None: from . import ( # noqa: E402 + ban, base, config as config_cli, inbox, diff --git a/relay/cli/ban.py b/relay/cli/ban.py new file mode 100644 index 0000000..7a62da9 --- /dev/null +++ b/relay/cli/ban.py @@ -0,0 +1,186 @@ +import click + +from typing import Any + +from . import cli, pass_state + +from ..misc import RELAY_SOFTWARE +from ..state import State + + +@cli.group("ban") +def cli_ban() -> None: + "Mannaged banned domains and software" + + +@cli_ban.command("list") +@click.option("--only-instances", "-i", is_flag = True, help = "Only list the banned instances") +@click.option("--only-software", "-s", is_flag = True, help = "Only list the banned software") +@click.option("--expanded-format", "-e", is_flag = True, + help = "Add extra spacing for better readability") +@pass_state +def cli_ban_list( + state: State, + only_instances: bool, + only_software: bool, + expanded_format: bool) -> None: + "List all domain and/or software bans" + + if only_instances and only_software: + click.echo("Do not pass '--only-instances' AND '--only-software'") + return + + template = "- {name}: {reason}" + + if expanded_format: + template = "- {name}\n {reason}\n" + + with state.database.session(False) as conn: + if not only_software: + click.echo("Banned Domains:") + + for domain in conn.get_domain_bans(): + click.echo(template.format(name = domain.domain, reason = domain.reason or "n/a")) + + if not only_instances: + click.echo("\nBanned Software:") + + for software in conn.get_software_bans(): + click.echo(template.format(name = software.name, reason = software.reason or "n/a")) + + +@cli_ban.command("add") +@click.argument("name") +@click.option("--reason", help = "Publicly displayed reason for the ban") +@click.option("--note", help = "Node on the ban that can only be read by admins") +@click.option("--software", "-s", is_flag = True, + help = "Add a software ban instad of a domain ban") +@click.option("--fetch-nodeinfo", "-n", is_flag = True, + help = "Use 'name' as a domain to fetch nodeinfo when adding a software ban") +@pass_state +async def cli_ban_add( + state: State, + name: str, + reason: str | None, + note: str | None, + software: bool, + fetch_nodeinfo: bool) -> None: + "Create a new ban" + + with state.database.session(True) as conn: + ban: Any + + if software: + ban = conn.get_software_ban(name) + + else: + ban = conn.get_domain_ban(name) + + if ban: + click.echo(f"Domain or software already banned: {name}") + return + + if not software: + conn.put_domain_ban(name, reason, note) + click.echo("Banned domain") + return + + if fetch_nodeinfo: + async with state.client: + if not (nodeinfo := await state.client.fetch_nodeinfo(name)): + click.echo(f"Could not fetch nodeinfo for {repr(name)}") + return + + name = nodeinfo.sw_name + + print(name, reason, note) + conn.put_software_ban(name, reason, note) + + click.echo(f"Added domain or software ban: {name}") + + +@cli_ban.command("update") +@click.argument("name") +@click.option("--reason", help = "Publicly displayed reason for the ban") +@click.option("--note", help = "Node on the ban that can only be read by admins") +@click.option("--software", "-s", is_flag = True, + help = "Update a software ban instad of a domain ban") +@pass_state +def cli_ban_update( + state: State, + name: str, + reason: str | None, + note: str | None, + software: bool) -> None: + "Update the reason or note of a ban" + + with state.database.session(True) as conn: + if not software: + if not conn.get_domain_ban(name): + click.echo(f"Domain not banned: {name}") + return + + conn.update_domain_ban(name, reason, note) + + else: + if not conn.get_software_ban(name): + click.echo(f"Software not banned: {name}") + return + + conn.update_software_ban(name, reason, note) + + click.echo(f"Domain or software updated: {name}") + + +@cli_ban.command("remove") +@click.argument("name") +@click.option("--software", "-s", is_flag = True, + help = "Remove a software ban instad of a domain ban") +@click.option("--fetch-nodeinfo", "-n", is_flag = True, + help = "Use 'name' as a domain to fetch nodeinfo when adding a software ban") +@pass_state +async def cli_ban_remove( + state: State, + name: str, + software: bool, + fetch_nodeinfo: bool) -> None: + "Remove a ban" + + result: bool + + with state.database.session(True) as conn: + if not software: + result = conn.del_domain_ban(name) + + else: + if fetch_nodeinfo: + async with state.client: + if not (nodeinfo := await state.client.fetch_nodeinfo(name)): + click.echo(f"Could not fetch nodeinfo for {repr(name)}") + return + + name = nodeinfo.sw_name + + result = conn.del_software_ban(name) + + if result: + click.echo(f"Removed domain or software ban: {name}") + return + + click.echo(f"Domain or software ban does not exist: {name}") + + +@cli_ban.command("add-relays") +@click.option("--reason", help = "Publicly displayed reason for the ban") +@click.option("--note", help = "Node on the ban that can only be read by admins") +@pass_state +def cli_ban_add_relays(state: State, reason: str | None, note: str | None) -> None: + for name in RELAY_SOFTWARE: + cli_ban_add.callback(name, reason, note, True, False) # type: ignore[misc] + + +@cli_ban.command("remove-relays") +@pass_state +def cli_ban_remove_relays(state: State) -> None: + for name in RELAY_SOFTWARE: + cli_ban_remove.callback(name, True, False) # type: ignore[misc] diff --git a/relay/cli/instance_ban.py b/relay/cli/instance_ban.py index 64826f9..118d133 100644 --- a/relay/cli/instance_ban.py +++ b/relay/cli/instance_ban.py @@ -5,9 +5,14 @@ from . import cli, pass_state from ..state import State +# remove this in 0.4.0 @cli.group("instance") def cli_instance() -> None: - "Manage instance bans" + """ + Manage instance bans (deprecated) + + Use 'activityrelay ban' instead + """ @cli_instance.command("list") @@ -15,6 +20,7 @@ def cli_instance() -> None: def cli_instance_list(state: State) -> None: "List all banned instances" + click.echo("[DEPRECATED] Please use 'activityrelay ban list' instead") click.echo("Banned domains:") with state.database.session() as conn: @@ -34,6 +40,8 @@ def cli_instance_list(state: State) -> None: def cli_instance_ban(state: State, domain: str, reason: str, note: str) -> None: "Ban an instance and remove the associated inbox if it exists" + click.echo("[DEPRECATED] Please use 'activityrelay ban add' instead") + with state.database.session() as conn: if conn.get_domain_ban(domain) is not None: click.echo(f"Domain already banned: {domain}") @@ -50,6 +58,8 @@ def cli_instance_ban(state: State, domain: str, reason: str, note: str) -> None: def cli_instance_unban(state: State, domain: str) -> None: "Unban an instance" + click.echo("[DEPRECATED] Please use 'activityrelay ban remove' instead") + with state.database.session() as conn: if conn.del_domain_ban(domain) is None: click.echo(f"Instance wasn\"t banned: {domain}") @@ -72,6 +82,8 @@ def cli_instance_update( note: str) -> None: "Update the public reason or internal note for a domain ban" + click.echo("[DEPRECATED] Please use 'activityrelay ban list' instead") + if not (reason or note): ctx.fail("Must pass --reason or --note") diff --git a/relay/cli/software_ban.py b/relay/cli/software_ban.py index 8fe3f86..1f9fab9 100644 --- a/relay/cli/software_ban.py +++ b/relay/cli/software_ban.py @@ -6,9 +6,14 @@ from ..misc import RELAY_SOFTWARE from ..state import State +# remove this in 0.4.0 @cli.group("software") def cli_software() -> None: - "Manage banned software" + """ + Manage software bans (deprecated) + + Use 'activityrelay ban' instead + """ @cli_software.command("list") @@ -16,6 +21,7 @@ def cli_software() -> None: def cli_software_list(state: State) -> None: "List all banned software" + click.echo("[DEPRECATED] Please use 'activityrelay ban list' instead") click.echo("Banned software:") with state.database.session() as conn: @@ -44,6 +50,8 @@ async def cli_software_ban(state: State, fetch_nodeinfo: bool) -> None: "Ban software. Use RELAYS for NAME to ban relays" + click.echo("[DEPRECATED] Please use 'activityrelay ban add --software' instead") + with state.database.session() as conn: if name == "RELAYS": for item in RELAY_SOFTWARE: @@ -90,6 +98,8 @@ async def cli_software_ban(state: State, async def cli_software_unban(state: State, name: str, fetch_nodeinfo: bool) -> None: "Ban software. Use RELAYS for NAME to unban relays" + click.echo("[DEPRECATED] Please use 'activityrelay ban remove --software' instead") + with state.database.session() as conn: if name == "RELAYS": for software in RELAY_SOFTWARE: @@ -130,6 +140,8 @@ def cli_software_update( note: str) -> None: "Update the public reason or internal note for a software ban" + click.echo("[DEPRECATED] Please use 'activityrelay ban update --software' instead") + if not (reason or note): ctx.fail("Must pass --reason or --note")