示例#1
0
    def test_if_subscription_pending_has_no_effect(self, registration_service,
                                                   storage,
                                                   confirmation_requester,
                                                   utcnow):
        given_email = Email("*****@*****.**")
        storage.upsert(
            Registration(
                email=given_email,
                state=State.pending_subscribe,
                last_update=utcnow() - timedelta(days=1),
                confirm_token=Token(b"token"),
                confirm_action=Action.subscribe,
            ))

        registration_service.unsubscribe(given_email)

        stored = storage.find(given_email)
        assert not confirmation_requester.request_confirmation.called
        assert stored == Registration(
            email=given_email,
            state=State.pending_subscribe,
            last_update=utcnow() - timedelta(days=1),
            confirm_token=Token(b"token"),
            confirm_action=Action.subscribe,
        )
示例#2
0
    def test_confirm_link_substitutions(self, settings):
        template = "{{confirm_link}}"
        token = Token(b"token")

        provider = EmailFromTemplateProvider(
            settings=settings,
            template_loader=MockTemplateLoader({
                "subscribe.subject.txt": template,
                "subscribe.txt": template,
                "subscribe.html": template,
            }),
            binary_loader=MockBinaryLoader(dict()),
        )
        msg = provider.get_confirmation_request_msg(Email("email@local"),
                                                    action=Action.subscribe,
                                                    confirm_token=token)

        expected_link = (
            "https://test.local/subscribe/confirm/email%40local?token=" +
            quote(token.to_string()))
        assert msg["Subject"] == expected_link
        assert (msg.get_body("plain").get_content().strip() ==
                expected_link  # type: ignore
                )
        assert (msg.get_body("html").get_content().strip() ==
                expected_link  # type: ignore
                )
示例#3
0
    def test_get_all_active_subscribers(self, tiny_db_storage):
        active = (
            Registration(
                email=Email("*****@*****.**"),
                last_update=datetime.utcnow(),
                state=State.subscribed,
            ),
            Registration(
                email=Email("*****@*****.**"),
                last_update=datetime.now(),
                state=State.pending_unsubscribe,
                confirm_action=Action.unsubscribe,
                confirm_token=Token(b"token"),
            ),
        )
        inactive = (Registration(
            email=Email("*****@*****.**"),
            last_update=datetime.now(),
            state=State.pending_subscribe,
            confirm_action=Action.subscribe,
            confirm_token=Token(b"token"),
        ), )

        for r in active + inactive:
            tiny_db_storage.upsert(r)

        result = tiny_db_storage.get_all_active_subscribers()

        assert tuple(sorted(result, key=lambda r: r.email)) == active
示例#4
0
    def test_confirm_with_invalid_token_raises_exception(
            self, state, registration_service, storage, utcnow):
        given_email = Email("*****@*****.**")
        storage.upsert(
            Registration(
                email=given_email,
                state=state,
                last_update=utcnow() - timedelta(days=1),
                confirm_token=Token(b"actual token"),
                confirm_action=Action.subscribe
                if state == State.pending_subscribe else Action.unsubscribe,
            ))

        with pytest.raises(UnauthorizedException):
            registration_service.confirm(given_email, Token(b"invalid token"))
示例#5
0
    def test_drop_old_unconfirmed(self, tiny_db_storage):
        reference_datetime = datetime(2019, 10, 25, 13, 18)
        fresh = (
            Registration(
                email=Email("*****@*****.**"),
                last_update=reference_datetime - timedelta(days=1),
                state=State.pending_subscribe,
                confirm_action=Action.subscribe,
                confirm_token=Token(b"token"),
            ),
            Registration(
                email=Email("*****@*****.**"),
                last_update=reference_datetime - timedelta(days=3),
                state=State.subscribed,
            ),
            Registration(
                email=Email("*****@*****.**"),
                last_update=reference_datetime - timedelta(days=3),
                state=State.pending_unsubscribe,
                confirm_action=Action.unsubscribe,
                confirm_token=Token(b"token"),
            ),
        )
        old = (Registration(
            email=Email("*****@*****.**"),
            last_update=reference_datetime - timedelta(days=3),
            state=State.pending_subscribe,
            confirm_action=Action.subscribe,
            confirm_token=Token(b"token"),
        ), )

        for r in fresh + old:
            tiny_db_storage.upsert(r)

        tiny_db_storage.drop_old_unconfirmed(drop_before=reference_datetime -
                                             timedelta(days=2))

        assert tuple(sorted(tiny_db_storage.all(),
                            key=lambda r: r.email)) == fresh
示例#6
0
    def test_confirm_with_valid_token_removes_subscription(
            self, registration_service, storage, utcnow):
        given_email = Email("*****@*****.**")
        given_token = Token(b"token")
        storage.upsert(
            Registration(
                email=given_email,
                state=State.pending_unsubscribe,
                last_update=utcnow() - timedelta(days=1),
                confirm_token=given_token,
                confirm_action=Action.unsubscribe,
            ))

        registration_service.confirm(given_email, given_token)

        assert storage.find(given_email) is None
示例#7
0
    def test_include_binary_and_b64encode(self, settings):
        binary_content = b"binary content"
        subject = "{{ include_binary('bin') | b64encode }}"
        provider = EmailFromTemplateProvider(
            settings=settings,
            template_loader=MockTemplateLoader({
                f"subscribe.subject.txt": subject,
                "subscribe.txt": "",
                "subscribe.html": "",
            }),
            binary_loader=MockBinaryLoader({"bin": binary_content}),
        )
        msg = provider.get_confirmation_request_msg(
            Email("email"),
            action=Action.subscribe,
            confirm_token=Token(b"token"))

        assert msg["Subject"] == b64encode(binary_content).decode("ascii")
示例#8
0
    def test_subject_substitutions(self, settings):
        subject = "{{display_name}} {{host}} {{to_email}}"

        provider = EmailFromTemplateProvider(
            settings=settings,
            template_loader=MockTemplateLoader({
                "subscribe.subject.txt": subject,
                "subscribe.txt": "",
                "subscribe.html": "",
            }),
            binary_loader=MockBinaryLoader(dict()),
        )
        msg = provider.get_confirmation_request_msg(
            Email("email"),
            action=Action.subscribe,
            confirm_token=Token(b"token"))

        assert msg[
            "Subject"] == f"{settings.display_name} {settings.host} email"
示例#9
0
    def test_body_substitutions(self, settings):
        subject = "subject"
        template = "{{subject}} {{display_name}} {{host}} {{to_email}}"

        provider = EmailFromTemplateProvider(
            settings=settings,
            template_loader=MockTemplateLoader({
                "subscribe.subject.txt": subject,
                "subscribe.txt": template,
                "subscribe.html": template,
            }),
            binary_loader=MockBinaryLoader(dict()),
        )
        msg = provider.get_confirmation_request_msg(
            Email("email"),
            action=Action.subscribe,
            confirm_token=Token(b"token"))

        assert (msg.get_body("plain").get_content().strip()  # type: ignore
                == f"{subject} {settings.display_name} {settings.host} email")
示例#10
0
def test_email_confirmation_requester():
    email = Email("email")
    action = Action.subscribe
    confirm_token = Token(b"token")
    message = EmailMessage()

    connection_manager = MagicMock()
    connection = MagicMock()
    message_provider = MagicMock()

    connection_manager.__enter__.return_value = connection
    message_provider.get_confirmation_request_msg.return_value = message

    requester = EmailConfirmationRequester(
        connection=lambda: connection_manager,
        message_provider=message_provider)
    requester.request_confirmation(email,
                                   action=action,
                                   confirm_token=confirm_token)

    message_provider.get_confirmation_request_msg.assert_called_once_with(
        email, action=action, confirm_token=confirm_token)
    connection.send_message.assert_called_once_with(message)
示例#11
0
    def test_constructs_email_message_from_templates(self, action, settings):
        to_email = Email("*****@*****.**")
        subject = "subject"
        plain_text = "plain text"
        html = "html"

        provider = EmailFromTemplateProvider(
            settings=settings,
            template_loader=MockTemplateLoader({
                f"{action.name}.subject.txt": subject,
                f"{action.name}.txt": plain_text,
                f"{action.name}.html": html,
            }),
            binary_loader=MockBinaryLoader(dict()),
        )
        msg = provider.get_confirmation_request_msg(
            to_email, action=action, confirm_token=Token(b"token"))

        assert msg["Subject"] == subject
        assert msg["To"] == to_email
        assert msg.get_body(
            "plain").get_content().strip() == plain_text  # type: ignore
        assert msg.get_body(
            "html").get_content().strip() == html  # type: ignore
示例#12
0
 def request_confirmation(self, email: Email, *, action: Action,
                          confirm_token: Token):
     self.tokens[email] = confirm_token.to_string()
示例#13
0
    conn = smtp_connection(args.host[0], user, getpass.getpass(f"Password for {user}:"))

    settings = EmailFromTemplateProvider.Settings(
        display_name="Doveseed template test",
        sender=args.from_mail[0],
        host="doveseed.local",
        confirm_url_format="https://{host}/confirm/{email}?token={token}",
    )
    message_provider = EmailFromTemplateProvider(
        settings=settings,
        template_loader=FileSystemLoader(args.template[0]),
        binary_loader=FileSystemBinaryLoader(args.template[0]),
    )

    token = Token(b"token")
    dispatch = {
        "subscribe": lambda: message_provider.get_confirmation_request_msg(
            args.to_mail[0], action=Action.subscribe, confirm_token=token
        ),
        "unsubscribe": lambda: message_provider.get_confirmation_request_msg(
            args.to_mail[0], action=Action.unsubscribe, confirm_token=token
        ),
        "new-post": lambda: message_provider.get_new_post_msg(
            FeedItem(
                title="Post title",
                description=LoremIpsum,
                link="https://doveseed.local/post",
                pub_date=datetime.now(),
                image=args.image[0],
            ),
示例#14
0
class TestTinyDbStorage:
    def test_upsert_of_new_entity(self, tiny_db, tiny_db_storage):
        last_update = datetime(2019, 10, 25, 13, 37)
        registration = Registration(
            email=Email("*****@*****.**"),
            last_update=last_update,
            state=State.subscribed,
        )

        tiny_db_storage.upsert(registration)

        assert tiny_db.get(Query().email == "*****@*****.**") == {
            "email": "*****@*****.**",
            "last_update": last_update.isoformat(),
            "state": "subscribed",
            "confirm_action": None,
            "confirm_token": None,
        }

    def test_upsert_of_existing_entity(self, tiny_db, tiny_db_storage):
        first_update = datetime(2019, 10, 25, 13, 37)
        registration = Registration(
            email=Email("*****@*****.**"),
            last_update=first_update,
            state=State.subscribed,
        )

        tiny_db_storage.upsert(registration)

        last_update = first_update + timedelta(days=1)
        registration.last_update = last_update
        tiny_db_storage.upsert(registration)

        assert tiny_db.get(Query().email == "*****@*****.**") == {
            "email": "*****@*****.**",
            "last_update": last_update.isoformat(),
            "state": "subscribed",
            "confirm_action": None,
            "confirm_token": None,
        }

    def test_find_of_non_exsting_entity_returns_none(self, tiny_db_storage):
        assert tiny_db_storage.find(Email("*****@*****.**")) is None

    def test_find_returns_matching_entity(self, tiny_db, tiny_db_storage):
        last_update = datetime(2019, 10, 25, 13, 37)
        tiny_db.insert({
            "email": "*****@*****.**",
            "last_update": last_update.isoformat(),
            "state": "subscribed",
            "confirm_action": None,
            "confirm_token": None,
        })

        assert tiny_db_storage.find(Email("*****@*****.**")) == Registration(
            email=Email("*****@*****.**"),
            last_update=last_update,
            state=State.subscribed,
        )

    def test_delete_existing_entity(self, tiny_db, tiny_db_storage):
        tiny_db.insert({
            "email":
            "*****@*****.**",
            "last_update":
            datetime(2019, 10, 25, 13, 37).isoformat(),
            "state":
            "subscribed",
            "confirm_action":
            None,
            "confirm_token":
            None,
        })

        tiny_db_storage.delete(Email("*****@*****.**"))

        assert tiny_db.get(Query().email == "*****@*****.**") is None

    def test_delete_non_existing_entity(self, tiny_db, tiny_db_storage):
        tiny_db_storage.delete(Email("*****@*****.**"))
        assert tiny_db.get(Query().email == "*****@*****.**") is None

    @pytest.mark.parametrize(
        "instance",
        (
            Registration(
                email=Email("*****@*****.**"),
                last_update=datetime(2019, 10, 25, 13, 37),
                state=State.subscribed,
                confirm_action=None,
                confirm_token=None,
            ),
            Registration(
                email=Email("*****@*****.**"),
                last_update=datetime(2019, 10, 25, 13, 38),
                state=State.pending_subscribe,
                confirm_action=Action.subscribe,
                confirm_token=Token(b"token"),
            ),
        ),
    )
    def test_roundtrip(self, instance, tiny_db_storage):
        tiny_db_storage.upsert(instance)
        assert tiny_db_storage.find(instance.email) == instance

    def test_drop_old_unconfirmed(self, tiny_db_storage):
        reference_datetime = datetime(2019, 10, 25, 13, 18)
        fresh = (
            Registration(
                email=Email("*****@*****.**"),
                last_update=reference_datetime - timedelta(days=1),
                state=State.pending_subscribe,
                confirm_action=Action.subscribe,
                confirm_token=Token(b"token"),
            ),
            Registration(
                email=Email("*****@*****.**"),
                last_update=reference_datetime - timedelta(days=3),
                state=State.subscribed,
            ),
            Registration(
                email=Email("*****@*****.**"),
                last_update=reference_datetime - timedelta(days=3),
                state=State.pending_unsubscribe,
                confirm_action=Action.unsubscribe,
                confirm_token=Token(b"token"),
            ),
        )
        old = (Registration(
            email=Email("*****@*****.**"),
            last_update=reference_datetime - timedelta(days=3),
            state=State.pending_subscribe,
            confirm_action=Action.subscribe,
            confirm_token=Token(b"token"),
        ), )

        for r in fresh + old:
            tiny_db_storage.upsert(r)

        tiny_db_storage.drop_old_unconfirmed(drop_before=reference_datetime -
                                             timedelta(days=2))

        assert tuple(sorted(tiny_db_storage.all(),
                            key=lambda r: r.email)) == fresh

    def test_get_unset_last_seen_storage(self, tiny_db_storage):
        assert tiny_db_storage.get_last_seen() is None

    def test_last_seen_storage(self, tiny_db_storage):
        now = datetime.now(tz=timezone(timedelta(hours=1)))
        tiny_db_storage.set_last_seen(now)
        assert tiny_db_storage.get_last_seen() == now

    def test_last_seen_storage_with_legacy_timezone_unaware_date(
            self, tiny_db, tiny_db_storage):
        now = datetime.now(tz=timezone.utc)
        tiny_db.insert({
            "key": "last_seen",
            "value": now.replace(tzinfo=None).isoformat()
        })
        assert tiny_db_storage.get_last_seen() == now

    def test_get_all_active_subscribers(self, tiny_db_storage):
        active = (
            Registration(
                email=Email("*****@*****.**"),
                last_update=datetime.utcnow(),
                state=State.subscribed,
            ),
            Registration(
                email=Email("*****@*****.**"),
                last_update=datetime.now(),
                state=State.pending_unsubscribe,
                confirm_action=Action.unsubscribe,
                confirm_token=Token(b"token"),
            ),
        )
        inactive = (Registration(
            email=Email("*****@*****.**"),
            last_update=datetime.now(),
            state=State.pending_subscribe,
            confirm_action=Action.subscribe,
            confirm_token=Token(b"token"),
        ), )

        for r in active + inactive:
            tiny_db_storage.upsert(r)

        result = tiny_db_storage.get_all_active_subscribers()

        assert tuple(sorted(result, key=lambda r: r.email)) == active
示例#15
0
 def __next__(self):
     self.generated_tokens.append(
         Token(b"token" + bytes(len(self.generated_tokens))))
     return self.generated_tokens[-1]
示例#16
0
    def test_confirm_for_unknown_email_raises_exception(
            self, registration_service):
        given_email = Email("*****@*****.**")

        with pytest.raises(UnauthorizedException):
            registration_service.confirm(given_email, Token(b"token"))