Mercurial > xmpp-account-manager
changeset 3:5aa1bf7154b0
Add a simple PEP node viewer and editor.
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Sat, 22 Dec 2018 02:23:38 +0100 |
parents | db033e5eabcb |
children | 5e97e1808a35 |
files | avatar.js client.js index.xhtml pep.js util.js |
diffstat | 5 files changed, 147 insertions(+), 21 deletions(-) [+] |
line wrap: on
line diff
--- a/avatar.js +++ b/avatar.js @@ -171,20 +171,7 @@ function initAvatar(connection) { } avatar_access.addEventListener('change', function (evt) { - const iq = $iq({type: 'set'}) - .c('pubsub', {xmlns: 'http://jabber.org/protocol/pubsub#owner'}) - .c('configure', {node: 'urn:xmpp:avatar:metadata'}) - .c('x', {xmlns: 'jabber:x:data', type: 'submit'}) - .c('field', {'var': 'FORM_TYPE', type: 'hidden'}) - .c('value') - .t('http://jabber.org/protocol/pubsub#node_config') - .up() - .up() - .c('field', {'var': 'pubsub#access_model'}) - .c('value') - .t(evt.target.value) - .up() - .up() + const iq = configurePEPField('urn:xmpp:avatar:metadata', 'pubsub#access_model', evt.target.value); connection.sendIQ(iq, onAvatarConfigured, onAvatarConfigureError.bind(null, 'PubSub configuration failed.')); });
--- a/client.js +++ b/client.js @@ -95,6 +95,7 @@ document.addEventListener('DOMContentLoa function onConnected() { connected_div.hidden = false; + initPEP(connection); initNickname(connection); initAvatar(connection); }
--- a/index.xhtml +++ b/index.xhtml @@ -62,6 +62,13 @@ <option value="presence">Only your contacts</option> </select></label> </p> +<h2>PEP</h2> +<table> +<thead> +<tr><th>PEP node</th><th>Title</th><th>Description</th><th>Type</th><th>⚠️ Delete</th></tr> +</thead> +<tbody id="pep-table"/> +</table> <h2>Dangerous zone</h2> <p> <button disabled="">Change my password</button> @@ -98,6 +105,7 @@ <script src="client.js"/> <script src="nickname.js"/> <script src="avatar.js"/> +<script src="pep.js"/> </body> </html>
new file mode 100644 --- /dev/null +++ b/pep.js @@ -0,0 +1,107 @@ +'use strict'; + +function initPEP(connection) { + const pep_table = document.getElementById('pep-table'); + + const iq = $iq({type: 'get'}) + .c('query', {xmlns: NS.disco_items}); + connection.sendIQ(iq, onDiscoItems, onDiscoItemsError.bind(null, 'disco#items query failed.')); + + function onDiscoItems(result_iq) + { + const items = parseXPath(result_iq, './disco_items:query/disco_items:item', XPathResult.ORDERED_NODE_ITERATOR_TYPE); + while (true) { + const item = items.iterateNext(); + if (!item) + break; + const node = item.getAttributeNS(null, 'node'); + const tr = document.createElementNS('http://www.w3.org/1999/xhtml', 'tr'); + const td = document.createElementNS('http://www.w3.org/1999/xhtml', 'td'); + td.textContent = node; + tr.appendChild(td); + pep_table.appendChild(tr); + const iq = $iq({type: 'get'}) + .c('query', {xmlns: NS.disco_info, node: node}); + connection.sendIQ(iq, onDiscoInfo.bind(tr), onDiscoInfoError.bind(tr, 'disco#items query failed.')); + } + } + + function onDiscoItemsError(string) + { + console.log('Failed to retrieve the list of PEP nodes: ' + string); + } + + function onDiscoInfo(result_iq) + { + const tr = this; + const node = parseXPath(result_iq, './disco_info:query').getAttributeNS(null, 'node'); + const fields = parseXPath(result_iq, './disco_info:query/dataforms:x/dataforms:field', XPathResult.ORDERED_NODE_ITERATOR_TYPE); + const parsed_fields = {}; + while (true) { + const field = fields.iterateNext(); + if (!field) + break; + const type = field.getAttributeNS(null, 'type'); + if (type == 'hidden') + continue; + const var_ = field.getAttributeNS(null, 'var'); + const value = parseXPath(field, './dataforms:value'); + parsed_fields[var_] = value ? value.textContent : ''; + } + for (let i of ['pubsub#title', 'pubsub#description', 'pubsub#type']) { + const td = document.createElementNS('http://www.w3.org/1999/xhtml', 'td'); + const input = document.createElementNS('http://www.w3.org/1999/xhtml', 'input'); + input.value = parsed_fields[i]; + input.onblur = function (evt) { + const iq = configurePEPField(node, i, evt.target.value); + connection.sendIQ(iq, onPEPConfigured, onPEPConfigureError.bind(null, 'PubSub configuration failed.')); + }; + td.appendChild(input); + tr.appendChild(td); + } + const td = document.createElementNS('http://www.w3.org/1999/xhtml', 'td'); + const button = document.createElementNS('http://www.w3.org/1999/xhtml', 'button'); + button.textContent = 'Delete this node'; + button.onclick = function (evt) { + const iq = $iq({type: 'set'}) + .c('pubsub', {xmlns: NS.pubsub_owner}) + .c('delete', {node: node}); + connection.sendIQ(iq, onNodeDeleted.bind(node), onNodeDeletionError.bind(node, 'PEP node deletion failed.')); + }; + td.appendChild(button); + tr.appendChild(td); + } + + function onDiscoInfoError(string) + { + console.log('Failed to retrieve PEP node info: ' + string); + } + + function onPEPConfigured(result_iq) + { + console.log('PEP node successfully configured.'); + } + + function onPEPConfigureError(string) + { + console.log('Configuration of PEP node failed: ' + string); + } + + function onNodeDeleted(result_iq) + { + const node = this; + for (let child of pep_table.children) { + if (node != child.firstChild.textContent) + continue + child.remove(); + break; + } + console.log('Node “' + node + '” successfully deleted.'); + } + + function onNodeDeletionError(string) + { + const node = this; + console.log('Deletion of PEP node “' + node + '” failed: ' + string); + } +}
--- a/util.js +++ b/util.js @@ -1,11 +1,17 @@ +const NS = { + xrd: 'http://docs.oasis-open.org/ns/xri/xrd-1.0', + disco_items: 'http://jabber.org/protocol/disco#items', + disco_info: 'http://jabber.org/protocol/disco#info', + dataforms: 'jabber:x:data', + pubsub: 'http://jabber.org/protocol/pubsub', + pubsub_owner: 'http://jabber.org/protocol/pubsub#owner', + avatar_metadata: 'urn:xmpp:avatar:metadata', + avatar_data: 'urn:xmpp:avatar:data', + nickname: 'http://jabber.org/protocol/nick', +}; + function nsResolver(prefix) { - return { - xrd: 'http://docs.oasis-open.org/ns/xri/xrd-1.0', - pubsub: 'http://jabber.org/protocol/pubsub', - avatar_metadata: 'urn:xmpp:avatar:metadata', - avatar_data: 'urn:xmpp:avatar:data', - nickname: 'http://jabber.org/protocol/nick', - }[prefix] || null; + return NS[prefix] || null; } function parseXPath(elem, xpath, result) @@ -17,3 +23,20 @@ function parseXPath(elem, xpath, result) return value.singleNodeValue; return value; } + +function configurePEPField(node, key, value, cb, err_cb) { + return $iq({type: 'set'}) + .c('pubsub', {xmlns: 'http://jabber.org/protocol/pubsub#owner'}) + .c('configure', {node: node}) + .c('x', {xmlns: 'jabber:x:data', type: 'submit'}) + .c('field', {'var': 'FORM_TYPE', type: 'hidden'}) + .c('value') + .t('http://jabber.org/protocol/pubsub#node_config') + .up() + .up() + .c('field', {'var': key}) + .c('value') + .t(value) + .up() + .up(); +}