diff --git a/main.go b/main.go
index 3c0afb6..2da625f 100644
--- a/main.go
+++ b/main.go
@@ -279,6 +279,7 @@ func nodeCreate(w http.ResponseWriter, r *http.Request) {// {{{
})
}// }}}
func nodeUpdate(w http.ResponseWriter, r *http.Request) {// {{{
+ log.Println("/node/update")
var err error
var session Session
diff --git a/static/js/node.mjs b/static/js/node.mjs
index bec4d80..22df9e7 100644
--- a/static/js/node.mjs
+++ b/static/js/node.mjs
@@ -54,7 +54,11 @@ export class NodeUI extends Component {
let page = ''
switch(this.page.value) {
case 'node':
- if(node.ID > 0) {
+ if(node.ID == 0) {
+ page = html`
+ ${children.length > 0 ? html`
${children}
` : html``}
+ `
+ } else {
let padlock = ''
if(node.CryptoKeyID > 0)
padlock = html`
`
@@ -209,7 +213,8 @@ export class NodeUI extends Component {
}//}}}
saveNode() {//{{{
let content = this.nodeContent.current.contentDiv.current.value
- this.node.value.save(content, ()=>this.props.app.nodeModified.value = false)
+ this.node.value.setContent(content)
+ this.node.value.save(()=>this.props.app.nodeModified.value = false)
}//}}}
renameNode() {//{{{
let name = prompt("New name")
@@ -299,7 +304,7 @@ class NodeContent extends Component {
textarea.parentNode.dataset.replicatedValue = textarea.value
}//}}}
unlock() {//{{{
- let pass = prompt("Password")
+ let pass = prompt(`Password for "${this.props.model.description}"`)
if(!pass)
return
@@ -397,21 +402,21 @@ export class Node {
})
.catch(this.app.responseError)
}//}}}
- async save(content, callback) {//{{{
- let update_content = content
- /*
- * XXX - fix encrypting when saving
- if(this.CryptoKeyID != 0)
- update_content = await this.#encrypt(content)
- */
+ async save(callback) {//{{{
+ try {
+ await this.#encrypt()
- this.app.request('/node/update', {
- NodeID: this.ID,
- Content: update_content,
- CryptoKeyID: this.CryptoKeyID,
- })
- .then(callback)
- .catch(this.app.responseError)
+ let req = {
+ NodeID: this.ID,
+ Content: this._content,
+ CryptoKeyID: this.CryptoKeyID,
+ }
+ this.app.request('/node/update', req)
+ .then(callback)
+ .catch(this.app.responseError)
+ } catch (err) {
+ this.app.responseError(err)
+ }
}//}}}
rename(name, callback) {//{{{
this.app.request('/node/rename', {
@@ -454,30 +459,26 @@ export class Node {
})
}//}}}
content() {//{{{
- if(this.CryptoKeyID != 0 && !this._decrypted) {
+ if(this.CryptoKeyID != 0 && !this._decrypted)
this.#decrypt()
- }
return this._content
}//}}}
-
- async encrypt(obj_key) {//{{{
- if(obj_key.ID != this.CryptoKeyID)
- throw('Invalid key')
-
- let crypto = new Crypto(obj_key.key)
- this._decrypted = false
-
- let counter = await obj_key.counter()
-
- this.content = sjcl.codec.base64.fromBits(
- crypto.encrypt(
- sjcl.codec.utf8String.toBits(this.content),
- counter,
- false,
- )
- )
+ setContent(new_content) {//{{{
+ this._content = new_content
+ if(this.CryptoKeyID == 0)
+ // Logic behind plaintext not being decrypted is that
+ // only encrypted values can be in a decrypted state.
+ this._decrypted = false
+ else
+ this._decrypted = true
+ }//}}}
+ async setCryptoKey(new_key) {//{{{
+ return this.#encrypt(true, new_key)
}//}}}
#decrypt() {//{{{
+ if(this.CryptoKeyID == 0 || this._decrypted)
+ return
+
let obj_key = this.app.nodeUI.current.getKey(this.CryptoKeyID)
if(obj_key === null || obj_key.ID != this.CryptoKeyID)
throw('Invalid key')
@@ -485,7 +486,7 @@ export class Node {
// Ask user to unlock key first
var pass = null
while(pass || obj_key.status() == 'locked') {
- pass = prompt("Password")
+ pass = prompt(`Password for "${obj_key.description}"`)
if(!pass)
throw new Error(`Key "${obj_key.description}" is locked`)
@@ -506,10 +507,25 @@ export class Node {
crypto.decrypt(this._content)
)
}//}}}
- /*
- async #encrypt(content) {//{{{
- let obj_key = this.app.nodeUI.current.getKey(this.CryptoKeyID)
- if(obj_key === null || obj_key.ID != this.CryptoKeyID)
+ async #encrypt(change_key = false, new_key = null) {//{{{
+ // Nothing to do if not changing key and already encrypted.
+ if(!change_key && this.CryptoKeyID != 0 && !this._decrypted)
+ return this._content
+
+ let content = this.content()
+
+ // Changing key to no encryption or already at no encryption -
+ // set to not decrypted (only encrypted values can be
+ // decrypted) and return plain value.
+ if((change_key && new_key === null) || (!change_key && this.CryptoKeyID == 0)) {
+ this._decrypted = false
+ this.CryptoKeyID = 0
+ return content
+ }
+
+ let key_id = change_key ? new_key.ID : this.CryptoKeyID
+ let obj_key = this.app.nodeUI.current.getKey(key_id)
+ if(obj_key === null || obj_key.ID != key_id)
throw('Invalid key')
if(obj_key.status() == 'locked')
@@ -518,9 +534,11 @@ export class Node {
let crypto = new Crypto(obj_key.key)
let content_bits = sjcl.codec.utf8String.toBits(content)
let counter = await this.app.nodeUI.current.keyCounter()
- return crypto.encrypt(content_bits, counter, true)
+ this.CryptoKeyID = obj_key.ID
+ this._content = crypto.encrypt(content_bits, counter, true)
+ this._decrypted = false
+ return this._content
}//}}}
- */
}
class Menu extends Component {
@@ -681,38 +699,26 @@ class NodeProperties extends Component {
`
}//}}}
- save() {//{{{
+ async save() {//{{{
let nodeui = this.props.nodeui
let node = nodeui.node.value
// Find the actual key object used for encryption
- let encrypt_key = nodeui.getKey(this.selected_key_id)
- let decrypt_key = nodeui.getKey(node.CryptoKeyID)
+ let new_key = nodeui.getKey(this.selected_key_id)
+ let current_key = nodeui.getKey(node.CryptoKeyID)
- if(decrypt_key && decrypt_key.status() == 'locked') {
+ if(current_key && current_key.status() == 'locked') {
alert("Decryption key is locked and can not be used.")
return
}
- if(encrypt_key && encrypt_key.status() == 'locked') {
+ if(new_key && new_key.status() == 'locked') {
alert("Key is locked and can not be used.")
return
}
- // Currently not encrypted - encrypt with new key.
- let crypto = new Crypto(selected_key.key)
- if(node.CryptoKeyID == 0) {
- let encrypted = crypto.encrypt(
- sjcl.codec.utf8String.toBits(node.Content()),
- 1n,
- )
- console.log(encrypted)
- }
-
- /*
- crypto.encrypt(
- )
- */
+ await node.setCryptoKey(new_key)
+ node.save(()=>this.props.nodeui.showPage('node'))
}//}}}
}