Integrate filepicker secure iframe in the code2 app

This commit is contained in:
yflory 2017-09-01 15:17:14 +02:00
parent 89b7b644f3
commit f12f4bb925
11 changed files with 311 additions and 151 deletions

View File

@ -24,6 +24,15 @@
padding:0; padding:0;
overflow:hidden; overflow:hidden;
} }
#sbox-filePicker-iframe {
position: fixed;
top:0; left:0;
bottom:0; right:0;
width:100%;
height: 100%;
border: 0;
}
</style> </style>
</head> </head>
<body> <body>

View File

@ -228,9 +228,9 @@ define([
APP.previewTo = window.setTimeout(function () { APP.previewTo = window.setTimeout(function () {
$codeMirror.removeClass('transition'); $codeMirror.removeClass('transition');
}, 500); }, 500);
/*if (mediaTagModes.indexOf(mode) !== -1) { if (mediaTagModes.indexOf(mode) !== -1) {
APP.$mediaTagButton.show(); APP.$mediaTagButton.show();
} else { APP.$mediaTagButton.hide(); }*/// TODO } else { APP.$mediaTagButton.hide(); }
if (mode === "markdown") { if (mode === "markdown") {
APP.$previewButton.show(); APP.$previewButton.show();
@ -360,26 +360,20 @@ define([
else { else {
CodeMirror.configureTheme(); CodeMirror.configureTheme();
} }
// TODO
return;
var fileDialogCfg = { var fileDialogCfg = {
$body: $iframe.find('body'), onSelect: function (data) {
onSelect: function (href) { var mt = '<media-tag src="' + data.src + '" data-crypto-key="cryptpad:' + data.key + '"></media-tag>';
var parsed = Cryptpad.parsePadUrl(href);
var hexFileName = Cryptpad.base64ToHex(parsed.hashData.channel);
var src = '/blob/' + hexFileName.slice(0,2) + '/' + hexFileName;
var mt = '<media-tag src="' + src + '" data-crypto-key="cryptpad:' + parsed.hashData.key + '"></media-tag>';
editor.replaceSelection(mt); editor.replaceSelection(mt);
}, }
data: APP
}; };
common.initFilePicker(common, fileDialogCfg);
APP.$mediaTagButton = $('<button>', { APP.$mediaTagButton = $('<button>', {
title: Messages.filePickerButton, title: Messages.filePickerButton,
'class': 'rightside-button fa fa-picture-o', 'class': 'rightside-button fa fa-picture-o',
style: 'font-size: 17px' style: 'font-size: 17px'
}).click(function () { }).click(function () {
Cryptpad.createFileDialog(fileDialogCfg); common.openFilePicker(common);
}).appendTo($rightside); }).appendTo($rightside);
}; };

View File

@ -751,7 +751,6 @@ define([
list[id] = data; list[id] = data;
} }
}); });
console.log(list);
cb (null, list); cb (null, list);
}; };
@ -1464,16 +1463,24 @@ define([
'id': cfg.id 'id': cfg.id
}); });
} }
var hide = function () {
if (cfg.onClose) { return void cfg.onClose(); }
$blockContainer.hide();
};
$blockContainer.html('').appendTo($body); $blockContainer.html('').appendTo($body);
var $block = $('<div>', {'class': 'cp-modal'}).appendTo($blockContainer); var $block = $('<div>', {'class': 'cp-modal'}).appendTo($blockContainer);
$('<span>', { $('<span>', {
'class': 'cp-modal-close fa fa-times', 'class': 'cp-modal-close fa fa-times',
'title': Messages.filePicker_close 'title': Messages.filePicker_close
}).click(function () { }).click(hide).appendTo($block);
$blockContainer.hide(); $body.click(hide);
}).appendTo($block); $block.click(function (e) {
e.stopPropagation();
});
$body.keydown(function (e) { $body.keydown(function (e) {
if (e.which === 27) { $blockContainer.hide(); } if (e.which === 27) {
hide();
}
}); });
return $blockContainer; return $blockContainer;
}; };

View File

@ -109,8 +109,9 @@ define([
window.addEventListener('message', function (msg) { window.addEventListener('message', function (msg) {
var data = JSON.parse(msg.data); var data = JSON.parse(msg.data);
if (ow !== msg.source) { if (ow !== msg.source) {
console.log("DROP Message from unexpected source"); return;
console.log(msg); //console.log("DROP Message from unexpected source");
//console.log(msg);
} else if (!otherWindow) { } else if (!otherWindow) {
otherWindow = ow; otherWindow = ow;
ow.postMessage(JSON.stringify({ txid: data.txid }), '*'); ow.postMessage(JSON.stringify({ txid: data.txid }), '*');

View File

@ -261,18 +261,40 @@ define([
return $userAdmin; return $userAdmin;
}; };
// createFileDialog can only be used in filepicker due to access rights restrictions
UI.createFileDialog = function (cfg) { UI.createFileDialog = function (cfg) {
var common = cfg.common; var common = cfg.common;
var sframeChan = common.getSframeChannel();
var updateContainer;
var hideFileDialog = function () {
sframeChan.event('EV_FILE_PICKER_CLOSE');
};
// Create modal
var $blockContainer = Cryptpad.createModal({ var $blockContainer = Cryptpad.createModal({
id: 'fileDialog', id: 'fileDialog',
$body: cfg.$body $body: cfg.$body,
}); onClose: hideFileDialog
}).show();
// Set the fixed content
var $block = $blockContainer.find('.cp-modal'); var $block = $blockContainer.find('.cp-modal');
var $description = $('<p>').text(Messages.filePicker_description); var $description = $('<p>').text(Messages.filePicker_description);
$block.append($description); $block.append($description);
var $filter = $('<p>', {'class': 'cp-modal-form'}).appendTo($block); var $filter = $('<p>', {'class': 'cp-modal-form'}).appendTo($block);
var to;
$('<input>', {
type: 'text',
'class': 'filter',
'placeholder': Messages.filePicker_filter
}).appendTo($filter).on('keypress', function () {
if (to) { window.clearTimeout(to); }
to = window.setTimeout(updateContainer, 300);
});
$filter.append(common.createButton('upload', false, cfg.data, function () {
hideFileDialog();
}));
var $container = $('<span>', {'class': 'fileContainer'}).appendTo($block); var $container = $('<span>', {'class': 'fileContainer'}).appendTo($block);
var updateContainer = function () { // Update the files list when needed
updateContainer = function () {
$container.html(''); $container.html('');
var filter = $filter.find('.filter').val().trim(); var filter = $filter.find('.filter').val().trim();
var todo = function (err, list) { var todo = function (err, list) {
@ -291,28 +313,27 @@ define([
$span.append(name); $span.append(name);
$span.click(function () { $span.click(function () {
if (typeof cfg.onSelect === "function") { cfg.onSelect(data.href); } if (typeof cfg.onSelect === "function") { cfg.onSelect(data.href); }
$blockContainer.hide(); hideFileDialog();
}); });
}); });
}; };
common.getFilesList(todo); common.getFilesList(todo);
}; };
var to;
$('<input>', {
type: 'text',
'class': 'filter',
'placeholder': Messages.filePicker_filter
}).appendTo($filter).on('keypress', function () {
if (to) { window.clearTimeout(to); }
to = window.setTimeout(updateContainer, 300);
});
//$filter.append(' '+Messages.or+' ');
/*var data = {FM: cfg.data.FM};
$filter.append(common.createButton('upload', false, data, function () {
$blockContainer.hide();
}));*/
updateContainer(); updateContainer();
$blockContainer.show(); sframeChan.on('EV_FILE_PICKER_REFRESH', updateContainer);
};
UI.initFilePicker = function (common, cfg) {
var onSelect = cfg.onSelect || $.noop;
var sframeChan = common.getSframeChannel();
sframeChan.on("EV_FILE_PICKED", function (data) {
onSelect(data);
});
};
UI.openFilePicker = function (common) {
var sframeChan = common.getSframeChannel();
sframeChan.event("EV_FILE_PICKER_OPEN");
}; };
return UI; return UI;

View File

@ -14,6 +14,7 @@ define([
var Crypto; var Crypto;
var Cryptget; var Cryptget;
var sframeChan; var sframeChan;
var FilePicker;
nThen(function (waitFor) { nThen(function (waitFor) {
// Load #2, the loading screen is up so grab whatever you need... // Load #2, the loading screen is up so grab whatever you need...
@ -23,11 +24,14 @@ define([
'/bower_components/chainpad-crypto/crypto.js', '/bower_components/chainpad-crypto/crypto.js',
'/common/cryptget.js', '/common/cryptget.js',
'/common/sframe-channel.js', '/common/sframe-channel.js',
], waitFor(function (_CpNfOuter, _Cryptpad, _Crypto, _Cryptget, SFrameChannel) { '/filepicker/main.js',
], waitFor(function (_CpNfOuter, _Cryptpad, _Crypto, _Cryptget, SFrameChannel,
_FilePicker) {
CpNfOuter = _CpNfOuter; CpNfOuter = _CpNfOuter;
Cryptpad = _Cryptpad; Cryptpad = _Cryptpad;
Crypto = _Crypto; Crypto = _Crypto;
Cryptget = _Cryptget; Cryptget = _Cryptget;
FilePicker = _FilePicker;
SFrameChannel.create($('#sbox-iframe')[0].contentWindow, waitFor(function (sfc) { SFrameChannel.create($('#sbox-iframe')[0].contentWindow, waitFor(function (sfc) {
sframeChan = sfc; sframeChan = sfc;
})); }));
@ -215,7 +219,7 @@ define([
}); });
sframeChan.on('Q_UPLOAD_FILE', function (data, cb) { var onFileUpload = function (sframeChan, data, cb) {
var sendEvent = function (data) { var sendEvent = function (data) {
sframeChan.event("EV_FILE_UPLOAD_STATE", data); sframeChan.event("EV_FILE_UPLOAD_STATE", data);
}; };
@ -245,6 +249,31 @@ define([
data.blob = Crypto.Nacl.util.decodeBase64(data.blob); data.blob = Crypto.Nacl.util.decodeBase64(data.blob);
Cryptpad.uploadFileSecure(data, data.noStore, Cryptpad, updateProgress, onComplete, onError, onPending); Cryptpad.uploadFileSecure(data, data.noStore, Cryptpad, updateProgress, onComplete, onError, onPending);
cb(); cb();
};
sframeChan.on('Q_UPLOAD_FILE', function (data, cb) {
onFileUpload(sframeChan, data, cb);
});
var FP = {};
var initFilePicker = function () {
var config = {};
config.onFilePicked = function (data) {
sframeChan.event('EV_FILE_PICKED', data);
};
config.onClose = function () {
FP.$iframe.hide();
};
config.onFileUpload = onFileUpload;
if (!FP.$iframe) {
FP.$iframe = $('<iframe>', {id: 'sbox-filePicker-iframe'}).appendTo($('body'));
FP.picker = FilePicker.create(config);
} else {
FP.$iframe.show();
FP.picker.refresh();
}
};
sframeChan.on('EV_FILE_PICKER_OPEN', function () {
initFilePicker();
}); });
CpNfOuter.start({ CpNfOuter.start({

View File

@ -56,6 +56,8 @@ define([
funcs.createUserAdminMenu = UI.createUserAdminMenu; funcs.createUserAdminMenu = UI.createUserAdminMenu;
funcs.displayAvatar = UI.displayAvatar; funcs.displayAvatar = UI.displayAvatar;
funcs.createFileDialog = UI.createFileDialog; funcs.createFileDialog = UI.createFileDialog;
funcs.initFilePicker = UI.initFilePicker;
funcs.openFilePicker = UI.openFilePicker;
// History // History
funcs.getHistory = function (config) { return History.create(funcs, config); }; funcs.getHistory = function (config) { return History.create(funcs, config); };
@ -200,6 +202,30 @@ define([
}, {accept: data ? data.accept : undefined})); }, {accept: data ? data.accept : undefined}));
} }
break; break;
case 'upload':
button = $('<button>', {
'class': 'btn btn-primary new',
title: Messages.uploadButtonTitle,
}).append($('<span>', {'class':'fa fa-upload'})).append(' '+Messages.uploadButton);
if (!data.FM) { return; }
var $input = $('<input>', {
'type': 'file',
'style': 'display: none;'
}).on('change', function (e) {
var file = e.target.files[0];
var ev = {
target: data.target
};
if (data.filter && !data.filter(file)) {
Cryptpad.log('TODO: invalid avatar (type or size)');
return;
}
data.FM.handleFile(file, ev);
if (callback) { callback(); }
});
if (data.accept) { $input.attr('accept', data.accept); }
button.click(function () { $input.click(); });
break;
case 'template': case 'template':
if (!AppConfig.enableTemplates) { return; } if (!AppConfig.enableTemplates) { return; }
button = $('<button>', { button = $('<button>', {

View File

@ -89,6 +89,14 @@ define({
'Q_GET_PAD_ATTRIBUTE': true, 'Q_GET_PAD_ATTRIBUTE': true,
'Q_SET_PAD_ATTRIBUTE': true, 'Q_SET_PAD_ATTRIBUTE': true,
// Open/close the File picker (sent from the iframe to the outside)
'EV_FILE_PICKER_OPEN': true,
'EV_FILE_PICKER_CLOSE': true,
'EV_FILE_PICKER_REFRESH': true,
// File selected in the file picker: sent from the filepicker iframe to the outside
// and then send to the inner iframe
'EV_FILE_PICKED': true,
// Get all the files from the drive to display them in a file picker secure app // Get all the files from the drive to display them in a file picker secure app
'Q_GET_FILES_LIST': true, 'Q_GET_FILES_LIST': true,

View File

@ -1,11 +1,25 @@
<!DOCTYPE html> <!DOCTYPE html>
<html style="height: 100%;"> <html style="height: 100%; background: transparent;">
<head> <head>
<meta content="text/html; charset=utf-8" http-equiv="content-type"/> <meta content="text/html; charset=utf-8" http-equiv="content-type"/>
<script async data-bootload="/filepicker/inner.js" data-main="/common/sframe-boot.js?ver=1.1" src="/bower_components/requirejs/require.js?ver=2.3.5"></script> <script async data-bootload="/filepicker/inner.js" data-main="/common/sframe-boot.js?ver=1.1" src="/bower_components/requirejs/require.js?ver=2.3.5"></script>
<style> .loading-hidden { display: none; } </style> <style>
.loading-hidden { display: none; }
body #loading {
position: absolute;
top: 15vh;
bottom: 15vh;
left: 10vw;
right: 10vw;
z-index: 200000;
overflow: hidden;
}
body #loading .loadingContainer {
margin-top: 35vh;
}
</style>
</head> </head>
<body> <body style="background: transparent;">
</body> </body>
</html> </html>

View File

@ -34,9 +34,35 @@ define([
var andThen = function (common) { var andThen = function (common) {
//var metadataMgr = common.getMetadataMgr(); //var metadataMgr = common.getMetadataMgr();
var $body = $('body'); var $body = $('body');
var sframeChan = common.getSframeChannel();
var onFilePicked = function (data) {
var parsed = Cryptpad.parsePadUrl(data.url);
var hexFileName = Cryptpad.base64ToHex(parsed.hashData.channel);
var src = '/blob/' + hexFileName.slice(0,2) + '/' + hexFileName;
sframeChan.event("EV_FILE_PICKED", {
src: src,
key: parsed.hashData.key
});
};
var fmConfig = {
body: $('body'),
noHandlers: true,
onUploaded: function (ev, data) {
onFilePicked(data);
}
};
APP.FM = common.createFileManager(fmConfig);
var cfg = { var cfg = {
$body: $body, $body: $body,
common: common common: common,
onSelect: function (url) {
onFilePicked({url: url});
},
data: {
FM: APP.FM
}
}; };
common.createFileDialog(cfg); common.createFileDialog(cfg);
Cryptpad.removeLoadingScreen(); Cryptpad.removeLoadingScreen();

View File

@ -7,7 +7,9 @@ define([
], function (nThen, ApiConfig, $, RequireConfig) { ], function (nThen, ApiConfig, $, RequireConfig) {
var requireConfig = RequireConfig(); var requireConfig = RequireConfig();
var create = function (config) {
// Loaded in load #2 // Loaded in load #2
var sframeChan;
nThen(function (waitFor) { nThen(function (waitFor) {
$(waitFor()); $(waitFor());
}).nThen(function (waitFor) { }).nThen(function (waitFor) {
@ -18,7 +20,7 @@ define([
}; };
window.rc = requireConfig; window.rc = requireConfig;
window.apiconf = ApiConfig; window.apiconf = ApiConfig;
$('#sbox-iframe').attr('src', $('#sbox-filePicker-iframe').attr('src',
ApiConfig.httpSafeOrigin + '/filepicker/inner.html?' + requireConfig.urlArgs + ApiConfig.httpSafeOrigin + '/filepicker/inner.html?' + requireConfig.urlArgs +
'#' + encodeURIComponent(JSON.stringify(req))); '#' + encodeURIComponent(JSON.stringify(req)));
@ -38,7 +40,6 @@ define([
var Cryptpad; var Cryptpad;
var Crypto; var Crypto;
var Cryptget; var Cryptget;
var sframeChan;
nThen(function (waitFor) { nThen(function (waitFor) {
// Load #2, the loading screen is up so grab whatever you need... // Load #2, the loading screen is up so grab whatever you need...
@ -51,7 +52,7 @@ define([
Cryptpad = _Cryptpad; Cryptpad = _Cryptpad;
Crypto = _Crypto; Crypto = _Crypto;
Cryptget = _Cryptget; Cryptget = _Cryptget;
SFrameChannel.create($('#sbox-iframe')[0].contentWindow, waitFor(function (sfc) { SFrameChannel.create($('#sbox-filePicker-iframe')[0].contentWindow, waitFor(function (sfc) {
sframeChan = sfc; sframeChan = sfc;
})); }));
Cryptpad.ready(waitFor()); Cryptpad.ready(waitFor());
@ -117,6 +118,7 @@ define([
}); });
sframeChan.on('Q_GET_FILES_LIST', function (data, cb) { sframeChan.on('Q_GET_FILES_LIST', function (data, cb) {
console.error("TODO: make sure Q_GET_FILES_LIST is only available from filepicker");
Cryptpad.getSecureFilesList(function (err, data) { Cryptpad.getSecureFilesList(function (err, data) {
cb({ cb({
error: err, error: err,
@ -124,6 +126,29 @@ define([
}); });
}); });
}); });
sframeChan.on('EV_FILE_PICKER_CLOSE', function () {
console.log('close file picker;..');
config.onClose();
});
sframeChan.on('EV_FILE_PICKED', function (data) {
config.onFilePicked(data);
console.log(data);
});
sframeChan.on('Q_UPLOAD_FILE', function (data, cb) {
config.onFileUpload(sframeChan, data, cb);
}); });
}); });
}); });
var refresh = function () {
if (!sframeChan) { return; }
sframeChan.event('EV_FILE_PICKER_REFRESH');
};
return {
refresh: refresh
};
};
return {
create: create
};
});