pyceo/tests/ceod/model/test_webhosting.py

164 lines
7.2 KiB
Python

import datetime
import os
import re
import subprocess
from unittest.mock import patch
from ceo_common.model import Term
import ceo_common.utils
from tests.utils import create_php_file_for_club
def create_website_config_for_club(sites_available_dir, cn, filename=None):
if filename is None:
filename = f'club-{cn}.conf'
filepath = os.path.join(sites_available_dir, filename)
with open(filepath, 'w') as fo:
fo.write(f"""
<VirtualHost *:80>
ServerName {cn}.uwaterloo.internal
ServerAdmin {cn}@{cn}.uwaterloo.internal
DocumentRoot /users/{cn}/www/
</VirtualHost>
""")
def get_enabled_sites(webhosting_srv):
return [
club_name
for club_name, club_info in webhosting_srv.clubs.items()
if not club_info['disabled']
]
def test_disable_club_sites(webhosting_srv, webhosting_srv_resources, new_club_gen):
sites_available_dir = webhosting_srv.sites_available_dir
with new_club_gen() as group1, new_club_gen() as group2:
create_website_config_for_club(sites_available_dir, group1.cn)
create_website_config_for_club(sites_available_dir, group2.cn, 'club-somerandomname.conf')
with webhosting_srv.begin_transaction():
enabled_clubs = get_enabled_sites(webhosting_srv)
assert sorted(enabled_clubs) == [group1.cn, group2.cn]
webhosting_srv.disable_club_site(group1.cn)
# Make sure that if we don't call commit(), nothing gets saved
with webhosting_srv.begin_transaction():
enabled_clubs = get_enabled_sites(webhosting_srv)
assert sorted(enabled_clubs) == [group1.cn, group2.cn]
webhosting_srv.disable_club_site(group1.cn)
webhosting_srv.commit()
# Now that we committed the changes, they should be persistent
with webhosting_srv.begin_transaction():
enabled_clubs = get_enabled_sites(webhosting_srv)
assert enabled_clubs == [group2.cn]
def test_disable_inactive_club_sites(
cfg, webhosting_srv, webhosting_srv_resources, g_admin_ctx, new_club_gen,
new_user_gen, mock_mail_server,
):
sites_available_dir = webhosting_srv.sites_available_dir
term = Term.current()
clubs_home = cfg.get('clubs_home')
with patch.object(ceo_common.utils, 'get_current_datetime') as now_mock:
now_mock.return_value = datetime.datetime.now()
with new_club_gen() as group1, \
new_club_gen() as group2, \
new_user_gen() as user1, \
new_user_gen() as user2:
create_website_config_for_club(sites_available_dir, group1.cn)
create_website_config_for_club(sites_available_dir, group2.cn)
create_php_file_for_club(clubs_home, group1.cn)
with g_admin_ctx():
# group1 has no club reps so it should be disabled
# group2 has no club reps but it doesn't use PHP
assert webhosting_srv.disable_sites_for_inactive_clubs(dry_run=True) == [group1.cn]
user1.add_non_member_terms([str(Term.current())])
group1.add_member(user1.uid)
with g_admin_ctx():
# group1 has an active club rep, so it shouldn't be disabled anymore
assert webhosting_srv.disable_sites_for_inactive_clubs(dry_run=True) == []
now_mock.return_value = (term + 3).to_datetime()
with g_admin_ctx():
# club reps are allowed to be inactive for up to 3 terms
assert webhosting_srv.disable_sites_for_inactive_clubs(dry_run=True) == []
now_mock.return_value = (term + 4).to_datetime()
with g_admin_ctx():
# club site should be disabled now that club rep is inactive
assert webhosting_srv.disable_sites_for_inactive_clubs(dry_run=True) == [group1.cn]
user2.add_non_member_terms([str(Term.current())])
group1.add_member(user2.uid)
with g_admin_ctx():
# group1 has a new club rep, so it shouldn't be disabled anymore
assert webhosting_srv.disable_sites_for_inactive_clubs(dry_run=True) == []
create_php_file_for_club(clubs_home, group2.cn)
group2.add_member(user2.uid)
with g_admin_ctx():
# user2 is an active club rep for both group1 and group2
assert webhosting_srv.disable_sites_for_inactive_clubs(dry_run=True) == []
now_mock.return_value = (term + 8).to_datetime()
mock_mail_server.messages.clear()
subprocess.run(['git', 'init'], cwd=webhosting_srv.apache_dir, check=True)
with g_admin_ctx():
disabled_sites = webhosting_srv.disable_sites_for_inactive_clubs()
# user2 expired and both sites use PHP, so they should both be disabled
assert sorted(disabled_sites) == [group1.cn, group2.cn]
# since each club had a ServerAdmin directive, they should both have received
# notification emails
assert len(mock_mail_server.messages) == 2
with open(webhosting_srv.conf_available_dir + '/disable-club.conf') as fi:
disable_club_conf_content = fi.read()
print(disable_club_conf_content)
for group in [group1, group2]:
pat = re.compile(
(
rf'^<Directory "?/users/{group.cn}/www"?>\n'
r'\s*Include snippets/disable-club\.conf\n'
r'</Directory>$'
),
re.MULTILINE
)
assert pat.search(disable_club_conf_content) is not None
with g_admin_ctx():
# Club sites should only be disabled once
assert webhosting_srv.disable_sites_for_inactive_clubs() == []
mock_mail_server.messages.clear()
def test_remove_inactive_club_reps(
cfg, webhosting_srv, webhosting_srv_resources, g_admin_ctx, new_club_gen,
new_user_gen, ldap_srv_session,
):
term = Term.current()
clubs_home = cfg.get('clubs_home')
with patch.object(ceo_common.utils, 'get_current_datetime') as now_mock:
now_mock.return_value = datetime.datetime.now()
with new_club_gen() as group, \
new_user_gen() as user1, \
new_user_gen() as user2:
create_php_file_for_club(clubs_home, group.cn)
for user in [user1, user2]:
user.add_non_member_terms([str(Term.current())])
group.add_member(user.uid)
now_mock.return_value = (term + 4).to_datetime()
with g_admin_ctx():
webhosting_srv.disable_sites_for_inactive_clubs(remove_inactive_club_reps=True)
group = ldap_srv_session.get_group(group.cn)
assert group.members == []
# Make sure that inactive club reps get removed even if the site
# has already been disabled
group.add_member(user1.uid)
with g_admin_ctx():
webhosting_srv.disable_sites_for_inactive_clubs(remove_inactive_club_reps=True)
group = ldap_srv_session.get_group(group.cn)
assert group.members == []