<commit_before>from constants import *
from exceptions import *
from loader import Loader
import loader
import os
import json
import time
import base64
import hashlib
import flask
import uuid
import cherrypy.wsgiserver
import tunldb
import threading
import functools
import werkzeug.debug.tbtools
import redis

app = flask.Flask('pritunl_loader')
app.secret_key = os.urandom(32)
app_db = tunldb.TunlDB()
app_db.set('state', 't')
redis_conn = redis.StrictRedis.from_url(REDIS_URL)

def get_remote_addr():
    if 'X-Forwarded-For' in flask.request.headers:
        return flask.request.headers.getlist('X-Forwarded-For')[0]
    if 'X-Real-Ip' in flask.request.headers:
        return flask.request.headers.getlist('X-Real-Ip')[0]
    return flask.request.remote_addr

def cors_headers(call):
    @functools.wraps(call)
    def wrapped(*args, **kwargs):
        if flask.request.method == 'OPTIONS':
            response = app.make_default_options_response()
        else:
            response = flask.make_response(call(*args, **kwargs))
        response.headers.add('Access-Control-Allow-Origin', ORIGIN_URL)
        response.headers.add('Access-Control-Allow-Methods',
            'GET,PUT,POST,DELETE,OPTIONS')
        response.headers.add('Access-Control-Max-Age', '600')
        response.headers.add('Access-Control-Allow-Headers',
            'Authorization,Content-Type,Accept,Origin,User-Agent,' +
            'DNT,Cache-Control,X-Mx-ReqToken,Keep-Alive,' +
            'X-Requested-With,If-Modified-Since')
        response.headers.add('Access-Control-Allow-Credentials', 'true')
        return response
    return wrapped

def create_droplet(client_id, api_key, region):
    loader = Loader(api_key, region)
    try:
        loader.install()
        time.sleep(10)
        app_db.dict_remove(client_id, 'error')
        app_db.dict_set(client_id, 'success', ('Your Pritunl server has ' +
            'successfully launched, you will be emailed a new root ' +
            'password to access the droplet. You may login to your ' +
            'Pritunl server using the default username and password ' +
            '"admin" at: <a href="https://%s:9700/" target="_blank">' +
            'https://%s:9700/</a>') % (loader.host, loader.host))
    except InvalidApiKey:
        app_db.dict_set(client_id, 'error', 'Failed to create Pritunl ' +
        'server, DigitalOcean API token is invalid.')
    except KeyImportError:
        app_db.dict_set(client_id, 'error', 'Failed to create Pritunl ' +
        'server, unable to import ssh key into DigitalOcean.')
    except CreateDropletError:
        app_db.dict_set(client_id, 'error', 'Failed to create Pritunl ' +
        'server, unable to create droplet.')
    except ResetPasswordError:
        app_db.dict_set(client_id, 'error', 'Failed to create Pritunl ' +
        'server, failed to reset password.')
    except DropletTimeout:
        app_db.dict_set(client_id, 'error', 'Failed to create Pritunl ' +
        'server, connection to droplet timed out.')
    except DropletExecError:
        app_db.dict_set(client_id, 'error', 'Failed to create Pritunl ' +
        'server, failed to execute command on server.')
    except:
        traceback = werkzeug.debug.tbtools.get_current_traceback()
        print traceback.render_summary()
        app_db.dict_set(client_id, 'error', 'Failed to create Pritunl ' +
        'server, unknown error occurred.')
    app_db.dict_set(client_id, 'status', 'f')
    app_db.expire(client_id, CLIENT_EXPIRE)
    app_db.publish(client_id, 'event')

def filter_str(in_str):
    if not in_str:
        return in_str
    return ''.join(x for x in in_str if x.isalnum())

def jsonify(data=None, status_code=None):
    if not isinstance(data, basestring):
        data = json.dumps(data)
    response = flask.Response(response=data, mimetype='application/json')
    response.headers.add('Cache-Control',
        'no-cache, no-store, must-revalidate')
    response.headers.add('Pragma', 'no-cache')
    if status_code is not None:
        response.status_code = status_code
    return response

def get_client_dict(client_id):
    status = app_db.dict_get(client_id, 'status')
    return {
        'id': client_id,
        'status': True if (status == 't') else False,
        'region': app_db.dict_get(client_id, 'region'),
        'success': app_db.dict_get(client_id, 'success'),
        'error': app_db.dict_get(client_id, 'error'),
    }

@app.route('/loader', methods=['GET', 'OPTIONS'])
@app.route('/loader/<client_id>', methods=['GET', 'OPTIONS'])
@cors_headers
def loader_get(client_id=None):
    client_id = client_id or flask.session.get('id') or app_db.get(
        get_remote_addr())
    if not client_id:
        client_id = uuid.uuid4().hex
        flask.session['id'] = client_id
        app_db.expire(get_remote_addr(), CLIENT_IP_EXPIRE)
        app_db.set(get_remote_addr(), client_id)

    if app_db.get('state') != 't' and \
            app_db.dict_get(client_id, 'status') != 't':
        return jsonify(get_client_dict(client_id), 503)

    return jsonify(get_client_dict(client_id))

@app.route('/loader', methods=['POST'])
@app.route('/loader/<client_id>', methods=['POST'])
@cors_headers
def loader_post(client_id=None):
    client_id = client_id or flask.session.get('id') or app_db.get(
        get_remote_addr())
    if not client_id:
        client_id = uuid.uuid4().hex
        flask.session['id'] = client_id
        app_db.expire(get_remote_addr(), CLIENT_IP_EXPIRE)
        app_db.set(get_remote_addr(), client_id)

    api_key = filter_str(flask.request.json['api_key'])[:256]
    region = filter_str(flask.request.json['region'])[:256]

    if app_db.dict_get(client_id, 'status') != 't':
        if app_db.get('state') != 't':
            app_db.remove(client_id)
            return jsonify(get_client_dict(client_id), 503)
        redis_conn.set(uuid.uuid4().hex, str(int(time.time())))
        app_db.expire(client_id, CLIENT_EXPIRE)
        app_db.dict_set(client_id, 'status', 't')
        app_db.dict_set(client_id, 'region', region)
        threading.Thread(target=create_droplet,
            args=(client_id, api_key, region)).start()

    return jsonify(get_client_dict(client_id))

@app.route('/loader', methods=['DELETE'])
@app.route('/loader/<client_id>', methods=['DELETE'])
@cors_headers
def loader_delete(client_id=None):
    client_id = client_id or flask.session.get('id') or app_db.get(
        get_remote_addr())
    if client_id:
        app_db.remove(client_id)
        flask.session.pop('id', None)
    return jsonify({})

@app.route('/poll', methods=['GET', 'OPTIONS'])
@app.route('/poll/<client_id>', methods=['GET', 'OPTIONS'])
@cors_headers
def poll_get(client_id=None):
    client_id = client_id or flask.session.get('id') or app_db.get(
        get_remote_addr())
    if not client_id:
        client_id = uuid.uuid4().hex
        flask.session['id'] = client_id
        app_db.expire(get_remote_addr(), CLIENT_IP_EXPIRE)<commit_msg>Remove host stored client id when third-party cookies available<commit_after>from constants import *
from exceptions import *
from loader import Loader
import loader
import os
import json
import time
import base64
import hashlib
import flask
import uuid
import cherrypy.wsgiserver
import tunldb
import threading
import functools
import werkzeug.debug.tbtools
import redis

app = flask.Flask('pritunl_loader')
app.secret_key = os.urandom(32)
app_db = tunldb.TunlDB()
app_db.set('state', 't')
redis_conn = redis.StrictRedis.from_url(REDIS_URL)

def get_remote_addr():
    if 'X-Forwarded-For' in flask.request.headers:
        return flask.request.headers.getlist('X-Forwarded-For')[0]
    if 'X-Real-Ip' in flask.request.headers:
        return flask.request.headers.getlist('X-Real-Ip')[0]
    return flask.request.remote_addr

def cors_headers(call):
    @functools.wraps(call)
    def wrapped(*args, **kwargs):
        if flask.request.method == 'OPTIONS':
            response = app.make_default_options_response()
        else:
            response = flask.make_response(call(*args, **kwargs))
        response.headers.add('Access-Control-Allow-Origin', ORIGIN_URL)
        response.headers.add('Access-Control-Allow-Methods',
            'GET,PUT,POST,DELETE,OPTIONS')
        response.headers.add('Access-Control-Max-Age', '600')
        response.headers.add('Access-Control-Allow-Headers',
            'Authorization,Content-Type,Accept,Origin,User-Agent,' +
            'DNT,Cache-Control,X-Mx-ReqToken,Keep-Alive,' +
            'X-Requested-With,If-Modified-Since')
        response.headers.add('Access-Control-Allow-Credentials', 'true')
        return response
    return wrapped

def create_droplet(client_id, api_key, region):
    loader = Loader(api_key, region)
    try:
        loader.install()
        time.sleep(10)
        app_db.dict_remove(client_id, 'error')
        app_db.dict_set(client_id, 'success', ('Your Pritunl server has ' +
            'successfully launched, you will be emailed a new root ' +
            'password to access the droplet. You may login to your ' +
            'Pritunl server using the default username and password ' +
            '"admin" at: <a href="https://%s:9700/" target="_blank">' +
            'https://%s:9700/</a>') % (loader.host, loader.host))
    except InvalidApiKey:
        app_db.dict_set(client_id, 'error', 'Failed to create Pritunl ' +
        'server, DigitalOcean API token is invalid.')
    except KeyImportError:
        app_db.dict_set(client_id, 'error', 'Failed to create Pritunl ' +
        'server, unable to import ssh key into DigitalOcean.')
    except CreateDropletError:
        app_db.dict_set(client_id, 'error', 'Failed to create Pritunl ' +
        'server, unable to create droplet.')
    except ResetPasswordError:
        app_db.dict_set(client_id, 'error', 'Failed to create Pritunl ' +
        'server, failed to reset password.')
    except DropletTimeout:
        app_db.dict_set(client_id, 'error', 'Failed to create Pritunl ' +
        'server, connection to droplet timed out.')
    except DropletExecError:
        app_db.dict_set(client_id, 'error', 'Failed to create Pritunl ' +
        'server, failed to execute command on server.')
    except:
        traceback = werkzeug.debug.tbtools.get_current_traceback()
        print traceback.render_summary()
        app_db.dict_set(client_id, 'error', 'Failed to create Pritunl ' +
        'server, unknown error occurred.')
    app_db.dict_set(client_id, 'status', 'f')
    app_db.expire(client_id, CLIENT_EXPIRE)
    app_db.publish(client_id, 'event')

def filter_str(in_str):
    if not in_str:
        return in_str
    return ''.join(x for x in in_str if x.isalnum())

def jsonify(data=None, status_code=None):
    if not isinstance(data, basestring):
        data = json.dumps(data)
    response = flask.Response(response=data, mimetype='application/json')
    response.headers.add('Cache-Control',
        'no-cache, no-store, must-revalidate')
    response.headers.add('Pragma', 'no-cache')
    if status_code is not None:
        response.status_code = status_code
    return response

def get_client_dict(client_id):
    status = app_db.dict_get(client_id, 'status')
    return {
        'id': client_id,
        'status': True if (status == 't') else False,
        'region': app_db.dict_get(client_id, 'region'),
        'success': app_db.dict_get(client_id, 'success'),
        'error': app_db.dict_get(client_id, 'error'),
    }

@app.route('/loader', methods=['GET', 'OPTIONS'])
@app.route('/loader/<client_id>', methods=['GET', 'OPTIONS'])
@cors_headers
def loader_get(client_id=None):
    if 'id' in flask.session:
        app_db.remove(get_remote_addr())
    client_id = client_id or flask.session.get('id') or app_db.get(
        get_remote_addr())
    if not client_id:
        client_id = uuid.uuid4().hex
        flask.session['id'] = client_id
        app_db.expire(get_remote_addr(), CLIENT_IP_EXPIRE)
        app_db.set(get_remote_addr(), client_id)

    if app_db.get('state') != 't' and \
            app_db.dict_get(client_id, 'status') != 't':
        return jsonify(get_client_dict(client_id), 503)

    return jsonify(get_client_dict(client_id))

@app.route('/loader', methods=['POST'])
@app.route('/loader/<client_id>', methods=['POST'])
@cors_headers
def loader_post(client_id=None):
    if 'id' in flask.session:
        app_db.remove(get_remote_addr())
    client_id = client_id or flask.session.get('id') or app_db.get(
        get_remote_addr())
    if not client_id:
        client_id = uuid.uuid4().hex
        flask.session['id'] = client_id
        app_db.expire(get_remote_addr(), CLIENT_IP_EXPIRE)
        app_db.set(get_remote_addr(), client_id)

    api_key = filter_str(flask.request.json['api_key'])[:256]
    region = filter_str(flask.request.json['region'])[:256]

    if app_db.dict_get(client_id, 'status') != 't':
        if app_db.get('state') != 't':
            app_db.remove(client_id)
            return jsonify(get_client_dict(client_id), 503)
        redis_conn.set(uuid.uuid4().hex, str(int(time.time())))
        app_db.expire(client_id, CLIENT_EXPIRE)
        app_db.dict_set(client_id, 'status', 't')
        app_db.dict_set(client_id, 'region', region)
        threading.Thread(target=create_droplet,
            args=(client_id, api_key, region)).start()

    return jsonify(get_client_dict(client_id))

@app.route('/loader', methods=['DELETE'])
@app.route('/loader/<client_id>', methods=['DELETE'])
@cors_headers
def loader_delete(client_id=None):
    client_id = client_id or flask.session.get('id') or app_db.get(
        get_remote_addr())
    if client_id:
        app_db.remove(client_id)
        flask.session.pop('id', None)
    return jsonify({})

@app.route('/poll', methods=['GET', 'OPTIONS'])
@app.route('/poll/<client_id>', methods=['GET', 'OPTIONS'])
@cors_headers
def poll_get(client_id=None):
    if 'id' in flask.session:
        app_db.remove(get_remote_addr())
    client_id = client_id or flask.session.get('id') or app_db.get(
        get_remote_addr())
    if not client_id:
        client_id = uuid.uuid4().hex
        flask.session['id'] = client_id
        app_db.expire(get_remote_addr(), CLIENT_IP_EXPIRE)
{'fraction_non_alphanumeric': 0.13515981735159818, 'fraction_numerical': 0.004917456972251493, 'mean_word_length': 3.384354789036033, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 15, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1853517', 'n_tokens_mistral': 4835, 'n_tokens_neox': 4758, 'n_words': 946}