# Source: Certificate.js

    /**
     * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *   http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */

    'use strict';

    const crypto = require('crypto');
    const fs = require('fs');
    const request = require('request');

    /**
     * 认证
     **/
    class Certificate {
        /**
         * @param {Object} headers http请求的header
         * @param {string} requestBody 请求体
         * @param {string} privateKeyContent 私钥. 用于请求DuerOS参数签名
         **/
        constructor (headers, requestBody, privateKeyContent = '') {
            this.data = requestBody;
            this.headers = headers;
            this.privateKey = privateKeyContent;
            this.verifyRequestSign = false;
        }

        /**
         * 开启验证请求参数签名，阻止非法请求
         *
         * @return {boolean}
         * @public
         */
        enableVerifyRequestSign() {
            this.verifyRequestSign = true;
            return this;
        }
        /**
         * 关闭验证请求参数签名
         *
         * @return {boolean}
         * @public
         */
        disableVerifyRequestSign() {
            this.verifyRequestSign = false;
            return this;
        }

        /**
         * @return promise
         * @private
         */
        _getRequestPublicKey() {
            var _this = this;
            return new Promise(function(resolve, reject){
                var url = _this.headers.signaturecerturl;
                if(!url) {
                    reject();
                }

                var hash = crypto.createHash('md5');
                var cache = __dirname + '/' + hash.update(url).digest('hex');

                let content = '';
                fs.access(cache, (err) => {
                    if(err) {
                        request({
                            url: url,
                            method: 'GET',
                        }, function(error, response, body){
                            let content = body;

                            if(!content) {
                                return reject();
                            }

                            fs.writeFile(cache, content, {encoding: "utf8"}, (err) => {
                                if (err) {
                                    console.error(err);
                                }

                                // 缓存失败，但内容已经获取了
                                resolve(content);
                            });
                        });
                    } else {
                        fs.readFile(cache, {encoding: "utf8"}, (err, data) => {
                            if(err) {
                                console.error(err);
                                reject();
                            } else {
                                resolve(data);
                            }
                        });
                    }
                });
            });
        }

        /**
         * @desc 验证请求者是否合法
         * @return promise
         * @public
         */
        verifyRequest() {
            var _this = this;
            return new Promise(function(resolve, reject){
                var verify = crypto.createVerify('RSA-SHA1');

                if(!_this.verifyRequestSign) {
                    resolve(true);
                }

                _this._getRequestPublicKey().then(function(publicKey){

                    if(!publicKey || !_this.data) {
                        reject();
                    }

                    verify.update(_this.data);
                    let isSignatureValid = verify.verify(publicKey.toString(), _this.getRequestSig(), 'base64');
                    if(isSignatureValid) {
                        resolve(isSignatureValid);
                    }else {

                        reject();
                    }

                }, function(){
                    reject();
                });
            });
        }

        /**
         * @return string
         * @public
         */
        getRequestSig() {
            return this.headers.signature;
        }
    }

    module.exports = Certificate;