Example #1
0
def test_purge_signup_tokens(db):
    with auth_api_session() as (auth_api, metadata_interceptor):
        reply = auth_api.Signup(auth_pb2.SignupReq(email="*****@*****.**"))

    # send email
    process_job()

    with session_scope() as session:
        signup_token = session.query(SignupToken).one()
        signup_token.expiry = func.now()
        assert session.query(SignupToken).count() == 1

    queue_job(BackgroundJobType.purge_signup_tokens, empty_pb2.Empty())

    # purge tokens
    process_job()

    with session_scope() as session:
        assert session.query(SignupToken).count() == 0

    with session_scope() as session:
        assert session.query(BackgroundJob).filter(
            BackgroundJob.state == BackgroundJobState.completed).count() == 2
        assert session.query(BackgroundJob).filter(
            BackgroundJob.state != BackgroundJobState.completed).count() == 0
Example #2
0
def test_purge_password_reset_tokens(db):
    user, api_token = generate_user()

    with session_scope() as session:
        password_reset_token = PasswordResetToken(token=urlsafe_secure_token(),
                                                  user=user,
                                                  expiry=now())
        session.add(password_reset_token)
        assert session.execute(
            select(func.count()).select_from(
                PasswordResetToken)).scalar_one() == 1

    queue_job(BackgroundJobType.purge_password_reset_tokens, empty_pb2.Empty())
    process_job()

    with session_scope() as session:
        assert session.execute(
            select(func.count()).select_from(
                PasswordResetToken)).scalar_one() == 0

    with session_scope() as session:
        assert (session.execute(
            select(func.count()).select_from(BackgroundJob).where(
                BackgroundJob.state ==
                BackgroundJobState.completed)).scalar_one() == 1)
        assert (session.execute(
            select(func.count()).select_from(BackgroundJob).where(
                BackgroundJob.state != BackgroundJobState.completed)).
                scalar_one() == 0)
Example #3
0
def test_job_retry(db):
    queue_job(BackgroundJobType.purge_login_tokens, empty_pb2.Empty())

    called_count = 0

    def mock_handler(payload):
        nonlocal called_count
        called_count += 1
        raise Exception()

    MOCK_JOBS = {
        BackgroundJobType.purge_login_tokens: (empty_pb2.Empty, mock_handler),
    }
    create_prometheus_server(registry=job_process_registry, port=8001)
    with patch("couchers.jobs.worker.JOBS", MOCK_JOBS):
        process_job()
        with session_scope() as session:
            assert (session.execute(
                select(func.count()).select_from(BackgroundJob).where(
                    BackgroundJob.state ==
                    BackgroundJobState.error)).scalar_one() == 1)
            assert (session.execute(
                select(func.count()).select_from(BackgroundJob).where(
                    BackgroundJob.state != BackgroundJobState.error)).
                    scalar_one() == 0)

            session.execute(select(
                BackgroundJob)).scalar_one().next_attempt_after = func.now()
        process_job()
        with session_scope() as session:
            session.execute(select(
                BackgroundJob)).scalar_one().next_attempt_after = func.now()
        process_job()
        with session_scope() as session:
            session.execute(select(
                BackgroundJob)).scalar_one().next_attempt_after = func.now()
        process_job()
        with session_scope() as session:
            session.execute(select(
                BackgroundJob)).scalar_one().next_attempt_after = func.now()
        process_job()

    with session_scope() as session:
        assert (session.execute(
            select(func.count()).select_from(BackgroundJob).where(
                BackgroundJob.state ==
                BackgroundJobState.failed)).scalar_one() == 1)
        assert (session.execute(
            select(func.count()).select_from(BackgroundJob).where(
                BackgroundJob.state != BackgroundJobState.failed)).scalar_one(
                ) == 0)

    _check_job_counter("purge_login_tokens", "error", "4", "Exception")
    _check_job_counter("purge_login_tokens", "failed", "5", "Exception")
Example #4
0
def queue_email(sender_name, sender_email, recipient, subject, plain, html):
    payload = jobs_pb2.SendEmailPayload(
        sender_name=sender_name,
        sender_email=sender_email,
        recipient=recipient,
        subject=subject,
        plain=plain,
        html=html,
    )
    queue_job(
        job_type=BackgroundJobType.send_email,
        payload=payload,
    )
Example #5
0
def test_enforce_community_memberships(db):
    queue_job(BackgroundJobType.enforce_community_membership,
              empty_pb2.Empty())
    process_job()

    with session_scope() as session:
        assert (session.execute(
            select(func.count()).select_from(BackgroundJob).where(
                BackgroundJob.state ==
                BackgroundJobState.completed)).scalar_one() == 1)
        assert (session.execute(
            select(func.count()).select_from(BackgroundJob).where(
                BackgroundJob.state != BackgroundJobState.completed)).
                scalar_one() == 0)
Example #6
0
def test_purge_account_deletion_tokens(db):
    user, api_token = generate_user()
    user2, api_token2 = generate_user()
    user3, api_token3 = generate_user()

    with session_scope() as session:
        """
        3 cases:
        1) Token is valid
        2) Token expired but account retrievable
        3) Account is irretrievable (and expired)
        """
        account_deletion_tokens = [
            AccountDeletionToken(token=urlsafe_secure_token(),
                                 user=user,
                                 expiry=now() - timedelta(hours=2)),
            AccountDeletionToken(token=urlsafe_secure_token(),
                                 user=user2,
                                 expiry=now()),
            AccountDeletionToken(token=urlsafe_secure_token(),
                                 user=user3,
                                 expiry=now() + timedelta(hours=5)),
        ]
        for token in account_deletion_tokens:
            session.add(token)
        assert session.execute(
            select(func.count()).select_from(
                AccountDeletionToken)).scalar_one() == 3

    queue_job(BackgroundJobType.purge_account_deletion_tokens,
              empty_pb2.Empty())
    process_job()

    with session_scope() as session:
        assert session.execute(
            select(func.count()).select_from(
                AccountDeletionToken)).scalar_one() == 1

    with session_scope() as session:
        assert (session.execute(
            select(func.count()).select_from(BackgroundJob).where(
                BackgroundJob.state ==
                BackgroundJobState.completed)).scalar_one() == 1)
        assert (session.execute(
            select(func.count()).select_from(BackgroundJob).where(
                BackgroundJob.state != BackgroundJobState.completed)).
                scalar_one() == 0)
Example #7
0
def _run_job_and_schedule(sched, schedule_id):
    job_type, frequency = SCHEDULE[schedule_id]
    logger.info(f"Processing job of type {job_type}")

    # wake ourselves up after frequency
    sched.enter(
        frequency.total_seconds(),
        1,
        _run_job_and_schedule,
        argument=(
            sched,
            schedule_id,
        ),
    )

    # queue the job
    queue_job(job_type, empty_pb2.Empty())
Example #8
0
def notify(
    *,
    user_id,
    topic,
    key,
    action,
    title,
    link,
    avatar_key=None,
    icon=None,
    content=None,
):
    """
    Queues a notification given the notification and a target, i.e. a tuple (user_id, topic, key), and an action.

    Notifications are sent to user identified by user_id, and are collapsed/grouped based on the combination of
    (topic, key).

    For example, topic may be "chat" for a group chat/direct message, and the key might be the chat id; so that messages
    in the same group chat show up in one group.

    The action is a simple identifier describing the action that caused the notification. For the above example, the
    action might be "add_admin" if the notification was caused by another user adding an admin into the gorup chat.

    Each different notification type should have its own action.
    """
    with session_scope() as session:
        notification = Notification(
            user_id=user_id,
            topic_action=enum_from_topic_action[topic, action],
            key=key,
            avatar_key=avatar_key,
            icon=icon,
            title=title,
            content=content,
            link=link,
        )
        session.add(notification)
        session.flush()
        notification_id = notification.id

    queue_job(
        job_type=BackgroundJobType.handle_notification,
        payload=jobs_pb2.HandleNotificationPayload(
            notification_id=notification_id, ),
    )
Example #9
0
def test_purge_login_tokens(db):
    user, api_token = generate_user()

    with session_scope() as session:
        login_token, expiry_text = new_login_token(session, user)
        login_token.expiry = func.now()
        assert session.query(LoginToken).count() == 1

    queue_job(BackgroundJobType.purge_login_tokens, empty_pb2.Empty())
    process_job()

    with session_scope() as session:
        assert session.query(LoginToken).count() == 0

    with session_scope() as session:
        assert session.query(BackgroundJob).filter(
            BackgroundJob.state == BackgroundJobState.completed).count() == 1
        assert session.query(BackgroundJob).filter(
            BackgroundJob.state != BackgroundJobState.completed).count() == 0
Example #10
0
def _add_message_to_subscription(session, subscription, **kwargs):
    """
    Creates a new message for a subscription, from the user whose subscription that is. Updates last seen message id

    Specify the keyword args for Message
    """
    message = Message(conversation=subscription.group_chat.conversation, author_id=subscription.user_id, **kwargs)

    session.add(message)
    session.flush()

    subscription.last_seen_message_id = message.id

    # generate notifications in the background
    queue_job(
        job_type=BackgroundJobType.generate_message_notifications,
        payload=jobs_pb2.GenerateMessageNotificationsPayload(
            message_id=message.id,
        ),
    )

    return message
Example #11
0
def test_job_retry(db):
    queue_job(BackgroundJobType.purge_login_tokens, empty_pb2.Empty())

    called_count = 0

    def mock_handler(payload):
        nonlocal called_count
        called_count += 1
        raise Exception()

    MOCK_JOBS = {
        BackgroundJobType.purge_login_tokens: (empty_pb2.Empty, mock_handler),
    }

    with patch("couchers.jobs.worker.JOBS", MOCK_JOBS):
        process_job()
        with session_scope() as session:
            assert session.query(BackgroundJob).filter(
                BackgroundJob.state == BackgroundJobState.error).count() == 1
            assert session.query(BackgroundJob).filter(
                BackgroundJob.state != BackgroundJobState.error).count() == 0

            session.query(BackgroundJob).one().next_attempt_after = func.now()
        process_job()
        with session_scope() as session:
            session.query(BackgroundJob).one().next_attempt_after = func.now()
        process_job()
        with session_scope() as session:
            session.query(BackgroundJob).one().next_attempt_after = func.now()
        process_job()
        with session_scope() as session:
            session.query(BackgroundJob).one().next_attempt_after = func.now()
        process_job()

    with session_scope() as session:
        assert session.query(BackgroundJob).filter(
            BackgroundJob.state == BackgroundJobState.failed).count() == 1
        assert session.query(BackgroundJob).filter(
            BackgroundJob.state != BackgroundJobState.failed).count() == 0