def persist_notification(template_id,
                         template_version,
                         recipient,
                         service_id,
                         personalisation,
                         notification_type,
                         api_key_id,
                         key_type,
                         created_at=None,
                         job_id=None,
                         job_row_number=None,
                         reference=None,
                         notification_id=None):
    notification = Notification(
        id=notification_id,
        template_id=template_id,
        template_version=template_version,
        to=recipient,
        service_id=service_id,
        personalisation=personalisation,
        notification_type=notification_type,
        api_key_id=api_key_id,
        key_type=key_type,
        created_at=created_at or datetime.utcnow(),
        job_id=job_id,
        job_row_number=job_row_number,
        client_reference=reference
    )
    dao_create_notification(notification)
    redis_store.incr(redis.daily_limit_cache_key(service_id))
    return notification
Exemple #2
0
def check_service_over_daily_message_limit(key_type, service):
    if key_type != KEY_TYPE_TEST:
        if current_app.config['REDIS_ENABLED']:
            cache_key = daily_limit_cache_key(service.id)
            service_stats = redis_store.get(cache_key)
            if not service_stats:
                service_stats = services_dao.fetch_todays_total_message_count(
                    service.id)
                redis_store.set(cache_key, service_stats, ex=3600)
            if int(service_stats) >= service.message_limit:
                current_app.logger.error(
                    "service {} has been rate limited for daily use sent {} limit {}"
                    .format(service.id, int(service_stats),
                            service.message_limit))
                raise TooManyRequestsError(service.message_limit)
            return

        # TODO: remove this block when redis is re-enabled in live
        service_stats = services_dao.fetch_todays_total_message_count(
            service.id)
        if int(service_stats) >= service.message_limit:
            current_app.logger.error(
                "service {} has been rate limited for daily use sent {} limit {}"
                .format(service.id, int(service_stats), service.message_limit))
            raise TooManyRequestsError(service.message_limit)
def check_service_message_limit(key_type, service):
    if key_type != KEY_TYPE_TEST:
        cache_key = redis.daily_limit_cache_key(service.id)
        service_stats = redis_store.get(cache_key)
        if not service_stats:
            service_stats = services_dao.fetch_todays_total_message_count(service.id)
            redis_store.set(cache_key, service_stats, ex=3600)
        if int(service_stats) >= service.message_limit:
            raise TooManyRequestsError(service.message_limit)
def check_service_over_daily_message_limit(key_type, service):
    if key_type != KEY_TYPE_TEST and current_app.config["REDIS_ENABLED"]:
        cache_key = daily_limit_cache_key(service.id)
        messages_sent = redis_store.get(cache_key)
        if not messages_sent:
            messages_sent = services_dao.fetch_todays_total_message_count(
                service.id)
            redis_store.set(cache_key,
                            messages_sent,
                            ex=int(timedelta(hours=1).total_seconds()))

        warn_about_daily_message_limit(service, int(messages_sent))
Exemple #5
0
def update_service(service_id):
    req_json = request.get_json()
    fetched_service = dao_fetch_service_by_id(service_id)
    # Capture the status change here as Marshmallow changes this later
    service_going_live = fetched_service.restricted and not req_json.get(
        "restricted", True)
    message_limit_changed = fetched_service.message_limit != req_json.get(
        "message_limit", fetched_service.message_limit)
    current_data = dict(service_schema.dump(fetched_service).data.items())

    current_data.update(request.get_json())

    service = service_schema.load(current_data).data

    if "email_branding" in req_json:
        email_branding_id = req_json["email_branding"]
        service.email_branding = None if not email_branding_id else EmailBranding.query.get(
            email_branding_id)
    if "letter_branding" in req_json:
        letter_branding_id = req_json["letter_branding"]
        service.letter_branding = None if not letter_branding_id else LetterBranding.query.get(
            letter_branding_id)

    dao_update_service(service)

    if message_limit_changed:
        redis_store.delete(daily_limit_cache_key(service_id))
        redis_store.delete(near_daily_limit_cache_key(service_id))
        redis_store.delete(over_daily_limit_cache_key(service_id))
        if not fetched_service.restricted:
            _warn_service_users_about_message_limit_changed(
                service_id, current_data)

    if service_going_live:
        _warn_services_users_about_going_live(service_id, current_data)

        try:
            # Two scenarios, if there is a user that has requested to go live, we will use that user
            # to create a user-service/contact-deal pair between notify and zendesk sell
            # If by any chance there is no tracked request to a user, notify will try to identify the user
            # that created the service and then create a user-service/contact-deal relationship
            if service.go_live_user_id:
                user = get_user_by_id(service.go_live_user_id)
            else:
                user = dao_fetch_service_creator(service.id)

            ZenDeskSell().send_go_live_service(service, user)
        except Exception as e:
            current_app.logger.exception(e)

    return jsonify(data=service_schema.dump(fetched_service).data), 200
Exemple #6
0
def check_service_over_daily_message_limit(key_type, service):
    if key_type != KEY_TYPE_TEST and current_app.config['REDIS_ENABLED']:
        cache_key = daily_limit_cache_key(service.id)
        service_stats = redis_store.get(cache_key)
        if not service_stats:
            service_stats = services_dao.fetch_todays_total_message_count(
                service.id)
            redis_store.set(cache_key, service_stats, ex=3600)

        if (service.message_limit - int(service_stats) <= 100):
            current_app.logger.info(
                'service {} nearing daily limit {} - {}'.format(
                    service.id, service.message_limit, service_stats))

        if int(service_stats) >= service.message_limit:
            current_app.logger.info(
                "service {} has been rate limited for daily use sent {} limit {}"
                .format(service.id, int(service_stats), service.message_limit))
            raise TooManyRequestsError(service.message_limit)
def persist_notification(*,
                         template_id,
                         template_version,
                         recipient,
                         service,
                         personalisation,
                         notification_type,
                         api_key_id,
                         key_type,
                         created_at=None,
                         job_id=None,
                         job_row_number=None,
                         reference=None,
                         client_reference=None,
                         notification_id=None,
                         simulated=False,
                         created_by_id=None,
                         status=NOTIFICATION_CREATED,
                         reply_to_text=None,
                         billable_units=None,
                         postage=None,
                         document_download_count=None,
                         updated_at=None):
    notification_created_at = created_at or datetime.utcnow()
    if not notification_id:
        notification_id = uuid.uuid4()
    notification = Notification(
        id=notification_id,
        template_id=template_id,
        template_version=template_version,
        to=recipient,
        service_id=service.id,
        personalisation=personalisation,
        notification_type=notification_type,
        api_key_id=api_key_id,
        key_type=key_type,
        created_at=notification_created_at,
        job_id=job_id,
        job_row_number=job_row_number,
        client_reference=client_reference,
        reference=reference,
        created_by_id=created_by_id,
        status=status,
        reply_to_text=reply_to_text,
        billable_units=billable_units,
        document_download_count=document_download_count,
        updated_at=updated_at)

    if notification_type == SMS_TYPE:
        formatted_recipient = validate_and_format_phone_number(
            recipient, international=True)
        recipient_info = get_international_phone_info(formatted_recipient)
        notification.normalised_to = formatted_recipient
        notification.international = recipient_info.international
        notification.phone_prefix = recipient_info.country_prefix
        notification.rate_multiplier = recipient_info.billable_units
    elif notification_type == EMAIL_TYPE:
        notification.normalised_to = format_email_address(notification.to)
    elif notification_type == LETTER_TYPE:
        notification.postage = postage
        notification.international = postage in INTERNATIONAL_POSTAGE_TYPES
        notification.normalised_to = ''.join(notification.to.split()).lower()

    # if simulated create a Notification model to return but do not persist the Notification to the dB
    if not simulated:
        dao_create_notification(notification)
        # Only keep track of the daily limit for trial mode services.
        if service.restricted and key_type != KEY_TYPE_TEST:
            if redis_store.get(redis.daily_limit_cache_key(service.id)):
                redis_store.incr(redis.daily_limit_cache_key(service.id))

        current_app.logger.info("{} {} created at {}".format(
            notification_type, notification_id, notification_created_at))
    return notification
def test_should_build_cache_key_service_and_action(sample_service):
    with freeze_time("2016-01-01 12:00:00.000000"):
        assert daily_limit_cache_key(
            sample_service.id) == '{}-2016-01-01-count'.format(
                sample_service.id)
def persist_notification(*,
                         template_id,
                         template_version,
                         recipient=None,
                         service,
                         personalisation,
                         notification_type,
                         api_key_id,
                         key_type,
                         created_at=None,
                         job_id=None,
                         job_row_number=None,
                         reference=None,
                         client_reference=None,
                         notification_id=None,
                         simulated=False,
                         created_by_id=None,
                         status=NOTIFICATION_CREATED,
                         reply_to_text=None,
                         billable_units=None,
                         postage=None,
                         template_postage=None,
                         recipient_identifier=None):
    notification_created_at = created_at or datetime.utcnow()
    if not notification_id:
        notification_id = uuid.uuid4()
    notification = Notification(id=notification_id,
                                template_id=template_id,
                                template_version=template_version,
                                to=recipient,
                                service_id=service.id,
                                service=service,
                                personalisation=personalisation,
                                notification_type=notification_type,
                                api_key_id=api_key_id,
                                key_type=key_type,
                                created_at=notification_created_at,
                                job_id=job_id,
                                job_row_number=job_row_number,
                                client_reference=client_reference,
                                reference=reference,
                                created_by_id=created_by_id,
                                status=status,
                                reply_to_text=reply_to_text,
                                billable_units=billable_units)
    if accept_recipient_identifiers_enabled() and recipient_identifier:
        _recipient_identifier = RecipientIdentifier(
            notification_id=notification_id,
            id_type=recipient_identifier['id_type'],
            id_value=recipient_identifier['id_value'])
        notification.recipient_identifiers.set(_recipient_identifier)

    if notification_type == SMS_TYPE and notification.to:
        formatted_recipient = validate_and_format_phone_number(
            recipient, international=True)
        recipient_info = get_international_phone_info(formatted_recipient)
        notification.normalised_to = formatted_recipient
        notification.international = recipient_info.international
        notification.phone_prefix = recipient_info.country_prefix
        notification.rate_multiplier = recipient_info.billable_units
    elif notification_type == EMAIL_TYPE and notification.to:
        notification.normalised_to = format_email_address(notification.to)
    elif notification_type == LETTER_TYPE:
        notification.postage = postage or template_postage

    # if simulated create a Notification model to return but do not persist the Notification to the dB
    if not simulated:
        dao_create_notification(notification)
        if key_type != KEY_TYPE_TEST:
            if redis_store.get(redis.daily_limit_cache_key(service.id)):
                redis_store.incr(redis.daily_limit_cache_key(service.id))

        current_app.logger.info("{} {} created at {}".format(
            notification_type, notification_id, notification_created_at))
    return notification
Exemple #10
0
def persist_notification(
    *,
    template_id,
    template_version,
    recipient,
    service,
    personalisation,
    notification_type,
    api_key_id,
    key_type,
    created_at=None,
    job_id=None,
    job_row_number=None,
    reference=None,
    client_reference=None,
    notification_id=None,
    simulated=False,
    created_by_id=None,
    status=NOTIFICATION_CREATED,
    reply_to_text=None,
    status_callback_url=None,
    status_callback_bearer_token=None,
):
    notification_created_at = created_at or datetime.utcnow()
    if not notification_id:
        notification_id = uuid.uuid4()
    notification = Notification(
        id=notification_id,
        template_id=template_id,
        template_version=template_version,
        to=recipient,
        service_id=service.id,
        service=service,
        personalisation=personalisation,
        notification_type=notification_type,
        api_key_id=api_key_id,
        key_type=key_type,
        created_at=notification_created_at,
        job_id=job_id,
        job_row_number=job_row_number,
        client_reference=client_reference,
        reference=reference,
        created_by_id=created_by_id,
        status=status,
        reply_to_text=reply_to_text,
        status_callback_url=status_callback_url,
        status_callback_bearer_token=status_callback_bearer_token,
    )

    if notification_type == SMS_TYPE:
        formatted_recipient = validate_and_format_phone_number_and_allow_international(
            recipient)
        recipient_info = get_international_phone_info(formatted_recipient)
        notification.normalised_to = formatted_recipient
        notification.international = recipient_info.international
        notification.phone_prefix = recipient_info.country_prefix
        notification.rate_multiplier = recipient_info.billable_units

        # We can't use a sender name/ID if the text is sending to an
        # international number. At the time of writing, this is because Telstra
        # won't send to an international number unless sending from the number
        # associated with the subscription. Additionally, Twilio can send from a
        # sender name/ID, however, it requires configuration and it depends on
        # the countries in play.
        if notification.international:
            notification.reply_to_text = None

    elif notification_type == EMAIL_TYPE:
        notification.normalised_to = format_email_address(notification.to)

    # if simulated create a Notification model to return but do not persist the Notification to the dB
    if not simulated:
        dao_create_notification(notification)
        if key_type != KEY_TYPE_TEST:
            if redis_store.get(redis.daily_limit_cache_key(service.id)):
                redis_store.incr(redis.daily_limit_cache_key(service.id))
            if redis_store.get_all_from_hash(
                    cache_key_for_service_template_counter(service.id)):
                redis_store.increment_hash_value(
                    cache_key_for_service_template_counter(service.id),
                    template_id)

            increment_template_usage_cache(service.id, template_id,
                                           notification_created_at)

        current_app.logger.info("{} {} created at {}".format(
            notification_type, notification_id, notification_created_at))
    return notification