#!/usr/bin/env python3

#########################################################
# Written by Carl Youngblood, carl@blockscale.net
# Copyright (c) 2018 Blockscale LLC
# released under the MIT license
#########################################################

from flask import Flask, request, Response, json, jsonify
from src.remote_signer import RemoteSigner
from os import path
import logging

logging.basicConfig(filename='./remote-signer.log', format='%(asctime)s %(message)s', level=logging.INFO)

app = Flask(__name__)

# sample config used for testing
config = {
    'hsm_username': 'resigner',
    'hsm_slot': 1,
    'hsm_lib': '/opt/cloudhsm/lib/libcloudhsm_pkcs11.so',
    'node_addr': 'http://node.internal:8732',
    'keys': {
        'tz3aTaJ3d7Rh4yXpereo4yBm21xrs4bnzQvW': {
            'public_key': 'p2pk67jx4rEadFpbHdiPhsKxZ4KCoczLWqsEpNarWZ7WQ1SqKMf7JsS',
            'private_handle': 7,
            'public_handle': 9
        }
    }
}

logging.info('Opening keys.json')
if path.isfile('keys.json'):
    logging.info('Found keys.json')
    with open('keys.json', 'r') as myfile:
        json_blob = myfile.read().replace('\n', '')
        logging.info('Parsed keys.json successfully as JSON')
        config = json.loads(json_blob)
        logging.info('Config contains: {}'.format(json.dumps(config, indent=2)))


@app.route('/keys/<key_hash>', methods=['POST'])
def sign(key_hash):
    response = None
    try:
        data = request.get_json(force=True)
        if key_hash in config['keys']:
            logging.info('Found key_hash {} in config'.format(key_hash))
            key = config['keys'][key_hash]
            logging.info('Attempting to sign {}'.format(data))
            rs = RemoteSigner(config, data)
            response = jsonify({
                'signature': rs.sign(key['private_handle'])
            })
            logging.info('Response is {}'.format(response))
        else:
            logging.warning("Couldn't find key {}".format(key_hash))
            response = Response('Key not found', status=404)
    except Exception as e:
        data = {'error': str(e)}
        logging.error('Exception thrown during request: {}'.format(str(e)))
        response = app.response_class(
            response=json.dumps(data),
            status=500,
            mimetype='application/json'
        )
    logging.info('Returning flask response {}'.format(response))
    return response


@app.route('/keys/<key_hash>', methods=['GET'])
def get_public_key(key_hash):
    response = None
    try:
        if key_hash in config['keys']:
            key = config['keys'][key_hash]
            response = jsonify({
                'public_key': key['public_key']
            })
            logging.info('Found public key {} for key hash {}'.format(key['public_key'], key_hash))
        else:
            logging.warning("Couldn't public key for key hash {}".format(key_hash))
            response = Response('Key not found', status=404)
    except Exception as e:
        data = {'error': str(e)}
        logging.error('Exception thrown during request: {}'.format(str(e)))
        response = app.response_class(
            response=json.dumps(data),
            status=500,
            mimetype='application/json'
        )
    logging.info('Returning flask response {}'.format(response))
    return response


@app.route('/authorized_keys', methods=['GET'])
def authorized_keys():
    return app.response_class(
        response=json.dumps({}),
        status=200,
        mimetype='application/json'
    )


if __name__ == '__main__':
    app.run(host='127.0.0.1', port=5000, debug=True)

[(14, 'logging.basicConfig', 'logging.basicConfig', ([], {'filename': '"""./remote-signer.log"""', 'format': '"""%(asctime)s %(message)s"""', 'level': 'logging.INFO'}), False, 'import logging\n'), (16, 'flask.Flask', 'Flask', (['__name__'], {}), False, 'from flask import Flask, request, Response, json, jsonify\n'), (33, 'logging.info', 'logging.info', (['"""Opening keys.json"""'], {}), False, 'import logging\n'), (34, 'os.path.isfile', 'path.isfile', (['"""keys.json"""'], {}), False, 'from os import path\n'), (35, 'logging.info', 'logging.info', (['"""Found keys.json"""'], {}), False, 'import logging\n'), (38, 'logging.info', 'logging.info', (['"""Parsed keys.json successfully as JSON"""'], {}), False, 'import logging\n'), (39, 'flask.json.loads', 'json.loads', (['json_blob'], {}), False, 'from flask import Flask, request, Response, json, jsonify\n'), (47, 'flask.request.get_json', 'request.get_json', ([], {'force': '(True)'}), False, 'from flask import Flask, request, Response, json, jsonify\n'), (52, 'src.remote_signer.RemoteSigner', 'RemoteSigner', (['config', 'data'], {}), False, 'from src.remote_signer import RemoteSigner\n'), (59, 'flask.Response', 'Response', (['"""Key not found"""'], {'status': '(404)'}), False, 'from flask import Flask, request, Response, json, jsonify\n'), (78, 'flask.jsonify', 'jsonify', (["{'public_key': key['public_key']}"], {}), False, 'from flask import Flask, request, Response, json, jsonify\n'), (84, 'flask.Response', 'Response', (['"""Key not found"""'], {'status': '(404)'}), False, 'from flask import Flask, request, Response, json, jsonify\n'), (100, 'flask.json.dumps', 'json.dumps', (['{}'], {}), False, 'from flask import Flask, request, Response, json, jsonify\n'), (40, 'flask.json.dumps', 'json.dumps', (['config'], {'indent': '(2)'}), False, 'from flask import Flask, request, Response, json, jsonify\n'), (64, 'flask.json.dumps', 'json.dumps', (['data'], {}), False, 'from flask import Flask, request, Response, json, jsonify\n'), (89, 'flask.json.dumps', 'json.dumps', (['data'], {}), False, 'from flask import Flask, request, Response, json, jsonify\n')]