add mailman CLI command
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Max Erenberg 2021-09-25 15:16:22 -04:00
parent 3cba9680f5
commit 2a5d903eba
6 changed files with 58 additions and 1 deletions

View File

@ -6,6 +6,7 @@ from .positions import positions
from .updateprograms import updateprograms from .updateprograms import updateprograms
from .mysql import mysql from .mysql import mysql
from .postgresql import postgresql from .postgresql import postgresql
from .mailman import mailman
@click.group() @click.group()
@ -19,3 +20,4 @@ cli.add_command(positions)
cli.add_command(updateprograms) cli.add_command(updateprograms)
cli.add_command(mysql) cli.add_command(mysql)
cli.add_command(postgresql) cli.add_command(postgresql)
cli.add_command(mailman)

29
ceo/cli/mailman.py Normal file
View File

@ -0,0 +1,29 @@
import click
from ..utils import http_post, http_delete
from .utils import handle_sync_response
@click.group(short_help='Manage mailing list subscriptions')
def mailman():
pass
@mailman.command(short_help='Subscribe a member to a mailing list')
@click.argument('username')
@click.argument('mailing_list')
def subscribe(username, mailing_list):
click.confirm(f'Are you sure you want to subscribe {username} to {mailing_list}?', abort=True)
resp = http_post(f'/api/mailman/{mailing_list}/{username}')
handle_sync_response(resp)
click.echo('Done.')
@mailman.command(short_help='Unsubscribe a member from a mailing list')
@click.argument('username')
@click.argument('mailing_list')
def unsubscribe(username, mailing_list):
click.confirm(f'Are you sure you want to unsubscribe {username} from {mailing_list}?', abort=True)
resp = http_delete(f'/api/mailman/{mailing_list}/{username}')
handle_sync_response(resp)
click.echo('Done.')

View File

@ -16,6 +16,8 @@ def http_request(method: str, path: str, **kwargs) -> requests.Response:
cfg = component.getUtility(IConfig) cfg = component.getUtility(IConfig)
if path.startswith('/api/db'): if path.startswith('/api/db'):
host = cfg.get('ceod_database_host') host = cfg.get('ceod_database_host')
elif path.startswith('/api/mailman'):
host = cfg.get('ceod_mailman_host')
else: else:
host = cfg.get('ceod_admin_host') host = cfg.get('ceod_admin_host')
return client.request( return client.request(

View File

@ -67,7 +67,7 @@ def authz_restrict_to_groups(f: Callable, allowed_groups: List[str]) -> Callable
def authz_restrict_to_staff(f: Callable) -> Callable: def authz_restrict_to_staff(f: Callable) -> Callable:
"""A decorator to restrict an endpoint to staff members.""" """A decorator to restrict an endpoint to staff members."""
allowed_groups = ['office', 'staff', 'adm'] allowed_groups = ['syscom', 'exec', 'office', 'staff', 'adm']
return authz_restrict_to_groups(f, allowed_groups) return authz_restrict_to_groups(f, allowed_groups)

View File

@ -0,0 +1,23 @@
from click.testing import CliRunner
from ceo.cli import cli
def test_mailman_subscribe(cli_setup, mock_mailman_server):
mock_mailman_server.clear()
runner = CliRunner()
result = runner.invoke(cli, ['mailman', 'subscribe', 'test_1', 'exec'], input='y\n')
expected = (
"Are you sure you want to subscribe test_1 to exec? [y/N]: y\n"
"Done.\n"
)
assert result.exit_code == 0
assert result.output == expected
result = runner.invoke(cli, ['mailman', 'unsubscribe', 'test_1', 'exec'], input='y\n')
expected = (
"Are you sure you want to unsubscribe test_1 from exec? [y/N]: y\n"
"Done.\n"
)
assert result.exit_code == 0
assert result.output == expected

View File

@ -6,6 +6,7 @@ uw_domain = uwaterloo.internal
# this is the host with the ceod/admin Kerberos key # this is the host with the ceod/admin Kerberos key
admin_host = phosphoric-acid admin_host = phosphoric-acid
database_host = coffee database_host = coffee
mailman_host = mail
use_https = false use_https = false
port = 9987 port = 9987