HR/CryptoSync

View on GitHub
static/vault.html

Summary

Maintainability
Test Coverage
<!doctype html>
<html>

  <head>
    <meta charset="utf-8">
    <title>The Vault</title>
    <link rel="stylesheet" href="style/vault.css" charset="utf-8">
    <!-- <script language="javascript" type="text/javascript" src="js/handle.js"></script> -->
  </head>

  <body>
    <section id="vault">
      <header class="top">
        <img src="images/icons/CryptoSyncVault.svg" class="icon centre" alt="">
      </header>
      <div class="main">
        <div class="segment" id="accounts">
          <div class="table" id="accountsList"></div>
        </div>
        <div class="segment" id="files">
          <!-- <input type="text" placeholder="    Search files"/> -->
          <div class="table" id="filesList"></div>
        </div>
        <div class="segment" id="info">
          <div id="content"></div>
          <footer>
            <a class="right" data-action="delete">
              <img src="images/icons/trashcan.svg" alt="delete"/>
            </a>
          </footer>
        </div>
      </div>
    </section>

    <script id="account-template" type="text/x-handlebars-template">
      <div class="row">
        <div class="type">
          <div class="profile" style="background:
    url(data:image/gif;base64,{{profileImg}})
    no-repeat
    center center;"></div>
          <div class="cloudType">
            <img src="images/icons/{{type}}.svg"></img>
          </div>
        </div>
        <div class="content">
          <div class="name">{{name}}</div>
          <div class="email">{{email}}</div>
        </div>
      </div>
    </script>

    <script id="file-template" type="text/x-handlebars-template">
      <div class="file row" data-fid="{{id}}">
        <div class="name">{{name}}</div>
        <div class="lastMod">{{lastSyncedText}}</div>
      </div>
    </script>
    <script id="info-template" type="text/x-handlebars-template">
      <h3>{{name}}</h3>
      <table>
        <tr>
          <td>Last Synced</td>
          <td>{{lastSyncedText}}</td>
        </tr>
        <tr>
          <td>Last Encrypted</td>
          <td>{{lastCryptedText}}</td>
        </tr>
        <tr>
          <td>Path</td>
          <td>{{path}}</td>
        </tr>
        <tr></tr>
        <tr>
          <td>Checksum</td>
          <td>
            <input type="text" value="{{md5Checksum}}"/>
            <a data-action="clip" data-share="{{md5Checksum}}">
              <img src="images/icons/clippy.svg" alt=""/>
            </a>
          </td>
        </tr>
        <tr>
          <td>Initialisation Vector</td>
          <td>
            <input type="text" value="{{iv}}"/>
            <a data-action="clip" data-share="{{iv}}">
              <img src="images/icons/clippy.svg" alt=""/>
            </a>
          </td>
        </tr>
        <tr>
          <td>Authentication Tag</td>
          <td>
            <input type="text" value="{{authTag}}"/>
            <a data-action="clip" data-share="{{authTag}}">
              <img src="images/icons/clippy.svg" alt=""/>
            </a>
          </td>
        </tr>
        <tr id="shares"></tr>
        <tr>
          <td class="bttline">Encryption key</td>
          <td>
            <button class="default">Reconstruct</button>
          </td>
        </tr>
      </table>
    </script>

    <script id="share-template" type="text/x-handlebars-template">
      <td>Shares</td>
      <td>
        {{#each data}}
          <input type="text" value="{{this}}"/>
          <a data-action="clip" data-share="{{this}}"><img src="images/icons/clippy.svg" alt=""/></a>
        {{/each}}
      </td>
    </script>

    <script id="input-template" type="text/x-handlebars-template">
      <input type="text" value="{{value}}"/>
      <a data-action="clip" data-share="{{value}}"><img src="images/icons/clippy.svg" alt=""/></a>`
    </script>

    <script type="text/javascript">
      window.$ = window.jQuery = require('jquery')
      // load core modules first
      var electron = require('electron'),
        remote = electron.remote,
        ipcRenderer = electron.ipcRenderer,
        clipboard = electron.clipboard,
        accounts = remote.getGlobal('accounts'),
        // TODO: ENCAPSULATE files var!
        vault = remote.getGlobal('vault'),
        files = remote.getGlobal('files'),
        _ = require('lodash'),
        moment = require('moment'),
        shares2pass = require('../src/crypto').shares2pass,
        Handlebars = require('handlebars')

      $(window).on('online', updateOnlineStatus)
      $(window).on('offline', updateOnlineStatus)
      updateOnlineStatus()

      Handlebars.registerHelper('each', function(context, options) {
        var ret = ""
        for (var i = 0, j = context.length; i < j; i++) {
          ret = ret + options.fn(context[i])
        }
        return ret
      })

      function handleDelete(fid) {
        $('#filesList > .selected').first().remove()
        var firstFile = $('#filesList > .row').first().addClass('selected')
        if (firstFile) {
          renderSelFileInfo()
        } else {
          var template = Handlebars.compile($('#file-template').html())
          var file = template({name: 'No files to show...'})
          fileList.append(file)
        }
      }

      function renderSelFileInfo(fid) {
        // console.log(`vault: ${JSON.stringify(vault)}`)
        var fid = (fid) ? fid : $('#filesList > .selected').first().data('fid')
        var info_template = Handlebars.compile($('#info-template').html())
        var share_template = Handlebars.compile($('#share-template').html())
        files[fid].lastSyncedText = (_.has(files[fid], 'lastSynced')) ?  moment(files[fid].lastSynced).format('LLLL') :  'not synced yet'
        files[fid].lastCryptedText = (_.has(files[fid], 'lastCrypted')) ? moment(files[fid].lastCrypted).format('LLLL') : 'not encrypted yet'
        var info = info_template(files[fid])
        var shares = share_template(vault.files[fid].shares)

        content = $('#info > #content')
        content.html(info)
        content.find('#shares').html(shares)

        $('button.default').click(function() {
          var pass = shares2pass(vault.files[fid].shares.data).toString('hex')
          console.log(`pass = ${pass}`)
          var input_temp = Handlebars.compile($('#input-template').html())
          $(this).replaceWith(input_temp({value: pass}))
        })

        $('a[data-action="delete"]').click(function() {
          console.log(`delete event triggerd for ${fid}`)
          handleDelete()
        })

        $('a[data-action="clip"]').each(function(index) {
          var self = $(this)
          self.click(function() {
            var fid = self.data('share')
            clipboard.writeText(fid)
            self.prev().fadeOut(300).fadeIn(300)
          })
        })
      }

      $(window).load(function() {
        /* Render accounts */
        for (var account in accounts) {
          if (accounts.hasOwnProperty(account)) {
            var template = Handlebars.compile($('#account-template').html())
            var account = template(accounts[account])
            $('#accountsList').append(account)
          }
        }
        // select first account by default
        $('#accountsList').find('.row').first().addClass('selected')

        var fileList = $('#filesList')
        for (var file in files) {
          if (files.hasOwnProperty(file)) {
            files[file].lastSyncedText = (_.has(file, 'lastSynced')) ?  moment(file.lastSynced).format('LLLL') :  'not synced yet'
            var template = Handlebars.compile($('#file-template').html())
            var file = template(files[file])
            fileList.append(file)
          }
        }
        // select first file of list by default
        $('#filesList').find('.row').first().addClass('selected')

        // render the info for the selected file
        renderSelFileInfo()

        $('.file.row').each(function(index) {
          var self = $(this)
          self.click(function() {
            var fid = self.data('fid'),
              sel = $('#filesList > .selected.row')

            if (fid !== sel.data('fid')) {
              console.log('not equal')
              sel.removeClass('selected')
              self.addClass('selected')
              renderSelFileInfo(fid)
            }
          })
        })
      })

      /* Helper functions */
      // Network change event
      function updateOnlineStatus() {
        ipcRenderer.send('online-status-changed', navigator.onLine
          ? 'online'
          : 'offline')
      }
    </script>
  </body>

</html>