<?php 

set_include_path(get_include_path() . PATH_SEPARATOR . '../../app');
include_once "base_controller.php";
include_once "utils.php";

class ServiceConfig extends BaseController {

  protected function signinRequired() {
    return true;
  }

  protected function adminRequired() {
    return true;
  }

  protected function applyHTTPSCerts() {
    $response = array();
    $certs_dir = "/etc/nginx/certs";

    //check if there is uploaded certificates 
    if (!file_exists(build_file_path($certs_dir, "uploaded/cert")) 
      || !file_exists(build_file_path($certs_dir, "uploaded/key")))
      $this->renderAjaxError($response, "please upload certificate and key first");

    //run nginx conf test against uploaded cert and key
    $output = rtrim(`(cd $certs_dir && ln -nsf uploaded live && nginx -q -t && echo OK) || echo ERROR`)
    if (endsWith($output, 'OK')) {
      //try to apply the cert and key
      $output = rtrim(`(cd $certs_dir && mkdir -p prod && mv uploaded/cert uploaded/key prod/ && ln -nsf prod live && nginx -s reload && echo OK) || echo ERROR`)
      if (endsWith($output, 'OK'))
        $this->renderAjaxSuccess2($response);
      else //fall back to default cert and key if it fails
        `cd $certs_dir && ln -nsf default live && nginx -s reload`
    } else {
      //restore to production cert and key, if that is missing, fall back to default
      $restore_to = file_exists(build_file_path($certs_dir, 'prod')) ? 'prod' : 'default';
      `cd $certs_dir && ln -nsf $restore_to live`
    }
    $this->renderAjaxError($response, "failed to apply uploaded cert and key");
  }

  protected function downloadHTTPSCerts() {
    $response = array();
    $certs_dir = "/etc/nginx/certs/prod";

    if (!file_exists($certs_dir) 
      || !file_exists(build_file_path($certs_dir, "cert")) 
      || !file_exists(build_file_path($certs_dir, "key")) )
      $this->renderAjaxError($response, "certificate are not available");

    $url = 'service_config.php?action=dlHTTPSCerts';
    $this->redirect($url);
  }

  public function doAjaxPost() {
    $response = array();
    $action = null;
    if (isset($_POST['action']))
      $action = $_POST['action']; 

    if (is_null($action))
      $this->renderAjaxError($response, "invalid action: " . $action);
    
    if ($action == "apply_https_certs")
      $this->applyHTTPSCerts();
    else if ($action == "download_https_cert")
      $this->downloadHTTPSCerts();
    else
      $this->renderAjaxError($response, "invalid action: " . $action);
  }

  public function doGet() {
    if (!isset($_GET['action']))
      return;

    $action = $_GET['action'];
    if ($action == 'dlHTTPSCerts') {
      $certs_dir = "/etc/nginx/certs/prod";
      $content = `cd $certs_dir && tar -cf - cert key`
      $this->genDownloadResp($content, "certs.tar"); 
    }
  }
}

$controller = new ServiceConfig();
$controller->run();

?>
<!DOCTYPE html>
<html>
  <head>
    <eta charset="utf-8" />
    <title>Service Config</title>
    <eta name="viewport" content="width=device-width, initial-scale=1.0">

    <link rel="stylesheet" href="../../css/bootstrap.min.css" media="screen" />
    <link rel="stylesheet" href="../../css/dropzone.css" media="screen" />
    <link rel="stylesheet" href="../../css/flatpickr.min.css" media="screen" />

    <link rel="stylesheet" href="css/service_config.css" media="screen" />
  </head>
  <body>
    <div class="container" id="service_config_content">
      <div class="navbar">
        <div class="navbar-inner">
          <a class="brand" href="/">EasyIO</a>
          <ul class="nav">
            <li class="divider-vertical"></li>
            <li v-for="sec in sections" :class="{active:isSectionActive(sec)}"><a href="#" @click="active_sec_id=sec.sec_id">{{ sec.name }}</a></li>
          </ul>
        </div>
      </div>

      <div class="row">
        <alert></alert>
        <keep-alive>
          <component :is="active_sec_id"></component>
        </keep-alive>
      </div>
    </div>

    <!-- component templates -->
    <script type="text/x-template" id="alert-template">
    <div class="span12">
      <div class="alert" :class="label_class" v-show="show">
        <button type="button" class="close" @click="show=false">&times;</button>
        <strong>{{ title }}</strong> {{ msg }}
      </div>
    </div>
    </script>
    <?php include "partials/modal_tmpl.php"; ?>

    <!-- app component -->
    <script type="text/x-template" id="https_cert_upload_template">
      <div class="dropzone needsclick dz-clickable">
        <div class="dz-message needsclick">
          <slot></slot>
        </div>
      </div>
    </script>

    <script type="text/x-template" id="web_config_template">
      <div class="span12">
        <div class="well">
          <div class="page-header" style="margin-bottom:0">
            <h4>HTTPS Certificate</h4>
          </div>
          <!-- 
          <div class="alert">
            <strong>Warning:</strong> The uploaded certificate will take effect after controller reboot. Make sure the certificate is a valid, otherwise the web server may stop working after reboot.
          </div>
          -->

          <h3>Certificate File:</h3>
          <https-cert-upload server_url="file_upload.php" accepted_files=".pem,.crt,.cer" param_name="cert">
            <span>Drop <strong>certificate(.pem,.crt,.cer)</strong> file here or click to select.</span>
          </https-cert-upload>

          <h3>Key File:</h3>
          <https-cert-upload server_url="file_upload.php" accepted_files=".pem,.key" param_name="key">
            <span>Drop <strong>key(.pem,.key)</strong> file here or click to select.</span>
          </https-cert-upload>

          <div class="row" style="margin-top: 20px">
            <button type="button" class="btn btn-primary btn-large pull-right" @click="applyHTTPSCert">Apply</button>
            <button type="button" class="btn btn-large" style="margin-left: 20px;" @click="downloadHTTPSCert">Download</button>
          </div>
          
        </div>
      </div>
    </script>

    <script type="text/x-template" id="openvpn_server_template">
      <div class="row">
        <div class="span12">
        <form class="form-horizontal" @submit.prevent="saveOpenVPNConfig">

          <div class="control-group" :class="{error: caError}">
            <div class="control-label">Certificate Authority:</div>
            <div class="controls">
              <template v-if="ca">
                <span class="label label-success">READY</span>
              </template>
              <template v-else>
                <button class="btn btn-warning" type="button" @click="collectCAData">Generate CA</button>
                <span class="help-inline" v-show="caError">Must generate certificate authority before openvpn server can work.</span>
              </template>
            </div>
          </div>
          <div class="control-group" :class="{error: serverCertError}">
            <div class="control-label">Server Certificate:</div>
            <div class="controls">
              <template v-if="serverCert">
                <span class="label label-success">READY</span>
              </template>
              <template v-else>
                <button class="btn btn-warning" type="button" @click="collectServerCertData">Generate Server Certificate</button>
                <span class="help-inline" v-show="serverCertError">Server certificate is not generated yet.</span>
              </template>
            </div>
          </div>

          <div class="control-group">
            <label class="control-label">Protocol:</label>
            <div class="controls">
              <select v-model="proto">
                <option value="tcp">TCP</option>
                <option value="udp">UDP</option>
              </select>
            </div>   
          </div>
          <div class="control-group" :class="{error:portError}">
            <div class="control-label" for="inputPort">Port:</div>
            <div class="controls">
              <input id="inputPort" type="number" v-model.number="port" >
              <span class="help-inline" v-show="portError">Invalid port value</span>
            </div>
          </div>

          <div class="control-group" :class="{error:ipError}">
            <div class="control-label" for="inputIPAddress">VPN Subnet:</div>
            <div class="controls">
              <input id="inputIPAddress" type="text" v-model.trim="ip">
              <span class="help-inline" v-show="ipError">Invalid Subnet Address</span>
            </div>
          </div>
          <div class="control-group" :class="{error:netmaskError}">
            <div class="control-label" for="inputNetMask">VPN Network Mask:</div>
            <div class="controls">
              <input id="inputNetMask" type="text" v-model.trim="netmask">
              <span class="help-inline" v-show="netmaskError">Invalid VPN Network Mask</span>
            </div>
          </div>

          <div class="control-group">
            <div class="controls">
              <button type="submit" class="btn">Save</button>
            </div>
          </div>
        </form>
        </div>

        <odalComp ref="gen_ca_modal" @confirmed="generateCA">
          <template slot="header">Generate CA</template>

          <div class="alert">
            <strong>Warning!</strong> After CA is created, you can not modify it anymore, please make sure the value of 'Common Name' field is correct.
          </div>
          <form class="form-horizontal" @submit.prevent>
            <div class="control-group" :class="{error: caCNError}">
              <div class="control-label" for="inputCN">Common Name:</div>
              <div class="controls">
                <input id="inputCN" type="text" v-model.trim="caCN">
                <span class="help-inline" v-show="caCNError">Invalid CA Common Name</span>
              </div>
            </div>
          </form>
        </modalComp>

        <odalComp ref="gen_cert_modal" @confirmed="generateServerCert">
          <template slot="header">Generate Certificate</template>

          <form class="form-horizontal" @submit.prevent>
            <div class="control-group" :class="{error: serverCertCNError}">
              <div class="control-label" for="inputCertCN">Common Name:</div>
              <div class="controls">
                <input id="inputCertCN" type="text" v-model.trim="serverCertCN">
                <span class="help-inline" v-show="serverCertCNError">Invalid Certificate Common Name</span>
              </div>
            </div>
          </form>
        </modalComp>
      </div>
    </script>

    <script type="text/x-template" id="openvpn_client_ovpn_generation_template">
      <div class='row'>
        <div class="span12">
        <form class="form-horizontal" @submit.prevent="generateClientOVPN">
          <div class="control-group" :class="{error:clientNameError}">
            <div class="control-label" for="inputClientName">Client Name:</div>
            <div class="controls">
              <input id="inputClientName" type="text" v-model.trim="clientName">
              <span class="help-inline" v-show="!clientNameError">Unique client name</span>
              <span class="help-inline" v-show="clientNameError">Invalid client name</span>
            </div>
          </div>

          <div class="control-group" :class="{error:ipError}">
            <div class="control-label" for="inputIPAddress">Remote Server IP:</div>
            <div class="controls">
              <input id="inputIPAddress" type="text" v-model.trim="ip">
              <span class="help-inline" v-show="!ipError">The IP address used to connect to the VPN server, normally should be the router's IP.</span>
              <span class="help-inline" v-show="ipError">Invalid IP address</span>
            </div>
          </div>
          <div class="control-group" :class="{error:portError}">
            <div class="control-label" for="inputPort">Port:</div>
            <div class="controls">
              <input id="inputPort" type="number" v-model.number="port" >
              <span class="help-inline" v-show="!portError">Normally should be router's port that forwards data to above VPN server's port</span>
              <span class="help-inline" v-show="portError">Invalid port value</span>
            </div>
          </div>

          <div class="control-group">
            <div class="controls">
              <button type="submit" class="btn">Generate & Download</button>
            </div>
          </div>
        </form>
        </div>
      </div>
    </script>

    <script type="text/x-template" id="openvpn_config_template">
      <div class="span12">
        <div class="well well-small">
            <div class="page-header"> <h4>Server Config</h4> </div>
            <openvpn-server />
        </div>
        <div class="well well-small">
          <div class="page-header"> <h4>Generate & Download Client Config(.ovpn)</h4> </div>
          <div class="alert alert-info">
            <button type="button" class="close" data-dismiss="alert">&times;</button>
            <strong>NOTE:</strong> Generate & Download OpenVPN client config file(.ovpn) that can connect to OpenVPN server configured by above settings. Please make sure above server settings are correct and work well.
          </div>
          <openvpn-client-ovpn-generator />
        </div>
      </div>
    </script>

    <script type="text/x-template" id="auth_key_editor_template">
      <tr v-show='editing'>
        <td colspan="4">
          <form class="form-inline" style="margin-bottom:0px; margin-left:28px;" @submit.prevent="saveModification">
          <div class="control-group input-append" style="display: inline;" :class="{error: this.expired_at.length <= 0}">
            <input type="text" placeholder="<?php echo L('Expiry Date') ?>" v-model="expired_at" readonly>
              <span class="add-on" @click="showHideCalendar"><i class="icon-calendar"></i></span>
            </div>

            <div class="control-group" style="display:inline" :class="{error: note_error}">
            <input type="text" placeholder="<?php echo L('Note') ?>" v-model="note" style="margin-left:10px; margin-right:10px;" >
            </div>

            <button type="submit" class="btn btn-mini btn-primary"><?php echo L('Save') ?></button>
            <button class="btn btn-mini" @click.prevent="$emit('editorCancelled')"><?php echo ('Cancel') ?></button>
          </form>
        </td>
      </tr>
    </script>

    <script type="text/x-template" id="auth_key_config_template">
      <div class="row">
        <div class="alert hide"></div>
        <div class="span12">
          <form class="form-horizontal span12" @submit.prevent="createAuthKey">
            <div class="control-group" :class="{error: expired_at_error}">
              <label class="control-label" for="inputAuthKeyExpiration"><?php echo L('Expiry Date') ?></label>
              <div class="controls input-append" id="authKeyExpiration" style="display: block;">
                <input type='text' id="inputAuthKeyExpiration" readonly :value="expired_at"></input>
                <span class="add-on" @click="showCalendar">
                  <i class="icon-calendar"></i>
                </span>

                <span class="help-block" v-show="expired_at_error" style="font-size: 14px;">Invalid Expiry Date</span>
              </div>
            </div>
            <div class="control-group" :class="{error: note_error}">
              <label class="control-label" for="inputAuthKeyNote"><?php echo L('Note') ?></label>
              <div class="controls">
                <input id="inputAuthKeyNote" type="text" placeholder="<?php echo L('Note for this AuthKey') ?>" focus v-model="note">
                <span class="help-block" v-show="note_error" style="font-size: 14px;">Note can not be longer than 64 characters.</span>
              </div>
            </div>
            <div class="control-group">
              <div class="controls">
                <button id="save_auth_key_btn" type="submit" class="btn btn-primary"><?php echo L('Create') ?></button>
              </div>
            </div>
          </form>
        </div>
        <hr/>

        <div class="span12"  style="width:920px;">
        <table class="table table-striped table-hover">
          <thead>
            <tr>
              <th @click="sortBy('key')"><?php echo L('Key') ?></th>
              <th @click="sortBy('expired_at')"><?php echo L('Expiry Date') ?></th>
              <th @click="sortBy('note')"><?php echo L('Note') ?></th>
              <th></th>
            </tr>
          </thead>
          <tbody> 
            <template v-for="(key, index) in keys">
              <tr>
                <td><i class="icon-certificate"></i> {{key.key}}</td>
                <td>{{key.expired_at}}</td>
                <td>{{key.note}}</td>
                <td>
                  <button class="btn btn-mini" @click="toggleAuthKeyEditor(key)"><?php echo L('Edit') ?></button>
                  <button class="btn btn-mini btn-danger" @click="delAuthKey(key, index)"><?php echo L('Delete') ?></button>
                </td>
              </tr>
              <auth-key-editor :editing="key.editing" :initial_note="key.note" :initial_expired_at="key.expired_at" @editCompleted="function(n, e) { onEditCompleted(key, n, e); }" @editorCancelled="key.editing = false" />
            </template>
          </tbody>
        </table> 
        </div>
      </div>
    </script>

    <script type="text/x-template" id="data_api_config_template">
      <div class="span12">
        <div class="well well-small">
          <div class="page-header">
            <h4>Authentication Key</h4>
          </div>
          <auth-key-config />
        </div>
      </div>
    </script>

    <script language="javascript" type="text/javascript">
      window.iot_platform = '<?php echo platformName() ?>';
    </script>

    <script type="text/javascript" src="../../js/jquery-1.10.0.min.js"></script>
    <script type="text/javascript" src="../../js/bootstrap.min.js"></script>
    <script type="text/javascript" src="../../js/underscore-min.js"></script>
    <script type="text/javascript" src="../../js/dropzone.js"></script>
    <script type="text/javascript" src="../../js/spin.min.js"></script>
    <script type="text/javascript" src="../../js/flatpickr.min.js"></script>

<?php
  if (isset($_GET["dev"])) {
?>
    <script type="text/javascript" src="../../js/vue.js"></script>
<?php
  } else {
?>
    <script type="text/javascript" src="../../js/vue.min.js"></script>
<?php
  }
?>
    <script type="text/javascript" src="../../js/plugin-utils.js"></script>
    <script type="text/javascript" src="../../js/vue-alert-component.js"></script>
    <script type="text/javascript" src="../../js/vue-modal-component.js"></script>
    <script type="text/javascript" src="js/service_config.js"></script>
  </body>
</html>