diff --git a/tests/ceo/cli/test_members.py b/tests/ceo/cli/test_members.py index cf13a38..63d211e 100644 --- a/tests/ceo/cli/test_members.py +++ b/tests/ceo/cli/test_members.py @@ -1,212 +1,213 @@ -import os -import re -import shutil -from datetime import datetime, timedelta - -from click.testing import CliRunner -import ldap3 - -from ceo.cli import cli -from ceo_common.model import Term -from tests.utils import set_datetime_in_app_process, restore_datetime_in_app_process - - -def test_members_get(cli_setup, ldap_user): - runner = CliRunner() - result = runner.invoke(cli, ['members', 'get', ldap_user.uid]) - expected = ( - f"uid: {ldap_user.uid}\n" - f"full name: {ldap_user.cn}\n" - f"first name: {ldap_user.given_name}\n" - f"last name: {ldap_user.sn}\n" - f"program: {ldap_user.program}\n" - f"UID number: {ldap_user.uid_number}\n" - f"GID number: {ldap_user.gid_number}\n" - f"login shell: {ldap_user.login_shell}\n" - f"home directory: {ldap_user.home_directory}\n" - f"is a club: {ldap_user.is_club()}\n" - f"is a club rep: {ldap_user.is_club_rep}\n" - "forwarding addresses: \n" - f"member terms: {','.join(ldap_user.terms)}\n" - ) - assert result.exit_code == 0 - assert result.output == expected - - -def test_members_add(cli_setup): - runner = CliRunner() - result = runner.invoke(cli, [ - 'members', 'add', 'test_1', '--cn', 'Test One', '--given-name', 'Test', - '--sn', 'One', '--program', 'Math', '--terms', '1', - ], input='y\n') - expected_pat = re.compile(( - "^The following user will be created:\n" - "uid: test_1\n" - "full name: Test One\n" - "first name: Test\n" - "last name: One\n" - "program: Math\n" - "forwarding addresses: test_1@uwaterloo.internal\n" - "member terms: [sfw]\\d{4}\n" - "Do you want to continue\\? \\[y/N\\]: y\n" - "Add user to LDAP... Done\n" - "Add group to LDAP... Done\n" - "Add user to Kerberos... Done\n" - "Create home directory... Done\n" - "Set forwarding addresses... Done\n" - "Send welcome message... Done\n" - "Subscribe to mailing list... Done\n" - "Announce new user to mailing list... Done\n" - "Transaction successfully completed.\n" - "uid: test_1\n" - "full name: Test One\n" - "first name: Test\n" - "last name: One\n" - "program: Math\n" - "UID number: \\d{5}\n" - "GID number: \\d{5}\n" - "login shell: /bin/bash\n" - "home directory: [a-z0-9/_-]+/test_1\n" - "is a club: False\n" - "is a club rep: False\n" - "forwarding addresses: test_1@uwaterloo\\.internal\n" - "member terms: [sfw]\\d{4}\n" - "password: \\S+\n$" - ), re.MULTILINE) - assert result.exit_code == 0 - assert expected_pat.match(result.output) is not None - - result = runner.invoke(cli, ['members', 'delete', 'test_1'], input='y\n') - assert result.exit_code == 0 - - -def test_members_modify(cli_setup, ldap_user): - # The homedir needs to exist so the API can write to ~/.forward - os.makedirs(ldap_user.home_directory) - try: - runner = CliRunner() - result = runner.invoke(cli, [ - 'members', 'modify', ldap_user.uid, '--login-shell', '/bin/sh', - '--forwarding-addresses', 'jdoe@test1.internal,jdoe@test2.internal', - ], input='y\n') - expected = ( - "Login shell will be set to: /bin/sh\n" - "~/.forward will be set to: jdoe@test1.internal\n" - " jdoe@test2.internal\n" - "Do you want to continue? [y/N]: y\n" - "Replace login shell... Done\n" - "Replace forwarding addresses... Done\n" - "Transaction successfully completed.\n" - ) - assert result.exit_code == 0 - assert result.output == expected - finally: - shutil.rmtree(ldap_user.home_directory) - - -def test_members_renew(cli_setup, ldap_user, g_admin_ctx): - # set the user's last term to something really old - with g_admin_ctx(), ldap_user.ldap_srv.entry_ctx_for_user(ldap_user) as entry: - entry.term = ['s1999', 'f1999'] - current_term = Term.current() - - runner = CliRunner() - result = runner.invoke(cli, [ - 'members', 'renew', ldap_user.uid, '--terms', '1', - ], input='y\n') - expected = ( - f"The following member terms will be added: {current_term}\n" - "Do you want to continue? [y/N]: y\n" - "Done.\n" - ) - assert result.exit_code == 0 - assert result.output == expected - - runner = CliRunner() - result = runner.invoke(cli, [ - 'members', 'renew', ldap_user.uid, '--terms', '2', - ], input='y\n') - expected = ( - f"The following member terms will be added: {current_term+1},{current_term+2}\n" - "Do you want to continue? [y/N]: y\n" - "Done.\n" - ) - assert result.exit_code == 0 - assert result.output == expected - - -def test_members_pwreset(cli_setup, ldap_user, krb_user): - runner = CliRunner() - result = runner.invoke( - cli, ['members', 'pwreset', ldap_user.uid], input='y\n') - expected_pat = re.compile(( - f"^Are you sure you want to reset {ldap_user.uid}'s password\\? \\[y/N\\]: y\n" - "New password: \\S+\n$" - ), re.MULTILINE) - assert result.exit_code == 0 - assert expected_pat.match(result.output) is not None - - -def test_members_expire(cli_setup, app_process, ldap_user): - runner = CliRunner() - - try: - # use a time that we know for sure will expire - test_date = datetime(4000, 4, 1) - set_datetime_in_app_process(app_process, test_date) - - result = runner.invoke(cli, ['members', 'expire', '--dry-run']) - assert result.exit_code == 0 - assert result.output == f"The following members will be marked as expired:\n{ldap_user.uid}\n" - - result = runner.invoke(cli, ['members', 'expire']) - assert result.exit_code == 0 - assert result.output == f"The following members has been marked as expired:\n{ldap_user.uid}\n" - - runner.invoke(cli, ['members', 'renew', ldap_user.uid, '--terms', '1']) - assert result.exit_code == 0 - - result = runner.invoke(cli, ['members', 'expire', '--dry-run']) - assert result.exit_code == 0 - assert result.output == '' - finally: - restore_datetime_in_app_process(app_process) - - -def test_members_remindexpire(cfg, cli_setup, app_process, ldap_conn, ldap_user): - runner = CliRunner() - term = Term(ldap_user.terms[0]) - test_date = (term + 1).to_datetime() - # Add a term to ctdalek so that he doesn't show up in the results - base_dn = cfg.get('ldap_users_base') - ldap_conn.modify( - f'uid=ctdalek,{base_dn}', - {'term': [(ldap3.MODIFY_ADD, [str(term + 1)])]}) - - try: - set_datetime_in_app_process(app_process, test_date) - result = runner.invoke(cli, ['members', 'remindexpire', '--dry-run']) - assert result.exit_code == 0 - assert result.output == ( - "The following members will be sent membership renewal reminders:\n" - f"{ldap_user.uid}\n" - ) - - result = runner.invoke(cli, ['members', 'remindexpire']) - assert result.exit_code == 0 - assert result.output == ( - "The following members were sent membership renewal reminders:\n" - f"{ldap_user.uid}\n" - ) - - test_date = (term + 1).to_datetime() + timedelta(days=40) - set_datetime_in_app_process(app_process, test_date) - result = runner.invoke(cli, ['members', 'remindexpire']) - assert result.exit_code == 0 - assert result.output == "No members are pending expiration.\n" - finally: - restore_datetime_in_app_process(app_process) - - ldap_conn.modify( - f'uid=ctdalek,{base_dn}', - {'term': [(ldap3.MODIFY_DELETE, [str(term + 1)])]}) +import os +import re +import shutil +from datetime import datetime, timedelta + +from click.testing import CliRunner +import ldap3 + +from ceo.cli import cli +from ceo_common.model import Term +from tests.utils import set_datetime_in_app_process, restore_datetime_in_app_process + + +def test_members_get(cli_setup, ldap_user): + runner = CliRunner() + result = runner.invoke(cli, ['members', 'get', ldap_user.uid]) + expected = ( + f"uid: {ldap_user.uid}\n" + f"full name: {ldap_user.cn}\n" + f"first name: {ldap_user.given_name}\n" + f"last name: {ldap_user.sn}\n" + f"program: {ldap_user.program}\n" + f"UID number: {ldap_user.uid_number}\n" + f"GID number: {ldap_user.gid_number}\n" + f"login shell: {ldap_user.login_shell}\n" + f"home directory: {ldap_user.home_directory}\n" + f"is a club: {ldap_user.is_club()}\n" + f"is a club rep: {ldap_user.is_club_rep}\n" + f"forwarding addresses: \n" + f"member terms: {','.join(ldap_user.terms)}\n" + f"groups: \n" + ) + assert result.exit_code == 0 + assert result.output == expected + + +def test_members_add(cli_setup): + runner = CliRunner() + result = runner.invoke(cli, [ + 'members', 'add', 'test_1', '--cn', 'Test One', '--given-name', 'Test', + '--sn', 'One', '--program', 'Math', '--terms', '1', + ], input='y\n') + expected_pat = re.compile(( + "^The following user will be created:\n" + "uid: test_1\n" + "full name: Test One\n" + "first name: Test\n" + "last name: One\n" + "program: Math\n" + "forwarding addresses: test_1@uwaterloo.internal\n" + "member terms: [sfw]\\d{4}\n" + "Do you want to continue\\? \\[y/N\\]: y\n" + "Add user to LDAP... Done\n" + "Add group to LDAP... Done\n" + "Add user to Kerberos... Done\n" + "Create home directory... Done\n" + "Set forwarding addresses... Done\n" + "Send welcome message... Done\n" + "Subscribe to mailing list... Done\n" + "Announce new user to mailing list... Done\n" + "Transaction successfully completed.\n" + "uid: test_1\n" + "full name: Test One\n" + "first name: Test\n" + "last name: One\n" + "program: Math\n" + "UID number: \\d{5}\n" + "GID number: \\d{5}\n" + "login shell: /bin/bash\n" + "home directory: [a-z0-9/_-]+/test_1\n" + "is a club: False\n" + "is a club rep: False\n" + "forwarding addresses: test_1@uwaterloo\\.internal\n" + "member terms: [sfw]\\d{4}\n" + "password: \\S+\n$" + ), re.MULTILINE) + assert result.exit_code == 0 + assert expected_pat.match(result.output) is not None + + result = runner.invoke(cli, ['members', 'delete', 'test_1'], input='y\n') + assert result.exit_code == 0 + + +def test_members_modify(cli_setup, ldap_user): + # The homedir needs to exist so the API can write to ~/.forward + os.makedirs(ldap_user.home_directory) + try: + runner = CliRunner() + result = runner.invoke(cli, [ + 'members', 'modify', ldap_user.uid, '--login-shell', '/bin/sh', + '--forwarding-addresses', 'jdoe@test1.internal,jdoe@test2.internal', + ], input='y\n') + expected = ( + "Login shell will be set to: /bin/sh\n" + "~/.forward will be set to: jdoe@test1.internal\n" + " jdoe@test2.internal\n" + "Do you want to continue? [y/N]: y\n" + "Replace login shell... Done\n" + "Replace forwarding addresses... Done\n" + "Transaction successfully completed.\n" + ) + assert result.exit_code == 0 + assert result.output == expected + finally: + shutil.rmtree(ldap_user.home_directory) + + +def test_members_renew(cli_setup, ldap_user, g_admin_ctx): + # set the user's last term to something really old + with g_admin_ctx(), ldap_user.ldap_srv.entry_ctx_for_user(ldap_user) as entry: + entry.term = ['s1999', 'f1999'] + current_term = Term.current() + + runner = CliRunner() + result = runner.invoke(cli, [ + 'members', 'renew', ldap_user.uid, '--terms', '1', + ], input='y\n') + expected = ( + f"The following member terms will be added: {current_term}\n" + "Do you want to continue? [y/N]: y\n" + "Done.\n" + ) + assert result.exit_code == 0 + assert result.output == expected + + runner = CliRunner() + result = runner.invoke(cli, [ + 'members', 'renew', ldap_user.uid, '--terms', '2', + ], input='y\n') + expected = ( + f"The following member terms will be added: {current_term+1},{current_term+2}\n" + "Do you want to continue? [y/N]: y\n" + "Done.\n" + ) + assert result.exit_code == 0 + assert result.output == expected + + +def test_members_pwreset(cli_setup, ldap_user, krb_user): + runner = CliRunner() + result = runner.invoke( + cli, ['members', 'pwreset', ldap_user.uid], input='y\n') + expected_pat = re.compile(( + f"^Are you sure you want to reset {ldap_user.uid}'s password\\? \\[y/N\\]: y\n" + "New password: \\S+\n$" + ), re.MULTILINE) + assert result.exit_code == 0 + assert expected_pat.match(result.output) is not None + + +def test_members_expire(cli_setup, app_process, ldap_user): + runner = CliRunner() + + try: + # use a time that we know for sure will expire + test_date = datetime(4000, 4, 1) + set_datetime_in_app_process(app_process, test_date) + + result = runner.invoke(cli, ['members', 'expire', '--dry-run']) + assert result.exit_code == 0 + assert result.output == f"The following members will be marked as expired:\n{ldap_user.uid}\n" + + result = runner.invoke(cli, ['members', 'expire']) + assert result.exit_code == 0 + assert result.output == f"The following members has been marked as expired:\n{ldap_user.uid}\n" + + runner.invoke(cli, ['members', 'renew', ldap_user.uid, '--terms', '1']) + assert result.exit_code == 0 + + result = runner.invoke(cli, ['members', 'expire', '--dry-run']) + assert result.exit_code == 0 + assert result.output == '' + finally: + restore_datetime_in_app_process(app_process) + + +def test_members_remindexpire(cfg, cli_setup, app_process, ldap_conn, ldap_user): + runner = CliRunner() + term = Term(ldap_user.terms[0]) + test_date = (term + 1).to_datetime() + # Add a term to ctdalek so that he doesn't show up in the results + base_dn = cfg.get('ldap_users_base') + ldap_conn.modify( + f'uid=ctdalek,{base_dn}', + {'term': [(ldap3.MODIFY_ADD, [str(term + 1)])]}) + + try: + set_datetime_in_app_process(app_process, test_date) + result = runner.invoke(cli, ['members', 'remindexpire', '--dry-run']) + assert result.exit_code == 0 + assert result.output == ( + "The following members will be sent membership renewal reminders:\n" + f"{ldap_user.uid}\n" + ) + + result = runner.invoke(cli, ['members', 'remindexpire']) + assert result.exit_code == 0 + assert result.output == ( + "The following members were sent membership renewal reminders:\n" + f"{ldap_user.uid}\n" + ) + + test_date = (term + 1).to_datetime() + timedelta(days=40) + set_datetime_in_app_process(app_process, test_date) + result = runner.invoke(cli, ['members', 'remindexpire']) + assert result.exit_code == 0 + assert result.output == "No members are pending expiration.\n" + finally: + restore_datetime_in_app_process(app_process) + + ldap_conn.modify( + f'uid=ctdalek,{base_dn}', + {'term': [(ldap3.MODIFY_DELETE, [str(term + 1)])]}) diff --git a/tests/ceod/api/test_members.py b/tests/ceod/api/test_members.py index 2814265..edf523e 100644 --- a/tests/ceod/api/test_members.py +++ b/tests/ceod/api/test_members.py @@ -127,6 +127,7 @@ def test_api_get_user(cfg, client, create_user_result): del old_data['password'] status, data = client.get(f'/api/members/{uid}') + del data['groups'] assert status == 200 assert data == old_data @@ -262,6 +263,7 @@ def test_authz_check(client, create_user_result): del old_data['password'] del old_data['forwarding_addresses'] _, data = client.get(f'/api/members/{uid}', principal='regular1') + del data['groups'] assert data == old_data # If we're syscom but we don't pass credentials, the request should fail