static/settings.html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Settings</title>
<link rel="stylesheet" href="style/settings.css">
</head>
<body>
<section id="settings">
<div class="panel-container">
<div class="menu">
<a class="item navigationLink active" data-target="accounts">Accounts</a>
<a class="item navigationLink" data-target="crypto">Crypto</a>
<a class="item navigationLink" data-target="sync">Sync</a>
<!-- <a class="item navigationLink" data-target="contribute">
<img class="icon" src="images/icons/mark-github.svg" alt="" />
</a> -->
<a class="item right">
<img class="icon" src="images/icons/CryptoSyncVault_sl.svg" alt=""/>
</a>
</div>
<div id="panel-accounts" class="current">
<section class="accounts">
<header>
<img class="icon" src="images/icons/accounts.svg" alt=""/>
<h3>Cloud accounts</h3>
</header>
<div class="list" id="accountsList"></div>
<!-- <button class="button add">
<img src="images/icons/add.svg" alt="" class="icon" />
</button> -->
</section>
</div>
<div id="panel-crypto">
<section class="crypto">
<header>
<img class="icon" src="images/icons/crypto.svg" alt="">
<h3>Crypto</h3>
</header>
<section class="category">
<h4>Encryption</h4>
<div class="options">
<div class="option">
<span>Algorithm</span>
<span class="right">AES-256-GCM</span>
</div>
<div class="option">
<span>Key length</span>
<span class="right">256 bits</span>
<!-- <select class="right config" data-config="keyLength">
<option value="256">256-bit</option>
</select> -->
</div>
<div class="option">
<span>IV length</span>
<span class="right config">96 bits</span>
</div>
<div class="option">
<span>Salt length</span>
<span class="right ">256 bits</span>
</div>
<div class="option">
<span>PBKDF2 iterations</span>
<span class="right ">5,000</span>
</div>
<div class="option">
<span>Hash function</span>
<span class="right ">MD5</span>
</div>
</div>
</section>
<section class="category">
<h4>Vault</h4>
<div class="options" id="vaultCreds">
<div class="option">
<span>Encryption</span>
</div>
</div>
</section>
<section class="category">
<h4>MasterPass</h4>
<div class="options">
<div class="option">
<span>Encryption</span>
</div>
<div class="option">
<span>PBKDF2 iterations</span>
<span class="right config" data-config="ivLength">100,000</span>
</div>
<div class="option">
<span>Hash function</span>
<span class="right ">SHA256</span>
</div>
<div class="option">
<span>Shares</span>
<select class="right config" data-config="shares">
<option value="2#3">s = 2, n = 3</option>
<option value="2#4">s = 2, n = 4</option>
</select>
</div>
<div class="option">
<img class="info" src="images/icons/info.svg" alt="">
<p class="info">s = Total number of shares <br/> n = Number of shares required to reconstruct MasterPass</p>
</div>
<!-- <div class="option">
<span>Change</span>
<button class="right" id="resetMasterPass">Reset</button>
</div> -->
</div>
</section>
</section>
</div>
<div id="panel-sync">
<section class="sync">
<header>
<img class="icon" src="images/icons/sync.svg" alt=""/>
<h3>Sync</h3>
</header>
<section class="category">
<h4>General</h4>
<div class="options">
<div class="option">
<span>Autostart</span>
<input type="checkbox" class="right config" data-config="autostart" checked/>
</div>
<div class="option">
<span>Encrypt while offline</span>
<input type="checkbox" class="right config" data-config="offlineEnc" checked/>
</div>
</div>
</section>
</section>
</div>
<div id="panel-contribute">
<section class="contribute">
<header>
<img class="icon" src="images/icons/mark-github.svg" alt=""/>
<h3>Contribute</h3>
</header>
<div class="list">
<div class="item">
<a class="navigationLink" data-target="https://github.com/HR/CryptoSync/issues">
<img src="images/icons/issue-opened.svg" class="icon" alt=""/>
<div class="name">
Report an issue / Give feedback
</div>
</a>
</div>
<div class="item">
<a class="navigationLink" data-target="https://github.com/HR/CryptoSync">
<img src="images/icons/star.svg" alt="" class="icon"/>
<div class="name">
Star the repo
</div>
</a>
</div>
<div class="item">
<a class="navigationLink" data-target="https://github.com/HR/CryptoSync/fork">
<img src="images/icons/repo-forked.svg" alt="" class="icon"/>
<div class="name">
Fork the repo
</div>
</a>
</div>
<div class="item">
<a class="navigationLink" data-action="check-updates">
<img src="images/icons/package.svg" alt="" class="icon"/>
<div class="name">
Check for Updates
</div>
</a>
</div>
</div>
<footer>
<img src="images/icons/code.svg" alt="" class="icon"/>
with
<img src="images/icons/heart.svg" alt="" class="icon"/>
by
<br>
<a class="navigationLink" data-target="https://github.com/HR">Habib Rehman</a>
</footer>
</section>
</div>
</div>
</section>
<script id="account-template" type="text/x-handlebars-template">
<div class="item">
<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 class="qouta">{{usage}}
/
{{limit}}</div>
</div>
<img src="images/icons/remove.svg" data-action="remove-{{account}}" class="icon remove right"/>
</div>
</script>
<script id="vault-template" type="text/x-handlebars-template">
<div class="option">
<span>Initialisation Vector</span>
<span class="right">{{viv}}</span>
</div>
<div class="option">
<span>Authentication tag</span>
<span class="right">{{authTag}}</span>
</div>
</script>
<script type="text/javascript">
'use strict'
// TODO: Add reset config feature
window.$ = window.jQuery = require('jquery')
// load core modules first
var remote = require('electron').remote
var accounts = remote.getGlobal("accounts")
var Buffer = require('buffer').Buffer
var Handlebars = require('handlebars')
var ipcRenderer = require('electron').ipcRenderer
var settings = remote.getGlobal("settings")
var creds = remote.getGlobal("creds")
var logger = require('../script/logger.js')
var shell = require('shell')
var userSettings = {}
$(window).on('online', updateOnlineStatus)
$(window).on('offline', updateOnlineStatus)
updateOnlineStatus()
function formatBytes(bytes, precision) {
if (bytes == 0) return '0 byte'
if (isNaN(parseFloat(bytes)) || !isFinite(bytes)) return '-'
if (typeof precision === 'undefined') precision = 0
var units = [
'bytes',
'KB',
'MB',
'GB',
'TB',
'PB'
]
var number = Math.floor(Math.log(bytes) / Math.log(1024))
return (bytes / Math.pow(1024, Math.floor(number))).toFixed(precision) + ' ' + units[number]
}
function buf2hex(buf) {
return (new Buffer(buf)).toString('hex')
}
ipcRenderer.on("resetMasterPassResult", function(event, err, MPKset) {
logger.verbose("IPCRENDER: resetMasterPassResult emitted")
logger.verbose(`resetMasterPassResult: MPKset ${MPKset}, err: ${err}`)
})
$(window).load(function() {
$('#resetMasterPass').unbind().click(function(event) {
event.preventDefault()
ipcRenderer.send("resetMasterPass")
return false
})
//Compile and render template code
for (var account in accounts) {
if (accounts.hasOwnProperty(account)) {
var template = Handlebars.compile($("#account-template").html())
var account = template({
account: account,
type: accounts[account].type,
name: accounts[account].name,
profileImg: accounts[account].profileImg,
email: accounts[account].email,
usage: formatBytes(accounts[account].quota.usage, 2),
limit: formatBytes(accounts[account].quota.limit)
})
$('#accountsList').append(account)
}
}
var creds_temp = Handlebars.compile($("#vault-template").html())
$('#vaultCreds').append(creds_temp({
viv: buf2hex(creds.viv.data),
authTag: buf2hex(creds.authTag.data)
}))
$(".navigationLink").each(function(index) {
var $this = $(this)
$(this).on('click', function(event) {
var target = $this.data("target")
var action = $this.data("action")
if (action) {
// TODO: Action (i.e. check for updates/open updater)
console.log(`${this} has data-action attr of ${action}`)
let r = /^remove-/g
if (r.test(action)) {
ipcRenderer.send('removeAccount', action.replace(r, ''))
} else {
ipcRenderer.send(action)
}
} else {
$(".active").first().removeClass("active")
$("a[data-target='" + target + "']").addClass("active")
navigate(target)
}
return false
})
})
$(".config").each(function(index) {
var $this = $(this)
if (!($.isEmptyObject(settings.user))) {
// TODO: Load defaults
console.log("settings.user is not empty")
setConfig(settings.user)
}
$this.change(function() {
var config = this.getAttribute("data-config")
var isCheckbox = $this.is(':checkbox')
var value = (isCheckbox)
? $this.is(':checked')
: $this.val()
logger.verbose(`RENDER: ${config} has changed to ${value} of type ${typeof value}`)
userSettings[config] = value
logger.verbose(`RENDER: Set userSettings[${config}] to ${userSettings[config]}`)
settings.user = userSettings
})
})
})
/* Helper functions */
function navigate(dest) {
var URLregex = /[-a-zA-Z0-9@:%_\+.~#?&//=]{2,256}\.[a-z]{2,4}\b(\/[-a-zA-Z0-9@:%_\+.~#?&//=]*)?/gi
if (URLregex.test(dest)) {
shell.openExternal(dest)
return
}
var oldSel = $('.panel-container > div.current')
var currSel = $("#panel-" + dest)
if (oldSel)
oldSel.removeClass("current")
$("#panel-" + dest).addClass("current")
}
function setConfig(configObj) {
for (var config in configObj) {
if (configObj.hasOwnProperty(config)) {
var value = configObj[config]
if ($.type(value) === "boolean") {
$("[data-config='" + config + "']").prop('checked', value)
} else {
$("[data-config='" + config + "']").val(value)
}
}
}
}
/* Event emitters */
function updateOnlineStatus() {
// Emitt network change event
ipcRenderer.send('online-status-changed', navigator.onLine
? 'online'
: 'offline')
}
</script>
</body>
</html>