<template>

<div class="Vlt-card">
  <h1>JWT Generator</h1>
  <div v-show="!jwt" :class="[computedClass, 'Vlt-callout']">
    <i></i>
    <div v-if="invalidAcl" class="Vlt-callout__content">
      Invalid ACL provided. Must be JSON
    </div>
    <div v-else-if="invalidPrivateKey" class="Vlt-callout__content">
      Invalid private key provided
    </div>
    <div v-if="!invalidPrivateKey && !invalidAcl" v-html="callout" class="Vlt-callout__content"/>
  </div>
  <div class="Vlt-grid">

    <div class="Vlt-col">
      <h2>Parameters</h2>
      <div class="Vlt-form__element">
        <label class="Vlt-label">Private Key</label>
        <div class="Vlt-textarea">
          <textarea rows="8" cols="50" v-model="privateKey" id="private-key"></textarea>
        </div>
      </div>
      <div class="Vlt-form__element">
        <label class="Vlt-label">Application ID</label>
        <div class="Vlt-input">
          <input v-model="applicationId" id="application-id"/>
        </div>
      </div>
      <div class="Vlt-form__element">
        <label htmlFor="example-input-icon-button" class="Vlt-label">Valid For</label>
        <div class="Vlt-composite">
          <div class="Vlt-input">
            <input type="number" v-model.number="validFor" placeholder="6" />
          </div>

          <div class="Vlt-composite__append">
            <div class="Vlt-native-dropdown">
              <select v-model.number='validForTimeUnit' defaultValue="3600">
                <option value="1">Seconds</option>
                <option value="60">Minutes</option>
                <option value="3600">Hours</option>
                <option value="86400">Days</option>
              </select>
            </div>
          </div>

        </div>
      </div>
      <div class="Vlt-form__element">
        <label class="Vlt-label">Sub (optional)</label>
        <div class="Vlt-input">
          <input v-model="sub"/>
        </div>
      </div>
      <div class="Vlt-form__element">
        <label class="Vlt-label">ACL (optional)</label>
        <div class="Vlt-textarea">
          <textarea rows="4" cols="50" v-model="acl" id="acl"></textarea>
        </div>
      </div>
    </div>
    <div class="Vlt-col">
      <h2>Encoded</h2>
      <div class="Vlt-form__element">
        <label class="Vlt-label">Your JWT</label>
        <div class="Vlt-textarea">
          <textarea rows="29" cols="50" v-model="jwt" id="jwt"></textarea>
        </div>
      </div>
    </div>
  </div>
  <div class="Vlt-grid">
    <div class="Vlt-col">
      <h2>Decoded</h2>
      <div class="Vlt-table Vlt-table--data">
        <table>
          <thead>
            <tr>
              <th>Name</th>
              <th>Value</th>
              <th>Meaning</th>
            </tr>
          </thead>
          <tbody>
            <tr><td><code>application_id</code></td><td>{{applicationId}}</td><td>The application ID this JWT uses for authentication</td></tr>
            <tr><td><code>iat</code></td><td>{{iat}}</td><td>The time at which the token was issued</td></tr>
            <tr><td><code>nbf</code></td><td>{{nbf}}</td><td>The time at which the token should become valid</td></tr>
            <tr><td><code>exp</code></td><td>{{exp}}</td><td>The time at which the token should expire</td></tr>
            <tr><td><code>sub</code></td><td>{{sub}}</td><td>The subject identified by the JWT (only used for the Client SDKs)</td></tr>
            <tr><td><code>acl</code></td><td>{{acl}}</td><td>A list of permissions that this token will have</td></tr>
            <tr><td><code>jti</code></td><td>{{jti}}</td><td>A unique identifier for the JWT</td></tr>
          </tbody>
        </table>
      </div>
    </div>
  </div>
</div>

</template>

<script> import { KJUR, KEYUTIL} from 'jsrsasign';

export default {

data: function() {
  return {
    sub: '',
    acl: '',
    iat: '',
    jti: '',
    nbf: '',
    applicationId: '',
    validFor: '',
    validForTimeUnit:  3600,
    privateKey: '',
  }
},
created: function() {
  let tNow = KJUR.jws.IntDate.get('now');
  let tEnd = tNow + (3600*6);

  this.iat = tNow;
  this.nbf = tNow;
  this.jti = this.generateJti();
},
computed: {
  invalidAcl: function() {
    let invalid = false;

    if (this.acl) {
      try {
        JSON.parse(this.acl);
      } catch (e) {
        invalid = true;
      }
    }
    return invalid;
  },
  callout: function() {
    let message;

    if (this.privateKey) {
      if (!this.applicationId) {
        message = 'Next, provide an Application ID';
      }
    } else if (this.applicationId) {
      message = 'Next, provide a Private Key';
    } else {
      message = '<h4>Use your <code>private key</code> and <code>application_id</code> to create a JWT for your Vonage Application</h4>The JWT is generated on the client-side so your private key <strong>never leaves your browser</strong>.';
    }
    return message;
  },
  exp: function() {
    let validFor = this.validFor || 6;
    return this.iat + (validFor * this.validForTimeUnit);
  },
  jwt: function() {
    let result = '';
    if (this.privateKey && this.applicationId) {
      try {
        result = this.generateJwt();
      } catch (e) {
        result = '';
      }
    }
    return result;
  },
  invalidPrivateKey: function() {
    let invalid = false;
    if (this.privateKey && this.applicationId) {
      try {
        this.generateJwt();
      } catch (e) {
        invalid = true;
      }
    }
    return invalid;
  },
  computedClass: function() {
    if (this.invalidPrivateKey || this.invalidAcl)
      return 'Vlt-callout--critical';
    if (this.applicationId && this.privateKey)
      return '';
    if (this.applicationId || this.privateKey)
      return 'Vlt-callout--warning';
    if (!this.applicationId && !this.privateKey)
      return 'Vlt-callout--tip';
  }
},
methods: {
  generateJti: function() {
    let text = "";
    let possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

    for (let i = 0; i < 12; i++) {
      text += possible.charAt(Math.floor(Math.random() * possible.length));
    }

    return text;
  },
  buildHeader: function() {
    return JSON.stringify({ typ: 'JWT', alg: 'RS256' });
  },
  buildPayload: function() {
    let payload = {};
    payload.iat = this.iat;
    payload.exp = this.exp;
    payload.jti = this.jti;
    payload.application_id = this.applicationId;
    if (this.sub) { payload.sub = this.sub; }
    if (this.acl) { payload.acl = JSON.parse(this.acl); }
    return JSON.stringify(payload);
  },
  generateJwt: function() {
    let prvKey = KEYUTIL.getKey(this.privateKey);
    return KJUR.jws.JWS.sign("RS256", this.buildHeader(), this.buildPayload(), prvKey);
  }
}

} </script>