get_invited_org_users_for_organisation)
from app.dao.templates_dao import dao_get_template_by_id
from app.errors import register_errors
from app.models import EMAIL_TYPE, KEY_TYPE_NORMAL, InvitedOrganisationUser
from app.notifications.process_notifications import persist_notification, send_notification_to_queue
from app.schema_validation import validate
from app.organisation.organisation_schema import (
    post_create_invited_org_user_status_schema,
    post_update_invited_org_user_status_schema)

organisation_invite_blueprint = Blueprint(
    'organisation_invite',
    __name__,
    url_prefix='/organisation/<uuid:organisation_id>/invite')

register_errors(organisation_invite_blueprint)


@organisation_invite_blueprint.route('', methods=['POST'])
def invite_user_to_org(organisation_id):
    data = request.get_json()
    validate(data, post_create_invited_org_user_status_schema)

    invited_org_user = InvitedOrganisationUser(
        email_address=data['email_address'],
        invited_by_id=data['invited_by'],
        organisation_id=organisation_id)
    save_invited_org_user(invited_org_user)

    template = dao_get_template_by_id(
        current_app.config['ORGANISATION_INVITATION_EMAIL_TEMPLATE_ID'])
import iso8601
from flask import jsonify, Blueprint, current_app, request, abort
from notifications_utils.recipients import try_validate_and_format_phone_number
from notifications_utils.timezones import convert_bst_to_utc

from app import statsd_client
from app.celery import tasks
from app.config import QueueNames
from app.dao.services_dao import dao_fetch_service_by_inbound_number
from app.dao.inbound_sms_dao import dao_create_inbound_sms
from app.models import InboundSms, INBOUND_SMS_TYPE, SMS_TYPE
from app.errors import register_errors

receive_notifications_blueprint = Blueprint('receive_notifications', __name__)
register_errors(receive_notifications_blueprint)


@receive_notifications_blueprint.route('/notifications/sms/receive/mmg',
                                       methods=['POST'])
def receive_mmg_sms():
    """
    {
        'MSISDN': '447123456789'
        'Number': '40604',
        'Message': 'some+uri+encoded+message%3A',
        'ID': 'SOME-MMG-SPECIFIC-ID',
        'DateRecieved': '2017-05-21+11%3A56%3A11'
    }
    """
    post_data = request.get_json()
from flask import Blueprint
from flask import current_app
from flask import json
from flask import request, jsonify

from app.errors import InvalidRequest, register_errors
from app.notifications.process_client_response import validate_callback_data, process_sms_client_response

sms_callback_blueprint = Blueprint("sms_callback",
                                   __name__,
                                   url_prefix="/notifications/sms")
register_errors(sms_callback_blueprint)


@sms_callback_blueprint.route('/mmg', methods=['POST'])
def process_mmg_response():
    client_name = 'MMG'
    data = json.loads(request.data)
    errors = validate_callback_data(data=data,
                                    fields=['status', 'CID'],
                                    client_name=client_name)
    if errors:
        raise InvalidRequest(errors, status_code=400)

    success, errors = process_sms_client_response(
        status=str(data.get('status')),
        provider_reference=data.get('CID'),
        client_name=client_name)

    safe_to_log = data.copy()
    safe_to_log.pop("MSISDN")
from flask import Blueprint, jsonify, request

from app import DATETIME_FORMAT
from app.dao.notifications_dao import dao_get_last_date_template_was_used
from app.dao.templates_dao import dao_get_template_by_id_and_service_id
from app.dao.fact_notification_status_dao import fetch_notification_status_for_service_for_today_and_7_previous_days

from app.errors import register_errors, InvalidRequest

template_statistics = Blueprint(
    'template_statistics',
    __name__,
    url_prefix='/service/<service_id>/template-statistics')

register_errors(template_statistics)


@template_statistics.route('')
def get_template_statistics_for_service_by_day(service_id):
    whole_days = request.args.get('whole_days',
                                  request.args.get('limit_days', ''))
    try:
        whole_days = int(whole_days)
    except ValueError:
        error = '{} is not an integer'.format(whole_days)
        message = {'whole_days': [error]}
        raise InvalidRequest(message, status_code=400)

    if whole_days < 0 or whole_days > 7:
        raise InvalidRequest(
            {'whole_days': ['whole_days must be between 0 and 7']},
from flask import Blueprint
from flask import current_app
from flask import json
from flask import request, jsonify

from app import statsd_client
from app.errors import InvalidRequest, register_errors
from app.notifications.process_client_response import validate_callback_data, process_shortnumber_keyword_client_response
from app.dao.services_dao import dao_fetch_service_by_inbound_shortnumber
from app.models import INBOUND_SMS_KEYWORD_TYPE, SMS_TYPE

shortnumber_keyword_callback_blueprint = Blueprint(
    "shortnumber_keyword_callback",
    __name__,
    url_prefix="/notifications/sms/shortnumber_keyword")
register_errors(shortnumber_keyword_callback_blueprint)


@shortnumber_keyword_callback_blueprint.route('/sinch', methods=['POST'])
def process_sinch_response():
    client_name = 'Sinch'

    data = json.loads(request.data)
    errors = validate_callback_data(
        data=data,
        fields=['id', 'from', 'to', 'body', 'received_at'],
        client_name=client_name)

    if errors:
        raise InvalidRequest(errors, status_code=400)
Exemple #6
0
    dao_update_template_reply_to,
    get_precompiled_letter_template,
)
from app.errors import InvalidRequest, register_errors
from app.letters.utils import get_letter_pdf
from app.models import LETTER_TYPE, SECOND_CLASS, SMS_TYPE, Template
from app.notifications.validators import check_reply_to, service_has_permission
from app.schema_validation import validate
from app.schemas import template_history_schema, template_schema
from app.template.template_schemas import post_create_template_schema
from app.utils import get_public_notify_type_text, get_template_instance

template_blueprint = Blueprint(
    "template", __name__, url_prefix="/service/<uuid:service_id>/template")

register_errors(template_blueprint)


def _content_count_greater_than_limit(content, template_type):
    if template_type != SMS_TYPE:
        return False
    template = SMSMessageTemplate({
        "content": content,
        "template_type": template_type
    })
    return template.content_count > SMS_CHAR_COUNT_LIMIT


def validate_parent_folder(template_json):
    if template_json.get("parent_folder_id"):
        try:
    'service_sms_sender',
    __name__,
    url_prefix='/service/<uuid:service_id>/sms-sender')
service_sms_sender_blueprint.before_request(validate_admin_auth)
service_sms_sender_blueprint.before_request(_validate_service_exists)


@service_sms_sender_blueprint.errorhandler(SmsSenderDefaultValidationException)
@service_sms_sender_blueprint.errorhandler(
    SmsSenderInboundNumberIntegrityException)
def handle_errors(error):
    current_app.logger.info(error)
    return jsonify(result='error', message=str(error)), 400


register_errors(service_sms_sender_blueprint)


@service_sms_sender_blueprint.route('', methods=['GET'])
def get_service_sms_senders_for_service(service_id):
    sms_senders = dao_get_sms_senders_by_service_id(service_id=service_id)
    return jsonify([sms_sender.serialize() for sms_sender in sms_senders]), 200


@service_sms_sender_blueprint.route('', methods=['POST'])
def add_service_sms_sender(service_id):
    form = validate(request.get_json(), add_service_sms_sender_request)
    new_sms_sender = dao_add_sms_sender_for_service(service_id=service_id,
                                                    **form)
    return jsonify(new_sms_sender.serialize()), 201
Exemple #8
0
from itsdangerous import SignatureExpired

from notifications_utils.url_safe_token import check_token

from app.dao.invited_user_dao import get_invited_user_by_id

from app.errors import (
    register_errors,
    InvalidRequest
)

from app.schemas import invited_user_schema


accept_invite = Blueprint('accept_invite', __name__)
register_errors(accept_invite)


@accept_invite.route('/<token>', methods=['GET'])
def get_invited_user_by_token(token):

    max_age_seconds = 60 * 60 * 24 * current_app.config['INVITATION_EXPIRATION_DAYS']

    try:
        invited_user_id = check_token(token,
                                      current_app.config['SECRET_KEY'],
                                      current_app.config['DANGEROUS_SALT'],
                                      max_age_seconds)
    except SignatureExpired:
        errors = {'invitation':
                  ['Your invitation to GOV.UK Notify has expired. '
Exemple #9
0
    dao_get_inbound_sms_by_id,
    dao_get_inbound_sms_for_service,
    dao_get_paginated_most_recent_inbound_sms_by_user_number_for_service,
)
from app.dao.service_data_retention_dao import (
    fetch_service_data_retention_by_notification_type, )
from app.errors import register_errors
from app.inbound_sms.inbound_sms_schemas import (
    get_inbound_sms_for_service_schema, )
from app.schema_validation import validate

inbound_sms = Blueprint('inbound_sms',
                        __name__,
                        url_prefix='/service/<uuid:service_id>/inbound-sms')

register_errors(inbound_sms)


@inbound_sms.route('', methods=['POST'])
def post_inbound_sms_for_service(service_id):
    form = validate(request.get_json(), get_inbound_sms_for_service_schema)
    user_number = form.get('phone_number')

    if user_number:
        # we use this to normalise to an international phone number - but this may fail if it's an alphanumeric
        user_number = try_validate_and_format_phone_number(user_number,
                                                           international=True)

    inbound_data_retention = fetch_service_data_retention_by_notification_type(
        service_id, 'sms')
    limit_days = inbound_data_retention.days_of_retention if inbound_data_retention else 7
Exemple #10
0
from flask import (Blueprint, jsonify, current_app)

from itsdangerous import SignatureExpired, BadData

from notifications_utils.url_safe_token import check_token

from app.dao.invited_user_dao import get_invited_user_by_id
from app.dao.organisation_dao import dao_get_invited_organisation_user

from app.errors import (register_errors, InvalidRequest)

from app.schemas import invited_user_schema

accept_invite = Blueprint('accept_invite', __name__)
register_errors(accept_invite)


@accept_invite.route('/<invitation_type>/<token>', methods=['GET'])
def validate_invitation_token(invitation_type, token):

    max_age_seconds = 60 * 60 * 24 * current_app.config[
        'INVITATION_EXPIRATION_DAYS']

    try:
        invited_user_id = check_token(token, current_app.config['SECRET_KEY'],
                                      current_app.config['DANGEROUS_SALT'],
                                      max_age_seconds)
    except SignatureExpired:
        errors = {'invitation': 'invitation expired'}
        raise InvalidRequest(errors, status_code=400)
    except BadData:
Exemple #11
0
from flask import Blueprint, current_app
from flask_jwt_extended import jwt_required

from app.comms.stats import send_ga_event
from app.dao.emails_dao import dao_get_emails_sent_count
from app.na_celery.stats_tasks import send_num_subscribers_and_social_stats
from app.errors import register_errors

stats_blueprint = Blueprint('stats', __name__)
register_errors(stats_blueprint)


@stats_blueprint.route('/stats/social')
@jwt_required
def send_social_stats():
    current_app.logger.info("Sending social stats...")
    _, _, facebook_count, instagram_count = send_num_subscribers_and_social_stats(
        inc_subscribers=False)
    current_app.logger.info("Social stats %r, %r", facebook_count,
                            instagram_count)
    return f'facebook={facebook_count}, instagram={instagram_count}'


@stats_blueprint.route('/stats/subscribers_and_social')
@jwt_required
def send_subscribers_and_social_stats():
    current_app.logger.info("Sending subscribers and social stats...")
    num_subscribers, num_new_subscribers, facebook_count, instagram_count = send_num_subscribers_and_social_stats(
        inc_subscribers=True)
    current_app.logger.info("Social stats %r, %r", facebook_count,
                            instagram_count)
Exemple #12
0
from app.comms.email import get_nice_event_dates
from app.errors import register_errors, InvalidRequest

from app.models import (
    Email, EmailToMember, Member,
    ANNOUNCEMENT, EVENT, MAGAZINE, MANAGED_EMAIL_TYPES, READY, APPROVED, REJECTED
)
from app.routes.emails.schemas import (
    post_create_email_schema, post_update_email_schema, post_import_emails_schema, post_preview_email_schema,
    post_import_email_members_schema
)
from app.schema_validation import validate

emails_blueprint = Blueprint('emails', __name__)
register_errors(emails_blueprint)


@emails_blueprint.route('/email/preview', methods=['GET'])
def email_preview():
    data = json.loads(urlparse.unquote(request.args.get('data')))

    validate(data, post_preview_email_schema)

    current_app.logger.info('Email preview: {}'.format(data))

    html = get_email_html(**data)
    return html


@emails_blueprint.route('/email', methods=['POST'])
Exemple #13
0
from flask import Blueprint, jsonify

from app.dao.organisation_dao import dao_get_organisations, dao_get_organisation_by_id
from app.schemas import organisation_schema
from app.errors import register_errors

organisation_blueprint = Blueprint('organisation', __name__)
register_errors(organisation_blueprint)


@organisation_blueprint.route('', methods=['GET'])
def get_organisations():
    data = organisation_schema.dump(dao_get_organisations(), many=True).data
    return jsonify(organisations=data)


@organisation_blueprint.route('/<uuid:org_id>', methods=['GET'])
def get_organisation_by_id(org_id):
    data = organisation_schema.dump(dao_get_organisation_by_id(org_id)).data
    return jsonify(organisation=data)
Exemple #14
0
                                                     )
from app.schemas import (email_data_request_schema,
                         partial_email_data_request_schema, create_user_schema,
                         permission_schema, user_update_schema_load_json,
                         user_update_password_schema_load_json)
from app.errors import (register_errors, InvalidRequest)
from app.utils import url_with_token
from app.user.users_schema import (
    post_verify_code_schema,
    post_send_user_sms_code_schema,
    post_send_user_email_code_schema,
)
from app.schema_validation import validate

user_blueprint = Blueprint('user', __name__)
register_errors(user_blueprint)


@user_blueprint.errorhandler(IntegrityError)
def handle_integrity_error(exc):
    """
    Handle integrity errors caused by the auth type/mobile number check constraint
    """
    if 'ck_users_mobile_or_email_auth' in str(exc):
        # we don't expect this to trip, so still log error
        current_app.logger.exception(
            'Check constraint ck_users_mobile_or_email_auth triggered')
        return jsonify(
            result='error',
            message='Mobile number must be set if auth_type is set to sms_auth'
        ), 400
Exemple #15
0
    dao_get_speakers, dao_get_speaker_by_id, dao_get_speaker_by_name, dao_create_speaker, dao_update_speaker
)
from app.errors import register_errors
from app.models import Speaker
from app.schema_validation import validate
from app.routes.speakers.schemas import (
    post_create_speaker_schema,
    post_create_speakers_schema,
    post_import_speakers_schema,
    post_update_speaker_schema
)

speakers_blueprint = Blueprint('speakers', __name__)
speaker_blueprint = Blueprint('speaker', __name__)

register_errors(speakers_blueprint)
register_errors(speaker_blueprint)


@speakers_blueprint.route('/speakers')
@jwt_required
def get_speakers():
    speakers = [s.serialize() if s else None for s in dao_get_speakers()]
    return jsonify(speakers)


@speakers_blueprint.route('/speakers', methods=['POST'])
@jwt_required
def create_speakers():
    data = request.get_json(force=True)
Exemple #16
0
from app.schemas import provider_details_schema

from app.dao.provider_details_dao import (
    get_provider_details,
    get_provider_details_by_id,
    dao_update_provider_details
)

from app.errors import (
    register_errors,
    InvalidRequest
)

provider_details = Blueprint('provider_details', __name__)
register_errors(provider_details)


@provider_details.route('', methods=['GET'])
def get_providers():
    data = provider_details_schema.dump(get_provider_details(), many=True).data
    return jsonify(provider_details=data)


@provider_details.route('/<uuid:provider_details_id>', methods=['GET'])
def get_provider_by_id(provider_details_id):
    data = provider_details_schema.dump(get_provider_details_by_id(provider_details_id)).data
    return jsonify(provider_details=data)


@provider_details.route('/<uuid:provider_details_id>', methods=['POST'])
Exemple #17
0
from jsonschema.exceptions import ValidationError
from sqlalchemy.orm.exc import MultipleResultsFound, NoResultFound

from app import statsd_client
from app.clients.email.govdelivery_client import govdelivery_status_map
from app.dao import notifications_dao
from app.errors import register_errors, InvalidRequest
from app.schema_validation import validate
from .govelivery_schema import govdelivery_webhook_schema
from ..celery.service_callback_tasks import publish_complaint
from ..dao.complaint_dao import save_complaint
from ..models import Notification, Complaint

govdelivery_callback_blueprint = Blueprint(
    "govdelivery_callback", __name__, url_prefix="/notifications/govdelivery")
register_errors(govdelivery_callback_blueprint)


@govdelivery_callback_blueprint.route('', methods=['POST'])
def process_govdelivery_response():
    try:
        data = validate(request.form, govdelivery_webhook_schema)
        sid = data['sid']
        reference = data['message_url'].split("/")[-1]
        govdelivery_status = data['status']
        notify_status = govdelivery_status_map[govdelivery_status]

    except ValidationError as e:
        raise e
    except Exception as e:
        raise InvalidRequest(f'Error processing Govdelivery callback: {e}',
Exemple #18
0
    dao_get_template_versions
)
from notifications_utils.template import SMSMessageTemplate
from app.dao.services_dao import dao_fetch_service_by_id
from app.models import SMS_TYPE
from app.schemas import (template_schema, template_history_schema)

template = Blueprint('template', __name__, url_prefix='/service/<uuid:service_id>/template')

from app.errors import (
    register_errors,
    InvalidRequest
)
from app.utils import get_template_instance

register_errors(template)


def _content_count_greater_than_limit(content, template_type):
    if template_type != SMS_TYPE:
        return False
    template = SMSMessageTemplate({'content': content, 'template_type': template_type})
    return template.content_count > current_app.config.get('SMS_CHAR_COUNT_LIMIT')


@template.route('', methods=['POST'])
def create_template(service_id):
    fetched_service = dao_fetch_service_by_id(service_id=service_id)
    new_template = template_schema.load(request.get_json()).data
    new_template.service = fetched_service
    new_template.content = _strip_html(new_template.content)
Exemple #19
0
from flask import Blueprint, jsonify, current_app

from app import db
from app.errors import register_errors

base_blueprint = Blueprint('', __name__)
register_errors(base_blueprint)


@base_blueprint.route('/')
def get_info():
    current_app.logger.info('get_info')
    query = 'SELECT version_num FROM alembic_version'
    try:
        full_name = db.session.execute(query).fetchone()[0]
    except Exception as e:
        current_app.logger.error('Database exception: %r', e)
        full_name = 'Database error, check logs'
    return jsonify(environment=current_app.config['ENVIRONMENT'],
                   info=full_name,
                   commit=current_app.config['TRAVIS_COMMIT'])
Exemple #20
0
from app.dao.services_dao import dao_fetch_service_by_id
from app.errors import register_errors, InvalidRequest
from app.models import BroadcastMessage, BroadcastStatusType, BroadcastEvent, BroadcastEventMessageType
from app.celery.broadcast_message_tasks import send_broadcast_event
from app.broadcast_message.broadcast_message_schema import (
    create_broadcast_message_schema,
    update_broadcast_message_schema,
    update_broadcast_message_status_schema,
)
from app.schema_validation import validate

broadcast_message_blueprint = Blueprint(
    'broadcast_message',
    __name__,
    url_prefix='/service/<uuid:service_id>/broadcast-message')
register_errors(broadcast_message_blueprint)


def _parse_nullable_datetime(dt):
    if dt:
        return iso8601.parse_date(dt).replace(tzinfo=None)
    return dt


def _update_broadcast_message(broadcast_message, new_status, updating_user):
    if updating_user not in broadcast_message.service.users:
        raise InvalidRequest(
            f'User {updating_user.id} cannot approve broadcast_message {broadcast_message.id} from other service',
            status_code=400)

    if new_status not in BroadcastStatusType.ALLOWED_STATUS_TRANSITIONS[
Exemple #21
0
from app.utils import convert_utc_to_aet
from app.dao.annual_billing_dao import (
    dao_get_free_sms_fragment_limit_for_year,
    dao_get_all_free_sms_fragment_limit,
    dao_create_or_update_annual_billing_for_year,
    dao_update_annual_billing_for_future_years)
from app.billing.billing_schemas import create_or_update_free_sms_fragment_limit_schema
from app.errors import InvalidRequest
from app.schema_validation import validate
from app.dao.date_util import get_current_financial_year_start_year

billing_blueprint = Blueprint('billing',
                              __name__,
                              url_prefix='/service/<uuid:service_id>/billing')

register_errors(billing_blueprint)


@billing_blueprint.route('/monthly-usage')
def get_yearly_usage_by_month(service_id):
    try:
        year = int(request.args.get('year'))
        results = []
        for month in get_months_for_financial_year(year):
            billing_for_month = get_monthly_billing_by_notification_type(
                service_id, month, SMS_TYPE)
            if billing_for_month:
                results.append(
                    _transform_billing_for_month_sms(billing_for_month))
            letter_billing_for_month = get_monthly_billing_by_notification_type(
                service_id, month, LETTER_TYPE)
    get_service_inbound_api,
    reset_service_inbound_api,
    delete_service_inbound_api,
)
from app.dao.service_callback_api_dao import (
    save_service_callback_api,
    get_service_callback_api,
    reset_service_callback_api,
    delete_service_callback_api,
)

service_callback_blueprint = Blueprint('service_callback',
                                       __name__,
                                       url_prefix='/service/<uuid:service_id>')

register_errors(service_callback_blueprint)


@service_callback_blueprint.route('/inbound-api', methods=['POST'])
def create_service_inbound_api(service_id):
    data = request.get_json()
    validate(data, create_service_callback_api_schema)
    data["service_id"] = service_id
    inbound_api = ServiceInboundApi(**data)
    try:
        save_service_inbound_api(inbound_api)
    except SQLAlchemyError as e:
        return handle_sql_error(e, 'service_inbound_api')

    return jsonify(data=inbound_api.serialize()), 201
Exemple #23
0
from json import decoder
from app.notifications import process_notifications
from app.notifications.notifications_ses_callback import (
    determine_notification_bounce_type, handle_ses_complaint,
    handle_smtp_complaint)
from app.celery.service_callback_tasks import (
    check_and_queue_callback_task, _check_and_queue_complaint_callback_task)
from app.errors import (register_errors, InvalidRequest)
from cachelib import SimpleCache
import validatesns

ses_callback_blueprint = Blueprint('notifications_ses_callback', __name__)
ses_smtp_callback_blueprint = Blueprint('notifications_ses_smtp_callback',
                                        __name__)

register_errors(ses_callback_blueprint)
register_errors(ses_smtp_callback_blueprint)


class SNSMessageType(enum.Enum):
    SubscriptionConfirmation = 'SubscriptionConfirmation'
    Notification = 'Notification'
    UnsubscribeConfirmation = 'UnsubscribeConfirmation'


class InvalidMessageTypeException(Exception):
    pass


def verify_message_type(message_type: str):
    try:
from app.service.send_notification import send_one_off_notification, send_pdf_letter_notification
from app.schemas import (service_schema, api_key_schema,
                         notification_with_template_schema,
                         notifications_filter_schema, detailed_service_schema,
                         email_data_request_schema)
from app.user.users_schema import post_set_permissions_schema
from app.utils import pagination_links

from app.smtp.aws import (smtp_add, smtp_get_user_key, smtp_remove)
from nanoid import generate

CAN_T_BE_EMPTY_ERROR_MESSAGE = "Can't be empty"

service_blueprint = Blueprint('service', __name__)

register_errors(service_blueprint)


@service_blueprint.errorhandler(IntegrityError)
def handle_integrity_error(exc):
    """
    Handle integrity errors caused by the unique constraint on ix_organisation_name
    """
    if any('duplicate key value violates unique constraint "{}"'.format(
            constraint) in str(exc)
           for constraint in {'services_name_key', 'services_email_from_key'}):
        return jsonify(result='error',
                       message={
                           'name': [
                               "Duplicate service name '{}'".format(
                                   exc.params.get(
Exemple #25
0
from flask import Blueprint, jsonify, request

from app.dao.provider_details_dao import (
    dao_get_provider_stats,
    dao_get_provider_versions,
    dao_update_provider_details,
    get_provider_details_by_id,
)
from app.dao.users_dao import get_user_by_id
from app.errors import InvalidRequest, register_errors
from app.schemas import provider_details_history_schema, provider_details_schema

provider_details = Blueprint("provider_details", __name__)
register_errors(provider_details)


@provider_details.route("", methods=["GET"])
def get_providers():
    data = dao_get_provider_stats()

    provider_details = [{
        "id":
        row.id,
        "display_name":
        row.display_name,
        "identifier":
        row.identifier,
        "priority":
        row.priority,
        "notification_type":
        row.notification_type,
Exemple #26
0
    email_notification_schema,
    notification_with_personalisation_schema,
    notifications_filter_schema,
    sms_template_notification_schema,
)
from app.service.utils import service_allowed_to_send_to
from app.utils import (
    get_document_url,
    get_public_notify_type_text,
    get_template_instance,
    pagination_links,
)

notifications = Blueprint("notifications", __name__)

register_errors(notifications)


@notifications.route("/notifications/<uuid:notification_id>", methods=["GET"])
def get_notification_by_id(notification_id):
    notification = notifications_dao.get_notification_with_personalisation(
        str(authenticated_service.id), notification_id, key_type=None)
    return (
        jsonify(
            data={
                "notification":
                notification_with_personalisation_schema.dump(
                    notification).data
            }),
        200,
    )
Exemple #27
0
from app.dao.users_dao import dao_get_admin_users, dao_get_users
from app.dao.venues_dao import dao_get_venue_by_old_id, dao_get_venue_by_id

from app.errors import register_errors, InvalidRequest, PaypalException
from app.models import Event, EventDate, RejectReason, APPROVED, DRAFT, READY, REJECTED

from app.routes import is_running_locally
from app.routes.events.schemas import post_create_event_schema, post_update_event_schema, post_import_events_schema

from app.schema_validation import validate

from app.payments.paypal import PayPal
from app.storage.utils import Storage

events_blueprint = Blueprint('events', __name__)
register_errors(events_blueprint)


def extract_startdate(json):
    if json['event_dates']:
        return json['event_dates'][0]['event_datetime']
    else:
        return 0


@events_blueprint.route('/paypal/<item_id>', methods=['POST'])
@jwt_required
def create_test_paypal(item_id):
    if current_app.config['ENVIRONMENT'] == 'live':
        return 'Cannot test paypal on live environment'
Exemple #28
0
from flask import Blueprint, jsonify, request

from app.dao.events_dao import dao_create_event
from app.errors import register_errors
from app.schemas import event_schema

events = Blueprint('events', __name__, url_prefix='/events')
register_errors(events)


@events.route('', methods=['POST'])
def create_event():
    data = request.get_json()
    event = event_schema.load(data).data
    dao_create_event(event)
    return jsonify(data=event_schema.dump(event).data), 201
Exemple #29
0
from flask import (Blueprint, current_app, jsonify, render_template, request)

from app.errors import register_errors
from app.models import EmailProvider

from flask_jwt_extended import jwt_required
from app.dao.email_providers_dao import (dao_create_email_provider,
                                         dao_update_email_provider,
                                         dao_get_email_provider_by_id,
                                         dao_get_first_email_provider,
                                         dao_get_email_providers)
from app.routes.email_providers.schemas import post_create_email_provider_schema, post_update_email_provider_schema
from app.schema_validation import validate

email_providers_blueprint = Blueprint('email_provider', __name__)
register_errors(email_providers_blueprint)


@email_providers_blueprint.route('/email_provider', methods=['POST'])
@jwt_required
def create_email_provider():
    data = request.get_json(force=True)

    validate(data, post_create_email_provider_schema)

    email_provider = EmailProvider(**data)

    dao_create_email_provider(email_provider)

    return jsonify(email_provider.serialize()), 201
Exemple #30
0
    fetch_letter_line_items_for_all_services
)
from app.dao.fact_notification_status_dao import (
    fetch_notification_stats_for_trial_services,
    fetch_notification_status_totals_for_all_services,
)
from app.dao.notifications_dao import send_method_stats_by_service
from app.errors import register_errors, InvalidRequest
from app.platform_stats.platform_stats_schema import platform_stats_request
from app.service.statistics import format_admin_stats
from app.schema_validation import validate
from app.utils import get_local_timezone_midnight_in_utc

platform_stats_blueprint = Blueprint('platform_stats', __name__)

register_errors(platform_stats_blueprint)


@platform_stats_blueprint.route('')
def get_platform_stats():
    if request.args:
        validate(request.args, platform_stats_request)

    # If start and end date are not set, we are expecting today's stats.
    today = str(datetime.utcnow().date())

    start_date = datetime.strptime(request.args.get('start_date', today), '%Y-%m-%d').date()
    end_date = datetime.strptime(request.args.get('end_date', today), '%Y-%m-%d').date()
    data = fetch_notification_status_totals_for_all_services(start_date=start_date, end_date=end_date)
    stats = format_admin_stats(data)
Exemple #31
0
from app.dao.templates_dao import dao_get_template_by_id
from app.dao.notifications_dao import get_notifications_for_job
from app.schemas import (job_schema, unarchived_template_schema,
                         notifications_filter_schema,
                         notification_with_template_schema)
from app.celery.tasks import process_job
from app.models import JOB_STATUS_SCHEDULED, JOB_STATUS_PENDING, JOB_STATUS_CANCELLED, LETTER_TYPE
from app.utils import pagination_links
from app.config import QueueNames
from app.errors import (register_errors, InvalidRequest)

job_blueprint = Blueprint('job',
                          __name__,
                          url_prefix='/service/<uuid:service_id>/job')

register_errors(job_blueprint)


@job_blueprint.route('/<job_id>', methods=['GET'])
def get_job_by_service_and_job_id(service_id, job_id):
    job = dao_get_job_by_service_id_and_job_id(service_id, job_id)
    statistics = dao_get_notification_outcomes_for_job(service_id, job_id)
    data = job_schema.dump(job).data

    data['statistics'] = [{
        'status': statistic[1],
        'count': statistic[0]
    } for statistic in statistics]

    return jsonify(data=data)
Exemple #32
0
from flask_jwt_extended import jwt_required

from app.dao.venues_dao import (dao_create_venue, dao_get_venues,
                                dao_update_venue, dao_get_venue_by_id)
from app.errors import register_errors

from app.routes.venues.schemas import (post_create_venue_schema,
                                       post_create_venues_schema,
                                       post_import_venues_schema,
                                       post_update_venue_schema)
from app.models import Venue
from app.schema_validation import validate

venues_blueprint = Blueprint('venues', __name__)
venue_blueprint = Blueprint('venue', __name__)
register_errors(venues_blueprint)
register_errors(venue_blueprint)


@venues_blueprint.route('/venues')
@jwt_required
def get_venues():
    venues = [e.serialize() if e else None for e in dao_get_venues()]
    return jsonify(venues)


@venue_blueprint.route('/venue/<uuid:venue_id>', methods=['GET'])
def get_venue_by_id(venue_id):
    current_app.logger.info('get_venue: {}'.format(venue_id))
    venue = dao_get_venue_by_id(venue_id)
    return jsonify(venue.serialize())
Exemple #33
0
from sqlalchemy.exc import IntegrityError

from flask import Blueprint, jsonify, request

from app.dao.letter_branding_dao import (
    dao_get_all_letter_branding, dao_create_letter_branding,
    dao_update_letter_branding,
    dao_get_letter_branding_by_id
)
from app.errors import register_errors
from app.letter_branding.letter_branding_schema import post_letter_branding_schema
from app.models import LetterBranding
from app.schema_validation import validate

letter_branding_blueprint = Blueprint('letter_branding', __name__, url_prefix='/letter-branding')
register_errors(letter_branding_blueprint)


@letter_branding_blueprint.errorhandler(IntegrityError)
def handle_integrity_error(exc):
    """
    Handle integrity errors caused by the unique constraint
    """
    for col in {'name', 'filename'}:
        if 'letter_branding_{}_key'.format(col) in str(exc):
            return jsonify(
                result='error',
                message={col: ["{} already in use".format(col.title())]}
            ), 400
    current_app.logger.exception(exc)
    return jsonify(result='error', message="Internal server error"), 500
Exemple #34
0
)

from app.celery.tasks import process_job

from app.models import JOB_STATUS_SCHEDULED, JOB_STATUS_PENDING, JOB_STATUS_CANCELLED

from app.utils import pagination_links

job = Blueprint('job', __name__, url_prefix='/service/<uuid:service_id>/job')

from app.errors import (
    register_errors,
    InvalidRequest
)

register_errors(job)


@job.route('/<job_id>', methods=['GET'])
def get_job_by_service_and_job_id(service_id, job_id):
    job = dao_get_job_by_service_id_and_job_id(service_id, job_id)
    statistics = dao_get_notification_outcomes_for_job(service_id, job_id)
    data = job_schema.dump(job).data

    data['statistics'] = [{'status': statistic[1], 'count': statistic[0]} for statistic in statistics]

    return jsonify(data=data)


@job.route('/<job_id>/cancel', methods=['POST'])
def cancel_job(service_id, job_id):
Exemple #35
0
from datetime import datetime

from flask import Blueprint, jsonify, request

from app.complaint.complaint_schema import complaint_count_request
from app.dao.complaint_dao import (
    fetch_count_of_complaints,
    fetch_paginated_complaints,
)
from app.errors import register_errors
from app.schema_validation import validate
from app.utils import pagination_links

complaint_blueprint = Blueprint('complaint', __name__, url_prefix='/complaint')

register_errors(complaint_blueprint)


@complaint_blueprint.route('', methods=['GET'])
def get_all_complaints():
    page = int(request.args.get('page', 1))
    pagination = fetch_paginated_complaints(page=page)

    return jsonify(complaints=[x.serialize() for x in pagination.items],
                   links=pagination_links(pagination, '.get_all_complaints',
                                          **request.args.to_dict())), 200


@complaint_blueprint.route('/count-by-date-range', methods=['GET'])
def get_complaint_count():
    if request.args:
Exemple #36
0
    user_schema_load_json,
    user_update_schema_load_json
)

from app.celery.tasks import (
    send_email
)

from app.errors import (
    register_errors,
    InvalidRequest
)
from app.utils import url_with_token

user = Blueprint('user', __name__)
register_errors(user)


@user.route('', methods=['POST'])
def create_user():
    user_to_create, errors = user_schema.load(request.get_json())
    req_json = request.get_json()
    if not req_json.get('password', None):
        errors.update({'password': ['Missing data for required field.']})
        raise InvalidRequest(errors, status_code=400)
    save_model_user(user_to_create, pwd=req_json.get('password'))
    return jsonify(data=user_schema.dump(user_to_create).data), 201


@user.route('/<uuid:user_id>', methods=['PUT'])
def update_user(user_id):
Exemple #37
0
from flask import Blueprint, jsonify

from app.delivery import send_to_providers
from app.models import EMAIL_TYPE
from app.celery import provider_tasks
from app.dao import notifications_dao
from flask import current_app

delivery_blueprint = Blueprint('delivery', __name__)

from app.errors import register_errors

register_errors(delivery_blueprint)


@delivery_blueprint.route('/deliver/notification/<uuid:notification_id>', methods=['POST'])
def send_notification_to_provider(notification_id):
    notification = notifications_dao.get_notification_by_id(notification_id)
    if not notification:
        return jsonify({"result": "error", "message": "No result found"}), 404

    if notification.notification_type == EMAIL_TYPE:
        send_response(
            send_to_providers.send_email_to_provider,
            provider_tasks.deliver_email,
            notification,
            'send-email')
    else:
        send_response(
            send_to_providers.send_sms_to_provider,
            provider_tasks.deliver_sms,