Пример #1
0
def delete_account(record_id):
    """
    Deletes a single account record, removes all traces of account from other
    tables
    """
    try:
        # Delete this account's subscriptions
        Interactions.delete_specific(
            DEFAULT_SUBSCRIPTIONS_TABLE, filters={'account_id': record_id})

        # Loop and delete any records subscribed to their registrations
        registrations = Interactions.query(DEFAULT_REGISTRATIONS_TABLE,
                                           filters={'account_id': record_id})

        for registration in registrations:
            delete_registration(registration['id'])

        return make_response(
            jsonify(Interactions.delete(DEFAULT_ACCOUNTS_TABLE, record_id)),
            client.OK)
    except RqlRuntimeError as runtime_err:
        return make_response(jsonify({'Error': runtime_err.message}),
                             client.INTERNAL_SERVER_ERROR)
    except RqlDriverError as rql_err:
        return make_response(jsonify({'Error': rql_err.message}),
                             client.INTERNAL_SERVER_ERROR)
    except TypeError:
        return make_response(
            jsonify({'Error': 'Invalid id parameter'}), client.BAD_REQUEST)
Пример #2
0
def delete_account(record_id):
    """
    Deletes a single account record, removes all traces of account from other
    tables
    """
    try:
        # Delete this account's subscriptions
        Interactions.delete_specific(DEFAULT_SUBSCRIPTIONS_TABLE,
                                     filters={'account_id': record_id})

        # Loop and delete any records subscribed to their registrations
        registrations = Interactions.query(DEFAULT_REGISTRATIONS_TABLE,
                                           filters={'account_id': record_id})

        for registration in registrations:
            delete_registration(registration['id'])

        return make_response(
            jsonify(Interactions.delete(DEFAULT_ACCOUNTS_TABLE, record_id)),
            client.OK)
    except RqlRuntimeError as runtime_err:
        return make_response(jsonify({'Error': runtime_err.message}),
                             client.INTERNAL_SERVER_ERROR)
    except RqlDriverError as rql_err:
        return make_response(jsonify({'Error': rql_err.message}),
                             client.INTERNAL_SERVER_ERROR)
    except TypeError:
        return make_response(jsonify({'Error': 'Invalid id parameter'}),
                             client.BAD_REQUEST)
Пример #3
0
        def wrapper(*args, **kwargs):
            try:
                api_key = request.headers['api-key']
            except KeyError:
                return make_response(
                    jsonify({'Error': 'Missing API key header value'}),
                    client.UNAUTHORIZED)

            try:
                username = request.headers['username']
            except KeyError:
                return make_response(
                    jsonify({'Error': 'Missing username header value'}),
                    client.UNAUTHORIZED)

            record = Interactions.query(DEFAULT_ACCOUNTS_TABLE,
                                        filters={'username': username})

            if not record:
                return make_response(
                    jsonify({'Error': 'Invalid API key or Username'}),
                    client.UNAUTHORIZED)

            if not check_password_hash(record[0]['api_key'], api_key):
                return make_response(jsonify({'Error': 'Invalid API key'}),
                                     client.UNAUTHORIZED)

            if verify_admin:
                if not record[0]['is_admin']:
                    return make_response(jsonify({'Error': 'Not an Admin'}),
                                         client.UNAUTHORIZED)

            return f(*args, **kwargs)
Пример #4
0
def insert_account(table_name, **kwargs):
    """
    Creates new account records (handles POST traffic)
    Salts the api_key
    """
    try:
        # Username cannot already exist
        record = Interactions.query(table_name,
                                    filters={'username': kwargs['username']})

        if record:
            return make_response(jsonify({'Error': 'Username already exists'}),
                                 client.CONFLICT)

        original_api_key = kwargs['api_key']
        kwargs['api_key'] = generate_password_hash(kwargs['api_key'])
        account_data = Interactions.insert(table_name, **kwargs)
        account_data['api_key'] = original_api_key

        return make_response(jsonify(account_data), client.CREATED)
    except RqlRuntimeError as runtime_err:
        return make_response(jsonify({'Error': runtime_err.message}),
                             client.INTERNAL_SERVER_ERROR)
    except RqlDriverError as rql_err:
        return make_response(jsonify({'Error': rql_err.message}),
                             client.INTERNAL_SERVER_ERROR)
    except TypeError:
        return make_response(jsonify({'Error': 'Invalid parameter(s)'}),
                             client.BAD_REQUEST)
Пример #5
0
def insert_account(table_name, **kwargs):
    """
    Creates new account records (handles POST traffic)
    Salts the api_key
    """
    try:
        # Username cannot already exist
        record = Interactions.query(
            table_name, filters={'username': kwargs['username']})

        if record:
            return make_response(
                jsonify({'Error': 'Username already exists'}), client.CONFLICT)

        original_api_key = kwargs['api_key']
        kwargs['api_key'] = generate_password_hash(kwargs['api_key'])
        account_data = Interactions.insert(table_name, **kwargs)
        account_data['api_key'] = original_api_key

        return make_response(jsonify(account_data), client.CREATED)
    except RqlRuntimeError as runtime_err:
        return make_response(jsonify({'Error': runtime_err.message}),
                             client.INTERNAL_SERVER_ERROR)
    except RqlDriverError as rql_err:
        return make_response(jsonify({'Error': rql_err.message}),
                             client.INTERNAL_SERVER_ERROR)
    except TypeError:
        return make_response(
            jsonify({'Error': 'Invalid parameter(s)'}), client.BAD_REQUEST)
Пример #6
0
def lookup_account_id(username):
    """
    Looks up the user's account id based on username
    """
    try:
        record = Interactions.query(DEFAULT_ACCOUNTS_TABLE,
                                    filters={'username': username})
        return record[0]['id']
    except RqlRuntimeError as runtime_err:
        return runtime_err
    except RqlDriverError as rql_err:
        return rql_err
Пример #7
0
def lookup_subscription_id(account_id, subscription_id):
    """
    Looks up subscription based on account_id and pass the record back
    """
    try:
        return Interactions.query(
            DEFAULT_SUBSCRIPTIONS_TABLE,
            filters={'account_id': account_id, 'id': subscription_id})
    except RqlRuntimeError as runtime_err:
        return runtime_err
    except RqlDriverError as rql_err:
        return rql_err
Пример #8
0
def lookup_registration_id(account_id, registration_id):
    """
    Looks up registration based on account_id and pass the record back
    """
    try:
        return Interactions.query(
            DEFAULT_REGISTRATIONS_TABLE,
            filters={'account_id': account_id, 'id': registration_id})
    except RqlRuntimeError as runtime_err:
        return runtime_err
    except RqlDriverError as rql_err:
        return rql_err
Пример #9
0
def lookup_account_id(username):
    """
    Looks up the user's account id based on username
    """
    try:
        record = Interactions.query(
            DEFAULT_ACCOUNTS_TABLE, filters={'username': username})
        return record[0]['id']
    except RqlRuntimeError as runtime_err:
        return runtime_err
    except RqlDriverError as rql_err:
        return rql_err
Пример #10
0
def lookup_subscription_id(account_id, subscription_id):
    """
    Looks up subscription based on account_id and pass the record back
    """
    try:
        return Interactions.query(DEFAULT_SUBSCRIPTIONS_TABLE,
                                  filters={
                                      'account_id': account_id,
                                      'id': subscription_id
                                  })
    except RqlRuntimeError as runtime_err:
        return runtime_err
    except RqlDriverError as rql_err:
        return rql_err
Пример #11
0
    def post(self, registration_id):
        """
        Creates new triggered webhook event
        """
        registration = Interactions.query(DEFAULT_REGISTRATIONS_TABLE,
                                          filters={'id': registration_id})

        if not registration:
            return make_response(
                jsonify({'Error': 'Registration id not found'}),
                client.NOT_FOUND)

        # Other users cannot trigger webhooks they didn't create
        calling_account_id = lookup_account_id(request.headers['username'])

        if not lookup_registration_id(calling_account_id, registration_id):
            return make_response(
                jsonify({
                    'Error':
                    'You don\'t have access '
                    'to this registration record or it no '
                    'longer exists'
                }), client.UNAUTHORIZED)

        # Notify subscribed endpoints (send the webhooks out)
        subscriptions = Interactions.list_all(
            DEFAULT_SUBSCRIPTIONS_TABLE,
            order_by='epoch',
            filters={'registration_id': registration_id})

        if subscriptions:
            for record in subscriptions:
                account = Interactions.get(DEFAULT_ACCOUNTS_TABLE,
                                           record['account_id'])
                # Only hit the endpoint if their failed count is low enough
                if int(account['failed_count']) < MAX_FAILED_COUNT:
                    # This import is required to be here so the flask-restful
                    # piece works properly with Celery
                    from pywebhooks.tasks.webhook_notification import \
                        notify_subscribed_accounts

                    notify_subscribed_accounts.delay(
                        event=registration[0]['event'],
                        event_data=registration[0]['event_data'],
                        secret_key=account['secret_key'],
                        endpoint=account['endpoint'],
                        account_id=record['account_id'])

        return insert(DEFAULT_TRIGGERED_TABLE,
                      **{'registration_id': registration_id})
Пример #12
0
def registration_id_exists(registration_id):
    """
    Looks up registration based on record_id and pass the record back
    """
    try:
        registration = Interactions.query(
            DEFAULT_REGISTRATIONS_TABLE, filters={'id': registration_id})
        if registration:
            return True
        return False
    except RqlRuntimeError as runtime_err:
        return runtime_err
    except RqlDriverError as rql_err:
        return rql_err
Пример #13
0
def registration_id_exists(registration_id):
    """
    Looks up registration based on record_id and pass the record back
    """
    try:
        registration = Interactions.query(DEFAULT_REGISTRATIONS_TABLE,
                                          filters={'id': registration_id})
        if registration:
            return True
        return False
    except RqlRuntimeError as runtime_err:
        return runtime_err
    except RqlDriverError as rql_err:
        return rql_err
Пример #14
0
def lookup_registration_id(account_id, registration_id):
    """
    Looks up registration based on account_id and pass the record back
    """
    try:
        return Interactions.query(DEFAULT_REGISTRATIONS_TABLE,
                                  filters={
                                      'account_id': account_id,
                                      'id': registration_id
                                  })
    except RqlRuntimeError as runtime_err:
        return runtime_err
    except RqlDriverError as rql_err:
        return rql_err
Пример #15
0
    def post(self, registration_id):
        """
        Creates new triggered webhook event
        """
        registration = Interactions.query(
            DEFAULT_REGISTRATIONS_TABLE, filters={'id': registration_id})

        if not registration:
            return make_response(
                jsonify(
                    {'Error': 'Registration id not found'}
                ), client.NOT_FOUND)

        # Other users cannot trigger webhooks they didn't create
        calling_account_id = lookup_account_id(request.headers['username'])

        if not lookup_registration_id(calling_account_id, registration_id):
            return make_response(
                jsonify({'Error': 'You don\'t have access '
                                  'to this registration record or it no '
                                  'longer exists'}),
                client.UNAUTHORIZED)

        # Notify subscribed endpoints (send the webhooks out)
        subscriptions = Interactions.list_all(
            DEFAULT_SUBSCRIPTIONS_TABLE, order_by='epoch',
            filters={'registration_id': registration_id})

        if subscriptions:
            for record in subscriptions:
                account = Interactions.get(DEFAULT_ACCOUNTS_TABLE,
                                           record['account_id'])
                # Only hit the endpoint if their failed count is low enough
                if int(account['failed_count']) < MAX_FAILED_COUNT:
                    # This import is required to be here so the flask-restful
                    # piece works properly with Celery
                    from pywebhooks.tasks.webhook_notification import \
                        notify_subscribed_accounts

                    notify_subscribed_accounts.delay(
                        event=registration[0]['event'],
                        event_data=registration[0]['event_data'],
                        secret_key=account['secret_key'],
                        endpoint=account['endpoint'],
                        account_id=record['account_id'])

        return insert(DEFAULT_TRIGGERED_TABLE,
                      **{'registration_id': registration_id})
Пример #16
0
        def wrapper(*args, **kwargs):
            try:
                username = request.headers['username']
            except KeyError:
                return make_response(
                    jsonify({'Error': 'Missing the username header value'}),
                    client.BAD_REQUEST)

            record = Interactions.query(DEFAULT_ACCOUNTS_TABLE,
                                        filters={'username': username})

            if not record:
                return make_response(jsonify({'Error': 'Username not found'}),
                                     client.NOT_FOUND)

            return f(*args, **kwargs)
Пример #17
0
def reset_key(username, key_type):
    """
    Resets either a secret key or api key
    """
    try:
        # Note: The validate_username_in_header decorator will verify the
        # username and record. The api_key_restricted_resource will validate
        # the username as well as a valid API key
        record = Interactions.query(DEFAULT_ACCOUNTS_TABLE,
                                    filters={"username": username})
        endpoint = record[0]['endpoint']

        if not endpoint:
            return make_response(
                jsonify({'Error': 'Endpoint not found'}),
                client.NOT_FOUND
            )

        new_key = common.generate_key()
        salted_new_key = generate_password_hash(new_key)

        if not client_reset_key(endpoint, key_type, new_key):
            return make_response(
                jsonify({'Error': 'Failed to contact the endpoint or wrong '
                                  'HTTP status code returned'}),
                client.BAD_REQUEST
            )

        if key_type == 'api_key':
            update = {key_type: salted_new_key}
        else:
            update = {key_type: new_key}

        Interactions.update(DEFAULT_ACCOUNTS_TABLE,
                            filters={"username": username},
                            updates=update)

        return make_response(jsonify({'Message': 'New key sent to endpoint'}),
                             client.OK)
    except RqlRuntimeError as runtime_err:
        return make_response(jsonify({'Error': runtime_err.message}),
                             client.INTERNAL_SERVER_ERROR)
    except RqlDriverError as rql_err:
        return make_response(jsonify({'Error': rql_err.message}),
                             client.INTERNAL_SERVER_ERROR)
Пример #18
0
def reset_key(username, key_type):
    """
    Resets either a secret key or api key
    """
    try:
        # Note: The validate_username_in_header decorator will verify the
        # username and record. The api_key_restricted_resource will validate
        # the username as well as a valid API key
        record = Interactions.query(DEFAULT_ACCOUNTS_TABLE,
                                    filters={"username": username})
        endpoint = record[0]['endpoint']

        if not endpoint:
            return make_response(jsonify({'Error': 'Endpoint not found'}),
                                 client.NOT_FOUND)

        new_key = common.generate_key()
        salted_new_key = generate_password_hash(new_key)

        if not client_reset_key(endpoint, key_type, new_key):
            return make_response(
                jsonify({
                    'Error':
                    'Failed to contact the endpoint or wrong '
                    'HTTP status code returned'
                }), client.BAD_REQUEST)

        if key_type == 'api_key':
            update = {key_type: salted_new_key}
        else:
            update = {key_type: new_key}

        Interactions.update(DEFAULT_ACCOUNTS_TABLE,
                            filters={"username": username},
                            updates=update)

        return make_response(jsonify({'Message': 'New key sent to endpoint'}),
                             client.OK)
    except RqlRuntimeError as runtime_err:
        return make_response(jsonify({'Error': runtime_err.message}),
                             client.INTERNAL_SERVER_ERROR)
    except RqlDriverError as rql_err:
        return make_response(jsonify({'Error': rql_err.message}),
                             client.INTERNAL_SERVER_ERROR)
Пример #19
0
        def wrapper(*args, **kwargs):
            try:
                api_key = request.headers['api-key']
            except KeyError:
                return make_response(
                    jsonify(
                        {'Error': 'Missing API key header value'}
                    ), client.UNAUTHORIZED
                )

            try:
                username = request.headers['username']
            except KeyError:
                return make_response(
                    jsonify(
                        {'Error': 'Missing username header value'}
                    ), client.UNAUTHORIZED
                )

            record = Interactions.query(DEFAULT_ACCOUNTS_TABLE,
                                        filters={'username': username})

            if not record:
                return make_response(
                    jsonify({'Error': 'Invalid API key or Username'}),
                    client.UNAUTHORIZED
                )

            if not check_password_hash(record[0]['api_key'], api_key):
                return make_response(
                    jsonify({'Error': 'Invalid API key'}), client.UNAUTHORIZED)

            if verify_admin:
                if not record[0]['is_admin']:
                    return make_response(
                        jsonify({'Error': 'Not an Admin'}),
                        client.UNAUTHORIZED
                    )

            return f(*args, **kwargs)