diff --git a/www/common/common-hash.js b/www/common/common-hash.js index 98330367f..4ed1193e3 100644 --- a/www/common/common-hash.js +++ b/www/common/common-hash.js @@ -231,10 +231,14 @@ Version 1 } if (['invite'].indexOf(type) !== -1) { parsed.type = 'invite'; - if (hashArr[1] && hashArr[1] === '1') { - parsed.version = 1; - parsed.channel = hashArr[2]; - parsed.pubkey = hashArr[3].replace(/-/g, '/'); + if (hashArr[1] && hashArr[1] === '2') { + parsed.version = 2; + parsed.app = hashArr[2]; + parsed.mode = hashArr[3]; + parsed.key = hashArr[4]; + + options = hashArr.slice(5); + parsed.password = options.indexOf('p') !== -1; return parsed; } return parsed; diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index 648448248..2fa3fb308 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -14,11 +14,14 @@ define([ '/customize/application_config.js', '/customize/pages.js', '/bower_components/nthen/index.js', + + '/bower_components/scrypt-async/scrypt-async.js', 'css!/customize/fonts/cptools/style.css', '/bower_components/croppie/croppie.min.js', 'css!/bower_components/croppie/croppie.css', ], function ($, Config, Util, Hash, Language, UI, Constants, Feedback, h, MediaTag, Clipboard, Messages, AppConfig, Pages, NThen) { + var Scrypt = window.scrypt; var UIElements = {}; // Configure MediaTags to use our local viewer @@ -1557,6 +1560,8 @@ define([ var team = privateData.teams[config.teamId]; if (!team) { return void UI.warn(Messages.error); } + var origin = privateData.origin; + var module = config.module || common.makeUniversal('team'); // Invite contacts @@ -1629,52 +1634,91 @@ define([ buttons: contactsButtons, }); - var linkName, linkPassword, linkMessage; - var linkError; + var linkName, linkPassword, linkMessage, linkError, linkSpinText; + var linkForm, linkSpin, linkResult; // Invite from link var linkContent = h('div.cp-share-modal', [ h('p', 'XXX Invite link description...'), // XXX linkError = h('div.alert.alert-danger', {style : 'display: none;'}), - linkName = h('input', { - placeholder: 'name...' // XXX - }), - h('br'), - linkPassword = UI.passwordInput({ - id: 'cp-teams-invite-password', - placeholder: 'password...' // XXX - }), - h('br'), - linkMessage = h('textarea', { - placeholder: 'note...' - }) + linkForm = h('div.cp-teams-invite-form', [ + linkName = h('input', { + placeholder: 'name...' // XXX + }), + h('br'), + linkPassword = UI.passwordInput({ + id: 'cp-teams-invite-password', + placeholder: 'password...' // XXX + }), + h('br'), + linkMessage = h('textarea', { + placeholder: 'note...' + }) + ]), + linkSpin = h('div', { + style: 'display: none;' + }, [ + h('i.fa.fa-spinner.fa-spin'), + linkSpinText = h('span', 'Scrypt...') // XXX + ]), + linkResult = h('div', { + style: 'display: none;' + }, h('textarea', { + readonly: 'readonly' + })) ]); + var $linkContent = $(linkContent); + var href; var process = function () { + var $nav = $linkContent.closest('.alertify').find('nav'); $(linkError).text('').hide(); var name = $(linkName).val(); var pw = $(linkPassword).val(); var msg = $(linkMessage).val(); + var hash = Hash.createRandomHash('invite', pw); + var hashData = Hash.parseTypeHash('invite', hash); + href = origin + '/teams/#' + hash; + console.log(hashData); if (!name || !name.trim()) { $(linkError).text('empty name...').show(); // XXX return true; } - var bytes; + var bytes64; NThen(function (waitFor) { + $(linkForm).hide(); + $(linkSpin).show(); + $nav.find('button.cp-teams-invite-create').prop('disabled', 'disabled'); + setTimeout(waitFor(), 150); + }).nThen(function (waitFor) { // Scrypt - waitFor()(); // jshint - bytes = bytes; + Scrypt(hashData.key, + (pw || '') + (AppConfig.loginSalt || ''), // salt + 8, // memoryCost (n) + 1024, // block size parameter (r) + 192, // dkLen + 200, // interruptStep + waitFor(function (_bytes) { + bytes64 = _bytes; + }), + 'base64'); // format, could be 'base64' }).nThen(function (waitFor) { + $(linkSpinText).text('Add invite link to team'); // XXX module.execCommand('CREATE_INVITE_LINK', { name: name, password: pw, message: msg, - // send scrypt result + bytes64: bytes64, + href: href, teamId: config.teamId, }, waitFor(function (obj) { if (obj && obj.error) { waitFor.abort(); + $(linkSpin).hide(); return void $(linkError).text('ERROR '+obj.error).show(); // XXX } // Display result here + $(linkSpin).hide(); + $(linkResult).show().find('textarea').text(href); + $nav.find('button.cp-teams-invite-copy').prop('disabled', ''); })); }); return true; @@ -1685,17 +1729,27 @@ define([ onClick: function () {}, keys: [27] }, { - className: 'primary', + className: 'primary cp-teams-invite-create', name: 'CREATE LINK', // XXX onClick: function () { return process(); }, keys: [13] + }, { + className: 'primary cp-teams-invite-copy', + name: 'COPY LINK', // XXX + onClick: function () { + if (!href) { return; } + var success = Clipboard.copy(href); + if (success) { UI.log(Messages.shareSuccess); } + }, + keys: [] }]; var frameLink = UI.dialog.customModal(linkContent, { buttons: linkButtons, }); + $(frameLink).find('.cp-teams-invite-copy').prop('disabled', 'disabled'); // Create modal var tabs = [{ diff --git a/www/common/outer/team.js b/www/common/outer/team.js index e48e5d313..3bb86cd4b 100644 --- a/www/common/outer/team.js +++ b/www/common/outer/team.js @@ -1262,13 +1262,20 @@ define([ var createInviteLink = function (ctx, data, cId, cb) { var team = ctx.teams[data.teamId]; team = team; - // var roster = team.roster; - // var name = data.name; - // var password = data.password; - // var msg = data.message; + /* + var roster = team.roster; + var name = data.name; + var password = data.password; + var msg = data.message; + var href = data.href; + var bytes64 = data.bytes64; + */ + return void cb(); + /* cb({ error: 'NOT_IMPLEMENTED' }); + */ }; Team.init = function (cfg, waitFor, emit) {