def mock_ggroup_vhost(): mocked_vhost = mock.Mock(user='******', domain='vhost.com') mocked_vhost2 = mock.Mock(user='******', domain='vhost2.com') mocked_vhost.get_forwarding_addresses.return_value = { MailForwardingAddress( address='*****@*****.**', crypt_password='******', forward_to=frozenset(('*****@*****.**', '*****@*****.**')), last_updated=datetime(2000, 1, 1), ), MailForwardingAddress( address='*****@*****.**', crypt_password=None, forward_to=frozenset(('*****@*****.**', )), last_updated=datetime(2000, 1, 1), ), } with mock.patch.object( vhost_mail, 'vhosts_for_user', return_value={ mocked_vhost, mocked_vhost2, }, ): yield mocked_vhost
def test_update_replace_noop(client_ggroup, mock_ggroup_vhost, mock_messages, mock_txn): resp = client_ggroup.post( reverse('vhost_mail_update'), { 'action': 'update', 'addr': '*****@*****.**', }, ) mock_ggroup_vhost.remove_forwarding_address.assert_called_once_with( mock_txn().__enter__(), '*****@*****.**', ) mock_ggroup_vhost.add_forwarding_address.assert_called_once_with( mock_txn().__enter__(), MailForwardingAddress( address='*****@*****.**', forward_to=frozenset(('*****@*****.**', '*****@*****.**')), crypt_password='******', last_updated=mock.ANY, ), ) assert resp.status_code == 302 mock_messages.assert_called_once_with( mock.ANY, messages.SUCCESS, 'Update successful!', )
def test_update_add_new_addr( addr, password, expected_password, client_ggroup, mock_ggroup_vhost, mock_messages, mock_txn, ): resp = client_ggroup.post( reverse('vhost_mail_update'), { 'action': 'add', 'addr': addr, 'forward_to': '[email protected],[email protected]', 'password': '******', }, ) mock_ggroup_vhost.add_forwarding_address.assert_called_once_with( mock_txn().__enter__(), MailForwardingAddress( address=addr, forward_to=frozenset(('*****@*****.**', '*****@*****.**')), crypt_password=expected_password, last_updated=None, ), ) assert resp.status_code == 302 mock_messages.assert_called_once_with( mock.ANY, messages.SUCCESS, 'Update successful!', )
def test_update_replace_some_stuff(client_ggroup, mock_ggroup_vhost, mock_messages, mock_txn): resp = client_ggroup.post( reverse('vhost_mail_update'), { 'action': 'update', 'addr': '*****@*****.**', 'new_addr': '*****@*****.**', 'forward_to': '[email protected],[email protected]', 'password': '******', }) mock_ggroup_vhost.remove_forwarding_address.assert_called_once_with( mock_txn().__enter__(), '*****@*****.**', ) mock_ggroup_vhost.add_forwarding_address.assert_called_once_with( mock_txn().__enter__(), MailForwardingAddress( address='*****@*****.**', forward_to=frozenset(('*****@*****.**', '*****@*****.**')), crypt_password=VerifyPassword('nice password bro'), last_updated=mock.ANY, ), ) assert resp.status_code == 302 mock_messages.assert_called_once_with( mock.ANY, messages.SUCCESS, 'Update successful!', )
def test_import_csv_success(client_ggroup, mock_ggroup_vhost, mock_messages, mock_txn): """A test request that adds and updates addresses should work and preserve passwords.""" csv_text = dedent("""\ exists,[email protected] [email protected] newtestaddress,[email protected] """) resp = client_ggroup.post( reverse('vhost_mail_csv_import', args=('vhost.com', )), { 'csv_file': io.StringIO(csv_text), }, ) mock_ggroup_vhost.remove_forwarding_address.assert_called_once_with( mock_txn().__enter__(), '*****@*****.**', ) mock_ggroup_vhost.add_forwarding_address.assert_has_calls( any_order=True, calls=( mock.call( mock_txn().__enter__(), MailForwardingAddress( address='*****@*****.**', crypt_password='******', forward_to=frozenset(('*****@*****.**', '*****@*****.**')), last_updated=None, ), ), mock.call( mock_txn().__enter__(), MailForwardingAddress( address='*****@*****.**', forward_to=frozenset(('*****@*****.**', )), crypt_password=None, last_updated=None, ), ), ), ) assert resp.status_code == 302 mock_messages.assert_called_once_with( mock.ANY, messages.SUCCESS, 'Import successful!', )
def vhost_mail_csv_import(request: HttpRequest, domain: str) -> HttpResponseRedirect: user = logged_in_user(request) vhost = _get_vhost(user, domain) if not vhost: _error(request, f'You cannot use the domain: "{domain}"') addresses = _parse_csv(request, domain) # Add new addresses and update existing if the recipients changed with _txn() as c: existing_addrs = { addr.address: addr for addr in vhost.get_forwarding_addresses(c) } for from_addr, to_addrs in addresses.items(): if from_addr in existing_addrs: existing_addr = existing_addrs[from_addr] if to_addrs != existing_addr.forward_to: new = MailForwardingAddress( address=from_addr, crypt_password=existing_addr.crypt_password, forward_to=to_addrs, last_updated=None, ) vhost.remove_forwarding_address(c, from_addr) else: new = None else: new = MailForwardingAddress( address=from_addr, crypt_password=None, forward_to=to_addrs, last_updated=None, ) if new is not None: vhost.add_forwarding_address(c, new) messages.add_message(request, messages.SUCCESS, 'Import successful!') return _redirect_back()
def test_add_and_remove_addresses( mysql_connection, example_vhost, another_example_vhost, ): assert example_vhost.get_forwarding_addresses(mysql_connection) == set() addr1 = MailForwardingAddress( '*****@*****.**', 'hunter2', frozenset(['*****@*****.**']), None, ) addr2 = MailForwardingAddress( '@dev-vhost.ocf.berkeley.edu', None, frozenset(['*****@*****.**', '*****@*****.**']), None, ) # add one-by-one example_vhost.add_forwarding_address(mysql_connection, addr1) assert _normalize_times(example_vhost.get_forwarding_addresses(mysql_connection)) == {addr1} example_vhost.add_forwarding_address(mysql_connection, addr2) assert _normalize_times(example_vhost.get_forwarding_addresses(mysql_connection)) == {addr1, addr2} # unrelated vhost should have no addresses assert another_example_vhost.get_forwarding_addresses(mysql_connection) == set() # now remove them example_vhost.remove_forwarding_address( mysql_connection, '*****@*****.**', ) assert _normalize_times(example_vhost.get_forwarding_addresses(mysql_connection)) == {addr2} example_vhost.remove_forwarding_address( mysql_connection, '@dev-vhost.ocf.berkeley.edu', ) assert example_vhost.get_forwarding_addresses(mysql_connection) == set()
def test_parse_then_write_csv_is_noop(mock_ggroup_vhost): """Not an explicit goal, but write-parse-write should be the same as one write de facto if our data structures are consistent.""" addresses_1 = mock_ggroup_vhost.get_forwarding_addresses() csv_str_1 = _write_csv(addresses_1) f = io.BytesIO(bytes(csv_str_1, encoding='utf-8')) fake_request = mock.Mock(**{'FILES.get': {'csv_file': f}.get}) addresses_2 = frozenset({ MailForwardingAddress( address=from_addr, forward_to=to_addrs, crypt_password=None, last_updated=None, ) for from_addr, to_addrs in _parse_csv(fake_request, 'vhost.com').items() }) assert _write_csv(addresses_2)
def test_main_view_works(client_ggroup): """Smoke test with a valid user.""" fake_vhosts = { mock.Mock( user='******', domain='vhost.com', **{ 'get_forwarding_addresses.return_value': { MailForwardingAddress( address='*****@*****.**', crypt_password=None, forward_to=frozenset(('*****@*****.**', '*****@*****.**')), last_updated=datetime.now(), ), }, }, ), } with mock.patch.object(vhost_mail, 'vhosts_for_user', return_value=fake_vhosts): resp = client_ggroup.get(reverse('vhost_mail')) assert resp.status_code == 200
def vhost_mail_update(request): user = logged_in_user(request) # All requests are required to have these action = _get_action(request) addr_name, addr_domain, addr_vhost = _get_addr(request, user, 'addr', required=True) addr = (addr_name or '') + '@' + addr_domain # These fields are optional; some might be None forward_to = _get_forward_to(request) new_addr = _get_addr(request, user, 'new_addr', required=False) new_addr_name = None if new_addr is not None: new_addr_name, new_addr_domain, new_addr_vhost = new_addr new_addr = (new_addr_name or '') + '@' + new_addr_domain # Sanity check: can't move addresses across vhosts if new_addr_vhost != addr_vhost: _error( request, 'You cannot change an address from "{}" to "{}"!'.format( addr_domain, new_addr_domain, ), ) password_hash = _get_password(request, new_addr_name or addr_name) # Perform the add/update with _txn() as c: existing = _find_addr(c, addr_vhost, addr) new = None if action == 'add': if existing is not None: _error(request, f'The address "{addr}" already exists!') new = MailForwardingAddress( address=addr, crypt_password=None, forward_to=None, last_updated=None, ) else: if existing is None: _error(request, f'The address "{addr}" does not exist!') addr_vhost.remove_forwarding_address(c, existing.address) if action != 'delete': new = new or existing if forward_to: new = new._replace(forward_to=forward_to) if password_hash is REMOVE_PASSWORD: new = new._replace(crypt_password=None) elif password_hash: new = new._replace(crypt_password=password_hash) if new_addr: new = new._replace(address=new_addr) if new is not None: addr_vhost.add_forwarding_address(c, new) messages.add_message(request, messages.SUCCESS, 'Update successful!') return _redirect_back()
def vhost_mail_update(request): user = logged_in_user(request) # All requests are required to have these action = _get_action(request) addr_name, addr_domain, addr_vhost = _get_addr(request, user, 'addr', required=True) addr = (addr_name or '') + '@' + addr_domain # These fields are optional; some might be None forward_to = _get_forward_to(request) new_addr = _get_addr(request, user, 'new_addr', required=False) new_addr_name = None if new_addr is not None: new_addr_name, new_addr_domain, new_addr_vhost = new_addr new_addr = (new_addr_name or '') + '@' + new_addr_domain # Sanity check: can't move addresses across vhosts if new_addr_vhost != addr_vhost: _error( request, 'You cannot change an address from "{}" to "{}"!'.format( addr_domain, new_addr_domain, ), ) password_hash = _get_password(request, new_addr_name or addr_name) # Perform the add/update with _txn() as c: existing = _find_addr(c, addr_vhost, addr) new = None if action == 'add': if existing is not None: _error(request, 'The address "{}" already exists!'.format(addr)) new = MailForwardingAddress( address=addr, crypt_password=None, forward_to=None, last_updated=None, ) else: if existing is None: _error(request, 'The address "{}" does not exist!'.format(addr)) addr_vhost.remove_forwarding_address(c, existing.address) if action != 'delete': new = new or existing if forward_to: new = new._replace(forward_to=forward_to) if password_hash is REMOVE_PASSWORD: new = new._replace(crypt_password=None) elif password_hash: new = new._replace(crypt_password=password_hash) if new_addr: new = new._replace(address=new_addr) if new is not None: addr_vhost.add_forwarding_address(c, new) messages.add_message(request, messages.SUCCESS, 'Update successful!') return _redirect_back()
def test_mail_forwarding_address_is_wildcard(): assert MailForwardingAddress('@vhost.com', None, frozenset(), None).is_wildcard assert not MailForwardingAddress('*****@*****.**', None, frozenset(), None).is_wildcard