Exemple #1
0
def restart(access_key):
    """Restarts a failed job"""

    account_id = Account.authorize(request.values.get('api_key'))

    jobs = Job.query.filter_by(access_key = access_key)
    job = jobs.first()
    
    if job == None or not account_id or not account_id == job.account_id:
        return jsonify(api_error('API_UNAUTHORIZED')), 401

    if not job.failed:
        return jsonify(api_error('JOBS_NOT_RESTARTABLE')), 400

    if job.data_deleted:
        return jsonify(api_error('JOBS_DATA_DELETED')), 400

    ip = fix_ip(request.headers.get('x-forwarded-for', request.remote_addr))

    job.ip_address = ip
    job.failed = 0
    job.fail_code = 0
    job.status = 'queued'
    db.session.commit()
    redis_conn = Redis.from_url(os.environ.get('REDIS_URI'))
    q = Queue(connection=redis_conn)
    q.enqueue_call(func=send_fax, args=(job.id,), timeout=600)

    return jsonify(job.public_data())
Exemple #2
0
def list():
    """List faxes"""

    v = request.values.get

    account_id = Account.authorize(v('api_key'))
    if not account_id:
        return jsonify(api_error('API_UNAUTHORIZED')), 401

    try:
        page = int(v('page', 1))
        if page < 1:
            raise
    except:
        return jsonify(api_error('JOBS_BAD_PAGINATION_VALUE')), 400

    if v('filter'):
        jobs = Job.query.filter_by(account_id=account_id, status=v('filter'))
    else:
        jobs = Job.query.filter_by(account_id=account_id)
    jobs = jobs.order_by(Job.create_date.desc()).paginate(page, 20, False)

    return jsonify({
        'page': jobs.page,
        'pages': jobs.pages,
        'per_page': jobs.per_page,
        'total': jobs.total,
        'has_next': jobs.has_next,
        'has_prev': jobs.has_prev,
        'jobs': [job.public_data() for job in jobs.items]
    })
Exemple #3
0
def list():
    """List faxes"""

    v = request.values.get

    account_id = Account.authorize(v('api_key'))
    if not account_id:
        return jsonify(api_error('API_UNAUTHORIZED')), 401

    try:
        page = int(v('page', 1))
        if page < 1:
            raise
    except:
        return jsonify(api_error('INCOMING_BAD_PAGINATION_VALUE')), 400

    faxes = IncomingFax.query.filter_by(account_id=account_id)
    faxes = faxes.order_by(IncomingFax.create_date.desc()).paginate(
        page, 20, False)

    return jsonify({
        'page': faxes.page,
        'pages': faxes.pages,
        'per_page': faxes.per_page,
        'total': faxes.total,
        'has_next': faxes.has_next,
        'has_prev': faxes.has_prev,
        'faxes': [fax.public_data() for fax in faxes.items]
    })
Exemple #4
0
def list():
    """List faxes"""

    v = request.values.get

    account_id = Account.authorize(v('api_key'))
    if not account_id:
        return jsonify(api_error('API_UNAUTHORIZED')), 401

    try:
        page = int(v('page', 1))
        if page < 1:
            raise
    except:
        return jsonify(api_error('JOBS_BAD_PAGINATION_VALUE')), 400

    if v('filter'):
        jobs = Job.query.filter_by(account_id= account_id, status= v('filter'))
    else:
        jobs = Job.query.filter_by(account_id= account_id)
    jobs = jobs.order_by(Job.create_date.desc()).paginate(page, 20, False)

    return jsonify({
        'page':     jobs.page,
        'pages':    jobs.pages,
        'per_page': jobs.per_page,
        'total':    jobs.total,
        'has_next': jobs.has_next,
        'has_prev': jobs.has_prev,
        'jobs':     [job.public_data() for job in jobs.items]
    })
Exemple #5
0
def restart(access_key):
    """Restarts a failed job"""

    account_id = Account.authorize(request.values.get('api_key'))

    jobs = Job.query.filter_by(access_key=access_key)
    job = jobs.first()

    if job == None or not account_id or not account_id == job.account_id:
        return jsonify(api_error('API_UNAUTHORIZED')), 401

    if not job.failed:
        return jsonify(api_error('JOBS_NOT_RESTARTABLE')), 400

    if job.data_deleted:
        return jsonify(api_error('JOBS_DATA_DELETED')), 400

    ip = fix_ip(request.headers.get('x-forwarded-for', request.remote_addr))

    job.ip_address = ip
    job.failed = 0
    job.fail_code = 0
    job.status = 'queued'
    db.session.commit()
    redis_conn = Redis.from_url(os.environ.get('REDIS_URI'))
    q = Queue(job.account.get_priority(), connection=redis_conn)
    q.enqueue_call(func=send_fax, args=(job.id, ), timeout=3600)

    return jsonify(job.public_data())
Exemple #6
0
def list():
    """List faxes"""

    v = request.values.get

    account_id = Account.authorize(v('api_key'))
    if not account_id:
        return jsonify(api_error('API_UNAUTHORIZED')), 401

    try:
        page = int(v('page', 1))
        if page < 1:
            raise
    except:
        return jsonify(api_error('INCOMING_BAD_PAGINATION_VALUE')), 400


    faxes = IncomingFax.query.filter_by(account_id= account_id)
    faxes = faxes.order_by(IncomingFax.create_date.desc()).paginate(page, 20,
            False)

    return jsonify({
        'page':     faxes.page,
        'pages':    faxes.pages,
        'per_page': faxes.per_page,
        'total':    faxes.total,
        'has_next': faxes.has_next,
        'has_prev': faxes.has_prev,
        'faxes':    [fax.public_data() for fax in faxes.items]
    })
Exemple #7
0
def login():
    """Logs into a user account"""

    if request.method == 'POST':
        v = request.values.get
        emails = Account.query.filter_by(email=v('email'))
        account = emails.first()

        if account == None:
            return jsonify(api_error('ACCOUNTS_LOGIN_ERROR')), 401
        elif account.password != password_hash(v('password')):
            return jsonify(api_error('ACCOUNTS_LOGIN_ERROR')), 401

        return jsonify(account.public_data())
    else:
        return render_template('accounts_login.html')
Exemple #8
0
def delete():
    """Delete an incoming fax"""

    from library.mailer import email_admin
    from boto.s3.connection import S3Connection
    from boto.s3.key import Key

    v = request.values.get

    access_key = v('access_key')
    account_id = Account.authorize(v('api_key'))

    if not account_id:
        return jsonify(api_error('API_UNAUTHORIZED')), 401

    faxes = IncomingFax.query.filter_by(access_key=access_key)
    fax = faxes.first()

    db.session.delete(fax)
    db.session.commit()

    try:
        conn = S3Connection(os.environ.get('AWS_ACCESS_KEY'),
                            os.environ.get('AWS_SECRET_KEY'))
        bucket = conn.get_bucket(os.environ.get('AWS_S3_BUCKET'))
        k = Key(bucket)
        k.key = 'incoming/' + access_key + '/fax.pdf'
        k.delete()
    except:
        email_admin("AWS S3 connect fail for fax deletion: %s" % access_key)

    return jsonify({"success": True})
Exemple #9
0
def transactions():
    """List transactions"""

    v = request.values.get

    page = int(v('page', 1))

    account_id = Account.authorize(v('api_key'))
    if not account_id:
        return jsonify(api_error('API_UNAUTHORIZED')), 401

    account = Account.query.get(account_id)

    res = Transaction.query.filter_by(account_id=account_id)
    res = res.order_by(Transaction.create_date.desc()).paginate(
        page, 15, False)

    return jsonify({
        'page': res.page,
        'pages': res.pages,
        'per_page': res.per_page,
        'total': res.total,
        'has_next': res.has_next,
        'has_prev': res.has_prev,
        'transactions': [trans.public_data() for trans in res.items]
    })
Exemple #10
0
def remove_card():
    """Removes stored credit card info from the account"""

    from datetime import datetime
    import json
    import stripe

    stripe.api_key = os.environ.get('STRIPE_SECRET_KEY')

    account_id = Account.authorize(request.values.get('api_key'))
    if not account_id:
        return jsonify(api_error('API_UNAUTHORIZED')), 401

    account = Account.query.get(account_id)

    if account.stripe_token and account.stripe_card:
        try:
            customer = stripe.Customer.retrieve(account.stripe_token)
            customer.sources.retrieve(account.stripe_card).delete()
        except:
            pass  # oh well, whatever. f**k it.

    account.stripe_token = None
    account.stripe_card = None
    account.last4 = None
    account.auto_recharge = 0
    account.mod_date = datetime.now()
    db.session.commit()

    return jsonify(account.public_data())
Exemple #11
0
def login():
    """Logs into a user account"""

    if request.method == 'POST':
        v = request.values.get
        emails = Account.query.filter_by(email=v('email'))
        account = emails.first()

        if account == None:
            return jsonify(api_error('ACCOUNTS_LOGIN_ERROR')), 401
        elif account.password != password_hash(v('password')):
            return jsonify(api_error('ACCOUNTS_LOGIN_ERROR')), 401

        return jsonify(account.public_data())
    else:
        return render_template('accounts_login.html');
Exemple #12
0
def delete():
    """Delete an incoming fax"""

    from library.mailer import email_admin
    from boto.s3.connection import S3Connection
    from boto.s3.key import Key

    v = request.values.get

    access_key = v('access_key')
    account_id = Account.authorize(v('api_key'))

    if not account_id:
        return jsonify(api_error('API_UNAUTHORIZED')), 401

    faxes = IncomingFax.query.filter_by(access_key = access_key)
    fax = faxes.first()

    db.session.delete(fax)
    db.session.commit()

    try:
        conn = S3Connection(os.environ.get('AWS_ACCESS_KEY'),
                            os.environ.get('AWS_SECRET_KEY'))
        bucket = conn.get_bucket(os.environ.get('AWS_S3_BUCKET'))
        k = Key(bucket)
        k.key ='incoming/' + access_key + '/fax.pdf'
        k.delete()
    except:
        email_admin("AWS S3 connect fail for fax deletion: %s" % access_key)

    return jsonify({"success": True})
Exemple #13
0
def transactions():
    """List transactions"""

    v = request.values.get

    page = int(v('page', 1))

    account_id = Account.authorize(v('api_key'))
    if not account_id:
        return jsonify(api_error('API_UNAUTHORIZED')), 401

    account = Account.query.get(account_id)

    res = Transaction.query.filter_by(account_id= account_id)
    res = res.order_by(Transaction.create_date.desc()).paginate(page, 15, False)

    return jsonify({
        'page':         res.page,
        'pages':        res.pages,
        'per_page':     res.per_page,
        'total':        res.total,
        'has_next':     res.has_next,
        'has_prev':     res.has_prev,
        'transactions': [trans.public_data() for trans in res.items]
    })
Exemple #14
0
def remove_card():
    """Removes stored credit card info from the account"""

    from datetime import datetime
    import json
    import stripe

    stripe.api_key = os.environ.get('STRIPE_SECRET_KEY')

    account_id = Account.authorize(request.values.get('api_key'))
    if not account_id:
        return jsonify(api_error('API_UNAUTHORIZED')), 401

    account = Account.query.get(account_id)

    if account.stripe_token and account.stripe_card:
        try:
            customer = stripe.Customer.retrieve(account.stripe_token)
            customer.sources.retrieve(account.stripe_card).delete()
        except:
            pass # oh well, whatever. f**k it.

    account.stripe_token = None
    account.stripe_card = None
    account.last4 = None
    account.auto_recharge = 0
    account.mod_date = datetime.now()
    db.session.commit()

    return jsonify(account.public_data())
Exemple #15
0
def charge():
    if request.values.get("admin_token") != os.environ.get("ADMIN_TOKEN"):
        return jsonify(api_error("ADMIN_BAD_ADMIN_TOKEN")), 401

    redis_conn = Redis.from_url(current_app.config['REDIS_URI'])
    q = Queue('default', connection=redis_conn)
    q.enqueue_call(func=charge_subscribers,  timeout=300)

    return jsonify({"kthx": "bai"})
Exemple #16
0
def get():
    """Gets the account information, provided a correct api_key is specified."""
    account_id = Account.authorize(request.values.get('api_key'))
    if account_id == None:
        return jsonify(api_error('API_UNAUTHORIZED')), 401

    account = Account.query.get(account_id)

    return jsonify(account.public_data())
Exemple #17
0
def charge():
    if request.values.get("admin_token") != os.environ.get("ADMIN_TOKEN"):
        return jsonify(api_error("ADMIN_BAD_ADMIN_TOKEN")), 401

    redis_conn = Redis.from_url(current_app.config['REDIS_URI'])
    q = Queue('default', connection=redis_conn)
    q.enqueue_call(func=charge_subscribers, timeout=300)

    return jsonify({"kthx": "bai"})
Exemple #18
0
def get():
    """Gets the account information, provided a correct api_key is specified."""
    account_id = Account.authorize(request.values.get('api_key'))
    if account_id == None:
        return jsonify(api_error('API_UNAUTHORIZED')), 401

    account = Account.query.get(account_id)

    return jsonify(account.public_data())
Exemple #19
0
def delete(access_key):
    """Deletes data associated with a job."""

    account_id = Account.authorize(request.values.get('api_key'))

    jobs = Job.query.filter_by(access_key = access_key)
    job = jobs.first()
    
    if job == None or (job.account_id != 0 and (not account_id or \
            account_id != job.account_id)):
        return jsonify(api_error('API_UNAUTHORIZED')), 401

    if not job.status == 'ready' and not job.status == 'sent' and \
            not job.status == 'failed':
        return jsonify(api_error('JOBS_CANNOT_DELETE_NOW')), 401   

    job.delete_data()

    return jsonify(job.public_data())
Exemple #20
0
def delete(access_key):
    """Deletes data associated with a job."""

    account_id = Account.authorize(request.values.get('api_key'))

    jobs = Job.query.filter_by(access_key=access_key)
    job = jobs.first()

    if job == None or (job.account_id != 0 and (not account_id or \
            account_id != job.account_id)):
        return jsonify(api_error('API_UNAUTHORIZED')), 401

    if not job.status == 'ready' and not job.status == 'sent' and \
            not job.status == 'failed':
        return jsonify(api_error('JOBS_CANNOT_DELETE_NOW')), 401

    job.delete_data()

    return jsonify(job.public_data())
Exemple #21
0
def get_by_id(id):
    """Get the status of a job by id"""

    account_id = Account.authorize(request.values.get('api_key'))

    jobs = Job.query.filter_by(id=id)
    job = jobs.first()

    if job == None or not account_id or job.account_id != account_id:
        return jsonify(api_error('API_UNAUTHORIZED')), 401

    return jsonify(job.public_data())
Exemple #22
0
def reset_api_key():
    """Resets the API key for an account"""

    from library.mailer import email_api_key_change
    from datetime import datetime

    account_id = Account.authorize(request.values.get('api_key'))
    if not account_id:
        return jsonify(api_error('API_UNAUTHORIZED')), 401

    account = Account.query.get(account_id)
    if account.password != password_hash(request.values.get('password')):
        return jsonify(api_error('ACCOUNTS_LOGIN_ERROR')), 401

    account.api_key = random_hash("%s%s" % (account.email, account.password))
    account.mod_date = datetime.now()
    db.session.commit()

    email_api_key_change(account)

    return jsonify({'api_key': account.api_key})
Exemple #23
0
def get_by_id(id):
    """Get the status of a job by id"""

    account_id = Account.authorize(request.values.get('api_key'))

    jobs = Job.query.filter_by(id = id)
    job = jobs.first()

    if job == None or not account_id or job.account_id != account_id:
        return jsonify(api_error('API_UNAUTHORIZED')), 401

    return jsonify(job.public_data())
Exemple #24
0
def get(access_key):
    """Get the status of a job"""

    account_id = Account.authorize(request.values.get('api_key'))

    jobs = Job.query.filter_by(access_key = access_key)
    job = jobs.first()

    if job == None or (job.account_id != 0 and (not account_id or \
            account_id != job.account_id)):
        return jsonify(api_error('API_UNAUTHORIZED')), 401

    return jsonify(job.public_data())
Exemple #25
0
def get(access_key):
    """Get the status of a job"""

    account_id = Account.authorize(request.values.get('api_key'))

    jobs = Job.query.filter_by(access_key=access_key)
    job = jobs.first()

    if job == None or (job.account_id != 0 and (not account_id or \
            account_id != job.account_id)):
        return jsonify(api_error('API_UNAUTHORIZED')), 401

    return jsonify(job.public_data())
Exemple #26
0
def deprovision():
    """Derovision a Phaxio fax number"""

    from library.mailer import email_registration

    ip = fix_ip(request.headers.get('x-forwarded-for', request.remote_addr))

    account_id = Account.authorize(request.values.get('api_key'))
    if account_id == None:
        return jsonify(api_error('API_UNAUTHORIZED')), 401

    account = Account.query.get(account_id)

    if len(account.incoming_numbers) == 0:
        return jsonify(api_error('INCOMING_CANNOT_REMOVE')), 400

    if not delete_number_from_phaxio(account.incoming_numbers[0].fax_number):
        return jsonify(api_error('INCOMING_FAILED_TO_DEPROVISION')), 500

    db.session.delete(account.incoming_numbers[0])
    db.session.commit()

    return jsonify({"success": True})
Exemple #27
0
def deprovision():
    """Derovision a Phaxio fax number"""

    from library.mailer import email_registration

    ip = fix_ip(request.headers.get('x-forwarded-for', request.remote_addr))

    account_id = Account.authorize(request.values.get('api_key'))
    if account_id == None:
        return jsonify(api_error('API_UNAUTHORIZED')), 401

    account = Account.query.get(account_id)

    if len(account.incoming_numbers) == 0:
        return jsonify(api_error('INCOMING_CANNOT_REMOVE')), 400

    if not delete_number_from_phaxio(account.incoming_numbers[0].fax_number):
        return jsonify(api_error('INCOMING_FAILED_TO_DEPROVISION')), 500

    db.session.delete(account.incoming_numbers[0])
    db.session.commit()

    return jsonify({"success": True})
Exemple #28
0
def reset_api_key():
    """Resets the API key for an account"""

    from library.mailer import email_api_key_change
    from datetime import datetime

    account_id = Account.authorize(request.values.get('api_key'))
    if not account_id:
        return jsonify(api_error('API_UNAUTHORIZED')), 401

    account = Account.query.get(account_id)
    if account.password != password_hash(request.values.get('password')):
        return jsonify(api_error('ACCOUNTS_LOGIN_ERROR')), 401

    account.api_key = random_hash("%s%s" % (account.email, account.password))
    account.mod_date = datetime.now()
    db.session.commit()

    email_api_key_change(account)

    return jsonify({
        'api_key': account.api_key
    })
Exemple #29
0
def create():
    """Creates a new user account"""

    from library.mailer import email_registration

    ip = fix_ip(request.headers.get('x-forwarded-for', request.remote_addr))

    if request.method == 'POST':

        v = request.values.get
        data = {
            'email':        v('email'),
            'password':     v('password'),
            'first_name':   v('first_name'),
            'last_name':    v('last_name'),
            'address':      v('address'),
            'address2':     v('address2'),
            'city':         v('city'),
            'state':        v('state'),
            'zip':          v('zip'),
        }
        try:
            account = Account(**data)
            account.validate()
        except ValidationError, err:
            return jsonify(api_error(err.ref)), 400

        try:
            db.session.add(account)
            db.session.commit()
        except IntegrityError:
            return jsonify(api_error('ACCOUNTS_CREATE_FAIL')), 400

        email_registration(account)

        return jsonify(account.public_data())
Exemple #30
0
def reset_password():
    """Actually reset a password using the hash"""

    from datetime import datetime

    v = request.values.get

    reset_hash = PasswordReset.query.filter_by(reset_hash=v('reset_hash'))
    reset_hash = reset_hash.first()

    if not reset_hash:
        return jsonify(api_error('ACCOUNTS_INVALID_RESET_HASH')), 401

    if reset_hash.used:
        return jsonify(api_error('ACCOUNTS_INVALID_RESET_HASH')), 401

    account = Account.query.get(reset_hash.account_id)
    account.password = account.password = password_hash(v('password'))
    account.mod_date = datetime.now()
    reset_hash.used = 1
    reset_hash.mod_date = datetime.now()
    db.session.commit()

    return jsonify(account.public_data())
Exemple #31
0
def reset_password():
    """Actually reset a password using the hash"""

    from datetime import datetime

    v = request.values.get

    reset_hash = PasswordReset.query.filter_by(reset_hash=v('reset_hash'))
    reset_hash = reset_hash.first()

    if not reset_hash:
        return jsonify(api_error('ACCOUNTS_INVALID_RESET_HASH')), 401

    if reset_hash.used:
        return jsonify(api_error('ACCOUNTS_INVALID_RESET_HASH')), 401

    account = Account.query.get(reset_hash.account_id)
    account.password = account.password = password_hash(v('password'))
    account.mod_date = datetime.now()
    reset_hash.used = 1
    reset_hash.mod_date = datetime.now()
    db.session.commit()

    return jsonify(account.public_data())
Exemple #32
0
def create():
    """Creates a new user account"""

    from library.mailer import email_registration

    ip = fix_ip(request.headers.get('x-forwarded-for', request.remote_addr))

    if request.method == 'POST':

        v = request.values.get
        data = {
            'email': v('email'),
            'password': v('password'),
            'first_name': v('first_name'),
            'last_name': v('last_name'),
            'address': v('address'),
            'address2': v('address2'),
            'city': v('city'),
            'state': v('state'),
            'zip': v('zip'),
        }
        try:
            account = Account(**data)
            account.validate()
        except ValidationError, err:
            return jsonify(api_error(err.ref)), 400

        try:
            db.session.add(account)
            db.session.commit()
        except IntegrityError:
            return jsonify(api_error('ACCOUNTS_CREATE_FAIL')), 400

        email_registration(account)

        return jsonify(account.public_data())
Exemple #33
0
def view():
    """View a fax"""

    import urllib
    from library.mailer import email_admin

    v = request.values.get

    ip = fix_ip(request.headers.get('x-forwarded-for', request.remote_addr))

    account_id = Account.authorize(v('api_key'))
    if not account_id:
        return jsonify(api_error('API_UNAUTHORIZED')), 401

    try:
        faxes = IncomingFax.query.filter_by(access_key=v('access_key'))
        fax = faxes.first()

        f = urllib.urlopen(fax.hosted_url)
        data = f.read()

        response = make_response(data)
        response.headers['Content-Type'] = 'application/pdf'
        response.headers[
            'Content-Disposition'] = 'attachment; filename=fax.pdf'
        return response
    except:
        msg = ("<h1>Something weird is going on.</h1>"
               "<p><strong>endpoint:</strong> /incoming/view<br/>"
               "<strong>api_key:</strong> %s<br/>"
               "<strong>access_key:</strong> %s<br/>"
               "<strong>ip:</strong> %s<br/>") % (v('api_key'),
                                                  v('access_key'), ip)

        email_admin(msg, "Security alert!")

        return (
            "<h1>File not found.</h1><p>Apologies for the glitch! Our staff"
            " has been notified in order to better assist you.</p>"), 401
Exemple #34
0
def view():
    """View a fax"""

    import urllib
    from library.mailer import email_admin

    v = request.values.get

    ip = fix_ip(request.headers.get('x-forwarded-for', request.remote_addr))

    account_id = Account.authorize(v('api_key'))
    if not account_id:
        return jsonify(api_error('API_UNAUTHORIZED')), 401

    try:
        faxes = IncomingFax.query.filter_by(access_key = v('access_key'))
        fax = faxes.first()

        f = urllib.urlopen(fax.hosted_url)
        data = f.read()

        response = make_response(data)
        response.headers['Content-Type'] = 'application/pdf'
        response.headers['Content-Disposition'] = 'attachment; filename=fax.pdf'
        return response
    except:
        msg = ("<h1>Something weird is going on.</h1>"
               "<p><strong>endpoint:</strong> /incoming/view<br/>"
               "<strong>api_key:</strong> %s<br/>"
               "<strong>access_key:</strong> %s<br/>"
               "<strong>ip:</strong> %s<br/>") % (v('api_key'), v('access_key'),
               ip)

        email_admin(msg, "Security alert!")

        return ("<h1>File not found.</h1><p>Apologies for the glitch! Our staff"
                " has been notified in order to better assist you.</p>"), 401
Exemple #35
0
def update(access_key):
    """Updates a fax"""

    account_id = Account.authorize(request.values.get('api_key'))
    if not account_id:
        account_id = 0
        # return jsonify(api_error('API_UNAUTHORIZED')), 401

    v = request.values.get

    jobs = Job.query.filter_by(access_key=access_key)
    job = jobs.first()

    if job == None:
        return jsonify(api_error('API_UNAUTHORIZED')), 401
    elif job.account_id and not job.account_id == account_id:
        return jsonify(api_error('API_UNAUTHORIZED')), 401
    elif not job.status == 'ready' and not job.status == 'new' and \
            not job.status == 'uploading':
        return jsonify(api_error('JOBS_NOT_READY')), 401

    if job.data_deleted:
        return jsonify(api_error('JOBS_DATA_DELETED')), 400

    ip = fix_ip(request.headers.get('x-forwarded-for', request.remote_addr))

    job.ip_address = ip
    job.account_id = account_id

    try:
        if v('destination'):
            job.destination = v('destination')

        if v('send_authorized') and v('send_authorized').lower() != "false" \
                and v('send_authorized') != "0":
            job.send_authorized = 1

        if v('cover') and v('cover').lower() != "false" and v('cover') != "0":
            job.cover = 1

        if v('cover_name'):
            job.cover_name = v('cover_name')

        if v('cover_address'):
            job.cover_address = v('cover_address')

        if v('cover_city'):
            job.cover_city = v('cover_city')

        if v('cover_state'):
            job.cover_state = v('cover_state')

        if v('cover_zip'):
            job.cover_zip = v('cover_zip')

        if v('cover_country'):
            job.cover_country = v('cover_country')

        if v('cover_phone'):
            job.cover_phone = v('cover_phone')

        if v('cover_email'):
            job.cover_email = v('cover_email')

        if v('cover_company'):
            job.cover_company = v('cover_company')

        if v('cover_to_name'):
            job.cover_to_name = v('cover_to_name')

        if v('cover_cc'):
            job.cover_cc = v('cover_cc')

        if v('cover_subject'):
            job.cover_subject = v('cover_subject')

        if v('cover_status'):
            job.cover_status = v('cover_status')

        if v('cover_comments'):
            job.cover_comments = v('cover_comments')

        if v('callback_url'):
            job.callback_url = v('callback_url')

        job.mod_date = datetime.now()
        job.validate()
        job.determine_international()
        job.compute_cost()
        job.rate_limit(account_id)

        if job.status == 'ready' and job.send_authorized:
            job.status = 'queued'
            db.session.commit()
            redis_conn = Redis.from_url(os.environ.get('REDIS_URI'))
            q = Queue(job.account.get_priority(), connection=redis_conn)
            q.enqueue_call(func=send_fax, args=(job.id, ), timeout=3600)
        else:
            db.session.commit()

    except ValidationError, err:
        return jsonify(api_error(err.ref)), 400
Exemple #36
0
def bootstrap():
    """
    Implicitly creates a user account and logs them in by processing a Stripe
    payment and email. If the email address belongs to a registered account, it
    requires the account password to authorize the payment and login attempt.
    """
    import json
    import stripe
    import sys
    import traceback
    from library.mailer import email_payment
    from datetime import datetime

    stripe.api_key = os.environ.get('STRIPE_SECRET_KEY')

    account_id = Account.authorize(request.values.get('api_key'))
    ip = fix_ip(request.headers.get('x-forwarded-for', request.remote_addr))

    if request.method == 'POST':

        v = request.values.get
        emails = Account.query.filter_by(email=v('email'))
        account = emails.first()

        o("Received bootstrap payment login: %s" % v('email'))

        if account_id and account != None and account.id != account_id:
            o("Account exists but user is logged in as someone else. Error.")
            return jsonify(api_error('ACCOUNTS_LOGIN_ERROR')), 401

        if account != None and account.password != password_hash(v('password'))\
                and not account_id:
            o("Account exists but password mismatch. Erroring out.")
            return jsonify(api_error('ACCOUNTS_LOGIN_ERROR')), 401

        temporary_password = None

        if account == None:
            o("Creating account with temporary password.")
            temporary_password = random_hash(v('email'))[:8]
            data = {'email': v('email'), 'password': temporary_password}
            try:
                account = Account(**data)
            except ValidationError, err:
                return jsonify(api_error(err.ref)), 400

            try:
                account.validate()
                db.session.add(account)
            except IntegrityError:
                return jsonify(api_error('ACCOUNTS_CREATE_FAIL')), 400

        o("Verifying payment with Stripe API.")
        failed = False

        try:
            payment = stripe.Charge.create(amount=int(
                float(v('amount')) * 100),
                                           currency="usd",
                                           source=v('stripe_token'),
                                           description="Bootstrap payment")
        except:
            o("STRIPE UNEXPECTED ERROR:", sys.exc_info()[0])
            failed = True
            payment = {'_DEBUG': traceback.format_exc()}

        o(payment)

        if not failed and payment and payment.status == "succeeded":
            o("Payment success.")
            db.session.commit()
            data = {
                'account_id': account.id,
                'amount': v('amount'),
                'source': 'stripe',
                'source_id': payment.id,
                'ip_address': ip,
                'initial_balance': account.credit,
                'trans_type': 'payment'
            }
            trans = Transaction(**data)
            db.session.add(trans)
            db.session.commit()

            o("Adding credit to account.")
            charged = float(payment.amount) / float(100)
            account.add_credit(charged)
            email_payment(account, charged, trans.id, payment.source.last4,
                          temporary_password)

        else:
            o("--- PAYMENT FAIL. LOGGING INFO ---")
            db.session.expunge_all()
            data = {
                'amount': v('amount'),
                'account_id': account.id,
                'source': 'stripe',
                'debug': json.dumps(payment),
                'ip_address': ip,
                'payment_type': 'bootstrap'
            }
            failed_payment = FailedPayment(**data)
            db.session.add(failed_payment)
            db.session.commit()
            return jsonify(api_error('ACCOUNTS_PAYMENT_FAIL')), 400

        result = account.public_data()
        if temporary_password:
            result['temporary_password'] = temporary_password

        return jsonify(result)
Exemple #37
0
def update():
    """Updates an account"""

    from datetime import datetime
    import stripe
    import traceback
    import json
    from library.mailer import email_password_change

    stripe.api_key = os.environ.get('STRIPE_SECRET_KEY')

    ip = fix_ip(request.headers.get('x-forwarded-for', request.remote_addr))

    account_id = Account.authorize(request.values.get('api_key'))
    if not account_id:
        return jsonify(api_error('API_UNAUTHORIZED')), 401

    account = Account.query.get(account_id)

    v = request.values.get

    try:
        if v('email'):

            existing = Account.query.filter_by(email=v('email'))

            if existing.first() and not existing.first().id == account.id:
                raise ValidationError('ACCOUNTS_EMAIL_TAKEN')

            account.email = v('email')

        if v('password'):

            if not v('old_password'):
                raise ValidationError('ACCOUNTS_INVALID_OLD_PASSWORD')

            if not account.password == password_hash(v('old_password')):
                raise ValidationError('ACCOUNTS_INVALID_OLD_PASSWORD')

            account.password = password_hash(v('password'))

        if v('first_name'):
            account.first_name = v('first_name')

        if v('last_name'):
            account.last_name = v('last_name')

        if v('address'):
            account.address = v('address')

        if v('address2'):
            account.address2 = v('address2')

        if v('city'):
            account.city = v('city')

        if v('state'):
            account.state = v('state')

        if v('zip'):
            account.zip = v('zip')

        if v('auto_recharge') != None:
            account.auto_recharge = 1 if v('auto_recharge') == "1" else 0

        if v('email_success') != None:
            account.email_success = 1 if v('email_success') == "1" else 0

        if v('email_fail') != None:
            account.email_fail = 1 if v('email_fail') == "1" else 0

        if v('email_list') != None:
            account.email_list = 1 if v('email_list') == "1" else 0

        if v('stripe_token') and v('last4'):
            try:
                customer = stripe.Customer.create(
                    description="%s Customer %s" %
                    (os.environ.get('PROJECT_NAME'), account.id),
                    email=account.email,
                    source=v('stripe_token')  # 'trol'
                )
                account.stripe_token = customer["id"]
                account.stripe_card = customer["sources"]["data"][0]["id"]
                account.last4 = v('last4')
            except:
                payment = {'_DEBUG': traceback.format_exc()}
                data = {
                    'amount': 0,
                    'account_id': account.id,
                    'source': 'stripe',
                    'debug': json.dumps(payment),
                    'ip_address': ip,
                    'payment_type': 'stored_payment'
                }
                failed_payment = FailedPayment(**data)
                db.session.add(failed_payment)
                db.session.commit()
                return jsonify(api_error('ACCOUNTS_STORED_PAYMENT_FAIL')), 400

        account.mod_date = datetime.now()
        account.validate()
        db.session.commit()

        # Send notification email for password / API key change
        if v('password'):
            email_password_change(account)

        info = account.public_data()
        info['mod_date'] = datetime.now()

    except ValidationError, err:
        return jsonify(api_error(err.ref)), 400
Exemple #38
0
def provision():
    """Provision a Phaxio fax number"""

    from library.mailer import email_provision_info

    ip = fix_ip(request.headers.get('x-forwarded-for', request.remote_addr))

    account_id = Account.authorize(request.values.get('api_key'))
    if account_id == None:
        return jsonify(api_error('API_UNAUTHORIZED')), 401

    account = Account.query.get(account_id)

    if len(account.incoming_numbers) > 0:
        return jsonify(api_error('INCOMING_NUMBER_EXISTS')), 400

    if account.credit < 6 and not account.allow_overflow:
        if account.stripe_card and account.auto_recharge:
            if not auto_recharge(account, ip) == True:
                return jsonify(api_error('INCOMING_CARD_DECLINED')), 401
        else:
            return jsonify(api_error('INCOMING_INSUFFICIENT_CREDIT')), 401

    payload = {
        "area_code": request.values.get("area_code"),
        "api_key": os.environ.get('PHAXIO_API_KEY'),
        "api_secret": os.environ.get('PHAXIO_API_SECRET')
    }
    if os.environ.get('PHAXIO_OVERRIDE_RECEIVED'):
        payload["callback_url"] = os.environ.get('PHAXIO_OVERRIDE_RECEIVED')

    try:
        url = "https://api.phaxio.com/v1/provisionNumber"
        r = requests.post(url, data=payload)
        response = json.loads(r.text)

        if response["success"] == False or not "data" in response \
            or not "number" in response["data"]:
            return jsonify(api_error('INCOMING_BOGUS_AREA_CODE')), 400
    except:
        return jsonify(api_error('INCOMING_FAILED_TO_PROVISION')), 500

    data = {
        'account_id':   account_id,
        'fax_number':   response["data"]["number"],
    }
    incoming_number = IncomingNumber(**data);
    db.session.add(incoming_number)
    db.session.commit()

    data2 = {
        'account_id':       account.id,
        'amount':           -6.00,
        'source':           "phaxio",
        'source_id':        data["fax_number"],
        'ip_address':       ip,
        'initial_balance':  account.credit,
        'trans_type':       "incoming_autopay"
    }
    trans = Transaction(**data2)
    db.session.add(trans)
    db.session.commit()

    account.subtract_credit(6)
    email_provision_info(account, data["fax_number"])

    return jsonify(account.public_data())
Exemple #39
0
def bootstrap():
    """
    Implicitly creates a user account and logs them in by processing a Stripe
    payment and email. If the email address belongs to a registered account, it
    requires the account password to authorize the payment and login attempt.
    """
    import json
    import stripe
    import sys
    import traceback
    from library.mailer import email_payment
    from datetime import datetime

    stripe.api_key = os.environ.get('STRIPE_SECRET_KEY')

    account_id = Account.authorize(request.values.get('api_key'))
    ip = fix_ip(request.headers.get('x-forwarded-for', request.remote_addr))

    if request.method == 'POST':

        v = request.values.get
        emails = Account.query.filter_by(email=v('email'))
        account = emails.first()

        o("Received bootstrap payment login: %s" % v('email'))

        if account_id and account != None and account.id != account_id:
            o("Account exists but user is logged in as someone else. Error.")
            return jsonify(api_error('ACCOUNTS_LOGIN_ERROR')), 401
            
        if account != None and account.password != password_hash(v('password'))\
                and not account_id:
            o("Account exists but password mismatch. Erroring out.")
            return jsonify(api_error('ACCOUNTS_LOGIN_ERROR')), 401

        temporary_password = None

        if account == None:
            o("Creating account with temporary password.")
            temporary_password = random_hash(v('email'))[:8]
            data = {
                'email':        v('email'),
                'password':     temporary_password
            }
            try:
                account = Account(**data)
            except ValidationError, err:
                return jsonify(api_error(err.ref)), 400

            try:
                account.validate()
                db.session.add(account)
            except IntegrityError:
                return jsonify(api_error('ACCOUNTS_CREATE_FAIL')), 400

        o("Verifying payment with Stripe API.")
        failed = False

        try:
            payment = stripe.Charge.create(
                amount=int(float(v('amount')) * 100),
                currency="usd",
                source=v('stripe_token'),
                description="Bootstrap payment"
            )
        except:
            o("STRIPE UNEXPECTED ERROR:", sys.exc_info()[0])
            failed = True
            payment = {'_DEBUG': traceback.format_exc()}

        o(payment)

        if not failed and payment and payment.status == "succeeded":
            o("Payment success.")
            db.session.commit()
            data = {
                'account_id':       account.id,
                'amount':           v('amount'),
                'source':           'stripe',
                'source_id':        payment.id,
                'ip_address':       ip,
                'initial_balance':  account.credit,
                'trans_type':       'payment'
            }
            trans = Transaction(**data)
            db.session.add(trans)
            db.session.commit()

            o("Adding credit to account.")
            charged = float(payment.amount) / float(100)
            account.add_credit(charged)
            email_payment(account, charged, trans.id, payment.source.last4,
                    temporary_password)

        else:
            o("--- PAYMENT FAIL. LOGGING INFO ---")
            db.session.expunge_all()
            data = {
                'amount':       v('amount'),
                'account_id':   account.id,
                'source':       'stripe',
                'debug':        json.dumps(payment),
                'ip_address':   ip,
                'payment_type': 'bootstrap'
            }
            failed_payment = FailedPayment(**data)
            db.session.add(failed_payment)
            db.session.commit()
            return jsonify(api_error('ACCOUNTS_PAYMENT_FAIL')), 400

        result = account.public_data()
        if temporary_password:
            result['temporary_password'] = temporary_password

        return jsonify(result)
Exemple #40
0
def create():
    """Creates a new outgoing fax"""

    account_id = Account.authorize(request.values.get('api_key'))
    if account_id == None:
        return jsonify(api_error('API_UNAUTHORIZED')), 401

    ip = fix_ip(request.headers.get('x-forwarded-for', request.remote_addr))

    if request.method == 'POST':

        if request.files and 'file' in request.files:
            uploaded_file = request.files['file']
        else:
            uploaded_file = None

        v = request.values.get

        if uploaded_file or v('body'):

            data = {
                'account_id': account_id,
                'ip_address': ip,
                'destination': v('destination'),
                'send_authorized': v('send_authorized', 0),
                'cover': v('cover', 0),
                'cover_name': v('cover_name'),
                'cover_address': v('cover_address'),
                'cover_city': v('cover_city'),
                'cover_state': v('cover_state'),
                'cover_zip': v('cover_zip'),
                'cover_country': v('cover_country'),
                'cover_phone': v('cover_phone'),
                'cover_email': v('cover_email'),
                'cover_company': v('cover_company'),
                'cover_to_name': v('cover_to_name'),
                'cover_cc': v('cover_cc'),
                'cover_subject': v('cover_subject'),
                'cover_status': v('cover_status', 'review'),
                'cover_comments': v('cover_comments'),
                'callback_url': v('callback_url')
            }
            if uploaded_file:
                data['filename'] = uploaded_file.filename
            else:
                data['body'] = v('body')

            o(data)

            try:
                job = Job(**data)
                job.validate()
                job.determine_international()
            except ValidationError, err:
                return jsonify(api_error(err.ref)), 400

            db.session.add(job)
            db.session.commit()

            if uploaded_file:
                binary = uploaded_file.stream.read()
            else:
                binary = job.body.replace("\r\n", "\n").encode('utf-8')

            redis_conn = Redis.from_url(current_app.config['REDIS_URI'])
            q = Queue('high', connection=redis_conn)
            q.enqueue_call(func=initial_process,
                           args=(job.id, binary),
                           timeout=300)

            return jsonify(job.public_data())
        else:
            return jsonify(api_error("JOBS_NO_ATTACHMENT")), 400
Exemple #41
0
def update(access_key):
    """Updates a fax"""

    account_id = Account.authorize(request.values.get('api_key'))
    if not account_id:
        return jsonify(api_error('API_UNAUTHORIZED')), 401

    v = request.values.get

    jobs = Job.query.filter_by(access_key = access_key)
    job = jobs.first()

    if job == None:
        return jsonify(api_error('API_UNAUTHORIZED')), 401
    elif job.account_id and not job.account_id == account_id:
        return jsonify(api_error('API_UNAUTHORIZED')), 401
    elif not job.status == 'ready' and not job.status == 'new' and \
            not job.status == 'uploading':
        return jsonify(api_error('JOBS_NOT_READY')), 401

    if job.data_deleted:
        return jsonify(api_error('JOBS_DATA_DELETED')), 400

    ip = fix_ip(request.headers.get('x-forwarded-for', request.remote_addr))

    job.ip_address = ip
    job.account_id = account_id

    try:
        if v('destination'):
            job.destination = v('destination')

        if v('send_authorized') and v('send_authorized').lower() != "false" \
                and v('send_authorized') != "0":
            job.send_authorized = 1;

        if v('cover') and v('cover').lower() != "false" and v('cover') != "0":
            job.cover = 1;

        if v('cover_name'):
            job.cover_name = v('cover_name')

        if v('cover_address'):
            job.cover_address = v('cover_address')

        if v('cover_city'):
            job.cover_city = v('cover_city')

        if v('cover_state'):
            job.cover_state = v('cover_state')

        if v('cover_zip'):
            job.cover_zip = v('cover_zip')

        if v('cover_country'):
            job.cover_country = v('cover_country')

        if v('cover_phone'):
            job.cover_phone = v('cover_phone')

        if v('cover_email'):
            job.cover_email = v('cover_email')

        if v('cover_company'):
            job.cover_company = v('cover_company')

        if v('cover_to_name'):
            job.cover_to_name = v('cover_to_name')

        if v('cover_cc'):
            job.cover_cc = v('cover_cc')

        if v('cover_subject'):
            job.cover_subject = v('cover_subject')

        if v('cover_status'):
            job.cover_status = v('cover_status')

        if v('cover_comments'):
            job.cover_comments = v('cover_comments')

        if v('callback_url'):
            job.callback_url = v('callback_url')

        job.mod_date = datetime.now()
        job.validate()

        if job.status == 'ready' and job.send_authorized:
            job.status = 'queued'
            db.session.commit()
            redis_conn = Redis.from_url(os.environ.get('REDIS_URI'))
            q = Queue('default', connection=redis_conn)
            q.enqueue_call(func=send_fax, args=(job.id,), timeout=600)
        else:
            db.session.commit()

    except ValidationError, err:
        return jsonify(api_error(err.ref)), 400
Exemple #42
0
def update():
    """Updates an account"""

    from datetime import datetime
    import stripe
    import traceback
    import json
    from library.mailer import email_password_change

    stripe.api_key = os.environ.get('STRIPE_SECRET_KEY')

    ip = fix_ip(request.headers.get('x-forwarded-for', request.remote_addr))

    account_id = Account.authorize(request.values.get('api_key'))
    if not account_id:
        return jsonify(api_error('API_UNAUTHORIZED')), 401

    account = Account.query.get(account_id)

    v = request.values.get

    try:
        if v('email'):

            existing = Account.query.filter_by(email=v('email'))

            if existing.first() and not existing.first().id == account.id:
                raise ValidationError('ACCOUNTS_EMAIL_TAKEN')

            account.email = v('email')

        if v('password'):

            if not v('old_password'):
                raise ValidationError('ACCOUNTS_INVALID_OLD_PASSWORD')

            if not account.password == password_hash(v('old_password')):
                raise ValidationError('ACCOUNTS_INVALID_OLD_PASSWORD')

            account.password = password_hash(v('password'))

        if v('first_name'):
            account.first_name = v('first_name')

        if v('last_name'):
            account.last_name = v('last_name')

        if v('address'):
            account.address = v('address')

        if v('address2'):
            account.address2 = v('address2')

        if v('city'):
            account.city = v('city')

        if v('state'):
            account.state = v('state')

        if v('zip'):
            account.zip = v('zip')

        if v('auto_recharge') != None:
            account.auto_recharge = 1 if v('auto_recharge') == "1" else 0

        if v('email_success') != None:
            account.email_success = 1 if v('email_success') == "1" else 0

        if v('email_fail') != None:
            account.email_fail = 1 if v('email_fail') == "1" else 0

        if v('email_list') != None:
            account.email_list = 1 if v('email_list') == "1" else 0

        if v('stripe_token') and v('last4'):
            try:
                customer = stripe.Customer.create(
                    description="%s Customer %s" % (
                        os.environ.get('PROJECT_NAME'), account.id),
                    email=account.email,
                    source=v('stripe_token') # 'trol'
                )
                account.stripe_token = customer["id"]
                account.stripe_card = customer["sources"]["data"][0]["id"]
                account.last4 = v('last4')
            except:
                payment = {'_DEBUG': traceback.format_exc()}
                data = {
                    'amount':       0,
                    'account_id':   account.id,
                    'source':       'stripe',
                    'debug':        json.dumps(payment),
                    'ip_address':   ip,
                    'payment_type': 'stored_payment'
                }
                failed_payment = FailedPayment(**data)
                db.session.add(failed_payment)
                db.session.commit()
                return jsonify(api_error('ACCOUNTS_STORED_PAYMENT_FAIL')), 400

        account.mod_date = datetime.now()
        account.validate()
        db.session.commit()

        # Send notification email for password / API key change
        if v('password'):
            email_password_change(account)

        info = account.public_data()
        info['mod_date'] = datetime.now()

    except ValidationError, err:
        return jsonify(api_error(err.ref)), 400
Exemple #43
0
def provision():
    """Provision a Phaxio fax number"""

    from library.mailer import email_provision_info

    ip = fix_ip(request.headers.get('x-forwarded-for', request.remote_addr))

    account_id = Account.authorize(request.values.get('api_key'))
    if account_id == None:
        return jsonify(api_error('API_UNAUTHORIZED')), 401

    account = Account.query.get(account_id)

    if len(account.incoming_numbers) > 0:
        return jsonify(api_error('INCOMING_NUMBER_EXISTS')), 400

    if account.credit < 6 and not account.allow_overflow:
        if account.stripe_card and account.auto_recharge:
            if not auto_recharge(account, ip) == True:
                return jsonify(api_error('INCOMING_CARD_DECLINED')), 401
        else:
            return jsonify(api_error('INCOMING_INSUFFICIENT_CREDIT')), 401

    payload = {
        "area_code": request.values.get("area_code"),
        "api_key": os.environ.get('PHAXIO_API_KEY'),
        "api_secret": os.environ.get('PHAXIO_API_SECRET')
    }
    if os.environ.get('PHAXIO_OVERRIDE_RECEIVED'):
        payload["callback_url"] = os.environ.get('PHAXIO_OVERRIDE_RECEIVED')

    try:
        url = "https://api.phaxio.com/v1/provisionNumber"
        r = requests.post(url, data=payload)
        response = json.loads(r.text)

        if response["success"] == False or not "data" in response \
            or not "number" in response["data"]:
            return jsonify(api_error('INCOMING_BOGUS_AREA_CODE')), 400
    except:
        return jsonify(api_error('INCOMING_FAILED_TO_PROVISION')), 500

    data = {
        'account_id': account_id,
        'fax_number': response["data"]["number"],
    }
    incoming_number = IncomingNumber(**data)
    db.session.add(incoming_number)
    db.session.commit()

    data2 = {
        'account_id': account.id,
        'amount': -6.00,
        'source': "phaxio",
        'source_id': data["fax_number"],
        'ip_address': ip,
        'initial_balance': account.credit,
        'trans_type': "incoming_autopay"
    }
    trans = Transaction(**data2)
    db.session.add(trans)
    db.session.commit()

    account.subtract_credit(6)
    email_provision_info(account, data["fax_number"])

    return jsonify(account.public_data())
Exemple #44
0
def create():
    """Creates a new outgoing fax"""

    account_id = Account.authorize(request.values.get('api_key'))
    if account_id == None:
        return jsonify(api_error('API_UNAUTHORIZED')), 401

    ip = fix_ip(request.headers.get('x-forwarded-for', request.remote_addr))

    if request.method == 'POST':

        uploaded_file = request.files['file']
        v = request.values.get

        if uploaded_file or v('body'):

            data = {
                'account_id':       account_id,
                'ip_address':       ip,
                'destination':      v('destination'),
                'send_authorized':  v('send_authorized', 0),
                'cover':            v('cover', 0),
                'cover_name':       v('cover_name'),
                'cover_address':    v('cover_address'),
                'cover_city':       v('cover_city'),
                'cover_state':      v('cover_state'),
                'cover_zip':        v('cover_zip'),
                'cover_country':    v('cover_country'),
                'cover_phone':      v('cover_phone'),
                'cover_email':      v('cover_email'),
                'cover_company':    v('cover_company'),
                'cover_to_name':    v('cover_to_name'),
                'cover_cc':         v('cover_cc'),
                'cover_subject':    v('cover_subject'),
                'cover_status':     v('cover_status','review'),
                'cover_comments':   v('cover_comments'),
                'callback_url':     v('callback_url')
            }
            if uploaded_file:
                data['filename']    = uploaded_file.filename
            else:
                data['body']        = v('body')

            o(data)

            try:
                job = Job(**data);
                job.validate()
            except ValidationError, err:
                return jsonify(api_error(err.ref)), 400

            db.session.add(job)
            db.session.commit()

            if uploaded_file:
                binary = uploaded_file.stream.read()
            else:
                binary = job.body.replace("\r\n", "\n").encode('utf-8')

            redis_conn = Redis.from_url(current_app.config['REDIS_URI'])
            q = Queue('high', connection=redis_conn)
            q.enqueue_call(func=initial_process, args=(job.id, binary),
                           timeout=300)

            return jsonify(job.public_data())
        else:
            return jsonify(api_error("JOBS_NO_ATTACHMENT")), 400