예제 #1
0
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
예제 #2
0
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!',
    )
예제 #3
0
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!',
    )
예제 #4
0
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!',
    )
예제 #5
0
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!',
    )
예제 #6
0
파일: vhost_mail.py 프로젝트: ocf/ocfweb
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()
예제 #7
0
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()
예제 #8
0
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)
예제 #9
0
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
예제 #10
0
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()
예제 #11
0
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()
예제 #12
0
def test_mail_forwarding_address_is_wildcard():
    assert MailForwardingAddress('@vhost.com', None, frozenset(), None).is_wildcard
    assert not MailForwardingAddress('*****@*****.**', None, frozenset(), None).is_wildcard