Merge branch 'staging' of github.com:xwiki-labs/cryptpad into keywords
This commit is contained in:
commit
d676a5e7db
15 changed files with 338 additions and 226 deletions
|
@ -325,4 +325,12 @@ module.exports = {
|
||||||
// '/etc/apache2/ssl/my_public_cert.crt',
|
// '/etc/apache2/ssl/my_public_cert.crt',
|
||||||
// '/etc/apache2/ssl/my_certificate_authorities_cert_chain.ca'
|
// '/etc/apache2/ssl/my_certificate_authorities_cert_chain.ca'
|
||||||
//],
|
//],
|
||||||
|
|
||||||
|
/* You can get a repl for debugging the server if you want it.
|
||||||
|
* to enable this, specify the debugReplName and then you can
|
||||||
|
* connect to it with `nc -U /tmp/repl/<your name>.sock`
|
||||||
|
* If you run multiple cryptpad servers, you need to use different
|
||||||
|
* repl names.
|
||||||
|
*/
|
||||||
|
//debugReplName: "cryptpad"
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,10 +6,17 @@ define([
|
||||||
'/common/outer/network-config.js',
|
'/common/outer/network-config.js',
|
||||||
'/customize/credential.js',
|
'/customize/credential.js',
|
||||||
'/bower_components/chainpad/chainpad.dist.js',
|
'/bower_components/chainpad/chainpad.dist.js',
|
||||||
|
'/common/common-realtime.js',
|
||||||
|
'/common/common-constants.js',
|
||||||
|
'/common/common-interface.js',
|
||||||
|
'/common/common-feedback.js',
|
||||||
|
'/common/outer/local-store.js',
|
||||||
|
'/customize/messages.js',
|
||||||
|
|
||||||
'/bower_components/tweetnacl/nacl-fast.min.js',
|
'/bower_components/tweetnacl/nacl-fast.min.js',
|
||||||
'/bower_components/scrypt-async/scrypt-async.min.js', // better load speed
|
'/bower_components/scrypt-async/scrypt-async.min.js', // better load speed
|
||||||
], function ($, Listmap, Crypto, Util, NetConfig, Cred, ChainPad) {
|
], function ($, Listmap, Crypto, Util, NetConfig, Cred, ChainPad, Realtime, Constants, UI,
|
||||||
|
Feedback, LocalStore, Messages) {
|
||||||
var Exports = {
|
var Exports = {
|
||||||
Cred: Cred,
|
Cred: Cred,
|
||||||
};
|
};
|
||||||
|
@ -142,5 +149,127 @@ define([
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Exports.loginOrRegisterUI = function (uname, passwd, isRegister, shouldImport, testing, test) {
|
||||||
|
var hashing = true;
|
||||||
|
|
||||||
|
var proceed = function (result) {
|
||||||
|
var proxy = result.proxy;
|
||||||
|
proxy.edPublic = result.edPublic;
|
||||||
|
proxy.edPrivate = result.edPrivate;
|
||||||
|
proxy.curvePublic = result.curvePublic;
|
||||||
|
proxy.curvePrivate = result.curvePrivate;
|
||||||
|
|
||||||
|
if (isRegister) {
|
||||||
|
Feedback.send('REGISTRATION', true);
|
||||||
|
} else {
|
||||||
|
Feedback.send('LOGIN', true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Realtime.whenRealtimeSyncs(result.realtime, function () {
|
||||||
|
try {
|
||||||
|
LocalStore.login(result.userHash, result.userName, function () {
|
||||||
|
hashing = false;
|
||||||
|
if (test && typeof test === "function" && test()) { console.log('testing');
|
||||||
|
return; }
|
||||||
|
if (shouldImport) {
|
||||||
|
sessionStorage.migrateAnonDrive = 1;
|
||||||
|
}
|
||||||
|
if (sessionStorage.redirectTo) {
|
||||||
|
var h = sessionStorage.redirectTo;
|
||||||
|
var parser = document.createElement('a');
|
||||||
|
parser.href = h;
|
||||||
|
if (parser.origin === window.location.origin) {
|
||||||
|
delete sessionStorage.redirectTo;
|
||||||
|
window.location.href = h;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
window.location.href = '/drive/';
|
||||||
|
});
|
||||||
|
} catch (e) { console.error(e); }
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// setTimeout 100ms to remove the keyboard on mobile devices before the loading screen
|
||||||
|
// pops up
|
||||||
|
window.setTimeout(function () {
|
||||||
|
UI.addLoadingScreen({
|
||||||
|
loadingText: Messages.login_hashing,
|
||||||
|
hideTips: true,
|
||||||
|
});
|
||||||
|
// We need a setTimeout(cb, 0) otherwise the loading screen is only displayed
|
||||||
|
// after hashing the password
|
||||||
|
window.setTimeout(function () {
|
||||||
|
Exports.loginOrRegister(uname, passwd, isRegister, function (err, result) {
|
||||||
|
var proxy;
|
||||||
|
if (result) { proxy = result.proxy; }
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
switch (err) {
|
||||||
|
case 'NO_SUCH_USER':
|
||||||
|
UI.removeLoadingScreen(function () {
|
||||||
|
UI.alert(Messages.login_noSuchUser, function () {
|
||||||
|
hashing = false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'INVAL_USER':
|
||||||
|
UI.removeLoadingScreen(function () {
|
||||||
|
UI.alert(Messages.login_invalUser, function () {
|
||||||
|
hashing = false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'INVAL_PASS':
|
||||||
|
UI.removeLoadingScreen(function () {
|
||||||
|
UI.alert(Messages.login_invalPass, function () {
|
||||||
|
hashing = false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'PASS_TOO_SHORT':
|
||||||
|
UI.removeLoadingScreen(function () {
|
||||||
|
var warning = Messages._getKey('register_passwordTooShort', [
|
||||||
|
Cred.MINIMUM_PASSWORD_LENGTH
|
||||||
|
]);
|
||||||
|
UI.alert(warning, function () {
|
||||||
|
hashing = false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'ALREADY_REGISTERED':
|
||||||
|
// logMeIn should reset registering = false
|
||||||
|
UI.removeLoadingScreen(function () {
|
||||||
|
UI.confirm(Messages.register_alreadyRegistered, function (yes) {
|
||||||
|
if (!yes) { return; }
|
||||||
|
proxy.login_name = uname;
|
||||||
|
|
||||||
|
if (!proxy[Constants.displayNameKey]) {
|
||||||
|
proxy[Constants.displayNameKey] = uname;
|
||||||
|
}
|
||||||
|
LocalStore.eraseTempSessionValues();
|
||||||
|
proceed(result);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
default: // UNHANDLED ERROR
|
||||||
|
hashing = false;
|
||||||
|
UI.errorLoadingScreen(Messages.login_unhandledError);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (testing) { return void proceed(result); }
|
||||||
|
|
||||||
|
proxy.login_name = uname;
|
||||||
|
proxy[Constants.displayNameKey] = uname;
|
||||||
|
sessionStorage.createReadme = 1;
|
||||||
|
|
||||||
|
proceed(result);
|
||||||
|
});
|
||||||
|
}, 0);
|
||||||
|
}, 200);
|
||||||
|
};
|
||||||
|
|
||||||
return Exports;
|
return Exports;
|
||||||
});
|
});
|
||||||
|
|
|
@ -33,16 +33,26 @@
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
h2, p {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
h2 {
|
h2 {
|
||||||
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
margin-bottom: 20px;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
.cp-creation-help {
|
.cp-creation-help {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.cp-creation-help-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
p {
|
||||||
|
padding: 0 20px;
|
||||||
|
flex-grow: 0;
|
||||||
|
flex-shrink: 0;
|
||||||
|
flex-basis: 50%;
|
||||||
|
text-align: justify;
|
||||||
|
}
|
||||||
|
}
|
||||||
@media screen and (max-width: 500px) {
|
@media screen and (max-width: 500px) {
|
||||||
width: ~"calc(100% - 30px)";
|
width: ~"calc(100% - 30px)";
|
||||||
}
|
}
|
||||||
|
@ -50,7 +60,7 @@
|
||||||
h2 .cp-creation-help {
|
h2 .cp-creation-help {
|
||||||
display: inline;
|
display: inline;
|
||||||
}
|
}
|
||||||
p {
|
.cp-creation-help-container {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
0
customize.dist/translations/messages.el.js
Executable file → Normal file
0
customize.dist/translations/messages.el.js
Executable file → Normal file
|
@ -866,16 +866,16 @@ define(function () {
|
||||||
out.creation_ownedTitle = "Type of pad";
|
out.creation_ownedTitle = "Type of pad";
|
||||||
out.creation_ownedTrue = "Owned pad";
|
out.creation_ownedTrue = "Owned pad";
|
||||||
out.creation_ownedFalse = "Open pad";
|
out.creation_ownedFalse = "Open pad";
|
||||||
out.creation_owned1 = "An <b>owned</b> pad is a pad that you can delete from the server whenever you want. Once it is deleted, no one else can access it, even if it is stored in their CryptDrive.";
|
out.creation_owned1 = "An <b>owned</b> pad can be deleted from the server whenever the owner wants. Deleting an owned pad removes it from other users' CryptDrives.";
|
||||||
out.creation_owned2 = "An <b>open</b> pad doesn't have any owner and thus, it can't be deleted from the server unless it has reached its expiration time.";
|
out.creation_owned2 = "An <b>open</b> pad doesn't have any owner and thus, it can't be deleted from the server unless it has reached its expiration time.";
|
||||||
out.creation_expireTitle = "Life time";
|
out.creation_expireTitle = "Life time";
|
||||||
out.creation_expireTrue = "Add a life time";
|
out.creation_expireTrue = "Add a life time";
|
||||||
out.creation_expireFalse = "Unlimited";
|
out.creation_expireFalse = "Unlimited";
|
||||||
out.creation_expireHours = "Hours";
|
out.creation_expireHours = "Hour(s)";
|
||||||
out.creation_expireDays = "Days";
|
out.creation_expireDays = "Day(s)";
|
||||||
out.creation_expireMonths = "Months";
|
out.creation_expireMonths = "Month(s)";
|
||||||
out.creation_expire1 = "By default, a pad stored by a registered user will never be removed from the server, unless it is requested by its owner.";
|
out.creation_expire1 = "An <b>unlimited</b> pad will not be removed from the server until its owner deletes it.";
|
||||||
out.creation_expire2 = "If you prefer, you can set a life time to make sure the pad will be permanently deleted from the server and unavailable after the specified date.";
|
out.creation_expire2 = "An <b>expiring</b> pad has a set lifetime, after which it will be automatically removed from the server and other users' CryptDrives.";
|
||||||
out.creation_createTitle = "Create a pad";
|
out.creation_createTitle = "Create a pad";
|
||||||
out.creation_createFromTemplate = "From template";
|
out.creation_createFromTemplate = "From template";
|
||||||
out.creation_createFromScratch = "From scratch";
|
out.creation_createFromScratch = "From scratch";
|
||||||
|
|
93
expire-channels.js
Normal file
93
expire-channels.js
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
var Fs = require("fs");
|
||||||
|
var Path = require("path");
|
||||||
|
|
||||||
|
var nThen = require("nthen");
|
||||||
|
var config = require("./config");
|
||||||
|
|
||||||
|
var root = Path.resolve(config.taskPath || './tasks');
|
||||||
|
|
||||||
|
var dirs;
|
||||||
|
var nt;
|
||||||
|
|
||||||
|
var queue = function (f) {
|
||||||
|
nt = nt.nThen(f);
|
||||||
|
};
|
||||||
|
|
||||||
|
var tryParse = function (s) {
|
||||||
|
try { return JSON.parse(s); }
|
||||||
|
catch (e) { return null; }
|
||||||
|
};
|
||||||
|
|
||||||
|
var CURRENT = +new Date();
|
||||||
|
|
||||||
|
var handleTask = function (str, path, cb) {
|
||||||
|
var task = tryParse(str);
|
||||||
|
if (!Array.isArray(task)) {
|
||||||
|
console.error('invalid task: not array');
|
||||||
|
return cb();
|
||||||
|
}
|
||||||
|
if (task.length < 2) {
|
||||||
|
console.error('invalid task: too small');
|
||||||
|
return cb();
|
||||||
|
}
|
||||||
|
|
||||||
|
var time = task[0];
|
||||||
|
var command = task[1];
|
||||||
|
var args = task.slice(2);
|
||||||
|
|
||||||
|
if (time > CURRENT) {
|
||||||
|
// not time for this task yet
|
||||||
|
console.log('not yet time');
|
||||||
|
return cb();
|
||||||
|
}
|
||||||
|
|
||||||
|
nThen(function () {
|
||||||
|
switch (command) {
|
||||||
|
case 'EXPIRE':
|
||||||
|
console.log("expiring: %s", args[0]);
|
||||||
|
// TODO actually remove the file...
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.log("unknown command", command);
|
||||||
|
}
|
||||||
|
}).nThen(function () {
|
||||||
|
// remove the file...
|
||||||
|
Fs.unlink(path, function (err) {
|
||||||
|
if (err) { console.error(err); }
|
||||||
|
cb();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
nt = nThen(function (w) {
|
||||||
|
Fs.readdir(root, w(function (e, list) {
|
||||||
|
if (e) { throw e; }
|
||||||
|
dirs = list;
|
||||||
|
}));
|
||||||
|
}).nThen(function () {
|
||||||
|
dirs.forEach(function (dir) {
|
||||||
|
queue(function (w) {
|
||||||
|
console.log('recursing into %s', dir);
|
||||||
|
Fs.readdir(Path.join(root, dir), w(function (e, list) {
|
||||||
|
list.forEach(function (fn) {
|
||||||
|
queue(function (w) {
|
||||||
|
var filePath = Path.join(root, dir, fn);
|
||||||
|
var cb = w();
|
||||||
|
|
||||||
|
console.log("processing file at %s", filePath);
|
||||||
|
Fs.readFile(filePath, 'utf8', function (e, str) {
|
||||||
|
if (e) {
|
||||||
|
console.error(e);
|
||||||
|
return void cb();
|
||||||
|
}
|
||||||
|
|
||||||
|
handleTask(str, filePath, cb);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
"express": "~4.10.1",
|
"express": "~4.10.1",
|
||||||
"nthen": "~0.1.0",
|
"nthen": "~0.1.0",
|
||||||
"pull-stream": "^3.6.1",
|
"pull-stream": "^3.6.1",
|
||||||
|
"replify": "^1.2.0",
|
||||||
"saferphore": "0.0.1",
|
"saferphore": "0.0.1",
|
||||||
"stream-to-pull-stream": "^1.7.2",
|
"stream-to-pull-stream": "^1.7.2",
|
||||||
"tweetnacl": "~0.12.2",
|
"tweetnacl": "~0.12.2",
|
||||||
|
|
25
rpc.js
25
rpc.js
|
@ -428,8 +428,7 @@ var getHash = function (Env, publicKey, cb) {
|
||||||
|
|
||||||
// The limits object contains storage limits for all the publicKey that have paid
|
// The limits object contains storage limits for all the publicKey that have paid
|
||||||
// To each key is associated an object containing the 'limit' value and a 'note' explaining that limit
|
// To each key is associated an object containing the 'limit' value and a 'note' explaining that limit
|
||||||
var limits = {};
|
var updateLimits = function (Env, config, publicKey, cb /*:(?string, ?any[])=>void*/) {
|
||||||
var updateLimits = function (config, publicKey, cb /*:(?string, ?any[])=>void*/) {
|
|
||||||
if (config.adminEmail === false) {
|
if (config.adminEmail === false) {
|
||||||
if (config.allowSubscriptions === false) { return; }
|
if (config.allowSubscriptions === false) { return; }
|
||||||
throw new Error("allowSubscriptions must be false if adminEmail is false");
|
throw new Error("allowSubscriptions must be false if adminEmail is false");
|
||||||
|
@ -494,15 +493,15 @@ var updateLimits = function (config, publicKey, cb /*:(?string, ?any[])=>void*/)
|
||||||
response.on('end', function () {
|
response.on('end', function () {
|
||||||
try {
|
try {
|
||||||
var json = JSON.parse(str);
|
var json = JSON.parse(str);
|
||||||
limits = json;
|
Env.limits = json;
|
||||||
Object.keys(customLimits).forEach(function (k) {
|
Object.keys(customLimits).forEach(function (k) {
|
||||||
if (!isLimit(customLimits[k])) { return; }
|
if (!isLimit(customLimits[k])) { return; }
|
||||||
limits[k] = customLimits[k];
|
Env.limits[k] = customLimits[k];
|
||||||
});
|
});
|
||||||
|
|
||||||
var l;
|
var l;
|
||||||
if (userId) {
|
if (userId) {
|
||||||
var limit = limits[userId];
|
var limit = Env.limits[userId];
|
||||||
l = limit && typeof limit.limit === "number" ?
|
l = limit && typeof limit.limit === "number" ?
|
||||||
[limit.limit, limit.plan, limit.note] : [defaultLimit, '', ''];
|
[limit.limit, limit.plan, limit.note] : [defaultLimit, '', ''];
|
||||||
}
|
}
|
||||||
|
@ -523,7 +522,7 @@ var updateLimits = function (config, publicKey, cb /*:(?string, ?any[])=>void*/)
|
||||||
|
|
||||||
var getLimit = function (Env, publicKey, cb) {
|
var getLimit = function (Env, publicKey, cb) {
|
||||||
var unescapedKey = unescapeKeyCharacters(publicKey);
|
var unescapedKey = unescapeKeyCharacters(publicKey);
|
||||||
var limit = limits[unescapedKey];
|
var limit = Env.limits[unescapedKey];
|
||||||
var defaultLimit = typeof(Env.defaultStorageLimit) === 'number'?
|
var defaultLimit = typeof(Env.defaultStorageLimit) === 'number'?
|
||||||
Env.defaultStorageLimit: DEFAULT_LIMIT;
|
Env.defaultStorageLimit: DEFAULT_LIMIT;
|
||||||
|
|
||||||
|
@ -1097,7 +1096,11 @@ type NetfluxWebsocketSrvContext_t = {
|
||||||
)=>void
|
)=>void
|
||||||
};
|
};
|
||||||
*/
|
*/
|
||||||
RPC.create = function (config /*:Config_t*/, cb /*:(?Error, ?Function)=>void*/) {
|
RPC.create = function (
|
||||||
|
config /*:Config_t*/,
|
||||||
|
debuggable /*:<T>(string, T)=>T*/,
|
||||||
|
cb /*:(?Error, ?Function)=>void*/
|
||||||
|
) {
|
||||||
// load pin-store...
|
// load pin-store...
|
||||||
console.log('loading rpc module...');
|
console.log('loading rpc module...');
|
||||||
|
|
||||||
|
@ -1115,8 +1118,10 @@ RPC.create = function (config /*:Config_t*/, cb /*:(?Error, ?Function)=>void*/)
|
||||||
msgStore: (undefined /*:any*/),
|
msgStore: (undefined /*:any*/),
|
||||||
pinStore: (undefined /*:any*/),
|
pinStore: (undefined /*:any*/),
|
||||||
pinnedPads: {},
|
pinnedPads: {},
|
||||||
evPinnedPadsReady: mkEvent(true)
|
evPinnedPadsReady: mkEvent(true),
|
||||||
|
limits: {}
|
||||||
};
|
};
|
||||||
|
debuggable('rpc_env', Env);
|
||||||
|
|
||||||
var Sessions = Env.Sessions;
|
var Sessions = Env.Sessions;
|
||||||
var paths = Env.paths;
|
var paths = Env.paths;
|
||||||
|
@ -1306,7 +1311,7 @@ RPC.create = function (config /*:Config_t*/, cb /*:(?Error, ?Function)=>void*/)
|
||||||
Respond(e, size);
|
Respond(e, size);
|
||||||
});
|
});
|
||||||
case 'UPDATE_LIMITS':
|
case 'UPDATE_LIMITS':
|
||||||
return void updateLimits(config, safeKey, function (e, limit) {
|
return void updateLimits(Env, config, safeKey, function (e, limit) {
|
||||||
if (e) {
|
if (e) {
|
||||||
WARN(e, limit);
|
WARN(e, limit);
|
||||||
return void Respond(e);
|
return void Respond(e);
|
||||||
|
@ -1418,7 +1423,7 @@ RPC.create = function (config /*:Config_t*/, cb /*:(?Error, ?Function)=>void*/)
|
||||||
};
|
};
|
||||||
|
|
||||||
var updateLimitDaily = function () {
|
var updateLimitDaily = function () {
|
||||||
updateLimits(config, undefined, function (e) {
|
updateLimits(Env, config, undefined, function (e) {
|
||||||
if (e) {
|
if (e) {
|
||||||
WARN('limitUpdate', e);
|
WARN('limitUpdate', e);
|
||||||
}
|
}
|
||||||
|
|
23
server.js
23
server.js
|
@ -21,10 +21,25 @@ try {
|
||||||
var websocketPort = config.websocketPort || config.httpPort;
|
var websocketPort = config.websocketPort || config.httpPort;
|
||||||
var useSecureWebsockets = config.useSecureWebsockets || false;
|
var useSecureWebsockets = config.useSecureWebsockets || false;
|
||||||
|
|
||||||
|
// This is stuff which will become available to replify
|
||||||
|
const debuggableStore = new WeakMap();
|
||||||
|
const debuggable = function (name, x) {
|
||||||
|
if (name in debuggableStore) {
|
||||||
|
try { throw new Error(); } catch (e) {
|
||||||
|
console.error('cannot add ' + name + ' more than once [' + e.stack + ']');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
debuggableStore[name] = x;
|
||||||
|
}
|
||||||
|
return x;
|
||||||
|
};
|
||||||
|
debuggable('global', global);
|
||||||
|
debuggable('config', config);
|
||||||
|
|
||||||
// support multiple storage back ends
|
// support multiple storage back ends
|
||||||
var Storage = require(config.storage||'./storage/file');
|
var Storage = require(config.storage||'./storage/file');
|
||||||
|
|
||||||
var app = Express();
|
var app = debuggable('app', Express());
|
||||||
|
|
||||||
var httpsOpts;
|
var httpsOpts;
|
||||||
|
|
||||||
|
@ -204,7 +219,6 @@ var rpc;
|
||||||
var nt = nThen(function (w) {
|
var nt = nThen(function (w) {
|
||||||
if (!config.enableTaskScheduling) { return; }
|
if (!config.enableTaskScheduling) { return; }
|
||||||
var Tasks = require("./storage/tasks");
|
var Tasks = require("./storage/tasks");
|
||||||
|
|
||||||
console.log("loading task scheduler");
|
console.log("loading task scheduler");
|
||||||
Tasks.create(config, w(function (e, tasks) {
|
Tasks.create(config, w(function (e, tasks) {
|
||||||
config.tasks = tasks;
|
config.tasks = tasks;
|
||||||
|
@ -214,7 +228,7 @@ var nt = nThen(function (w) {
|
||||||
if (typeof(config.rpc) !== 'string') { return; }
|
if (typeof(config.rpc) !== 'string') { return; }
|
||||||
// load pin store...
|
// load pin store...
|
||||||
var Rpc = require(config.rpc);
|
var Rpc = require(config.rpc);
|
||||||
Rpc.create(config, w(function (e, _rpc) {
|
Rpc.create(config, debuggable, w(function (e, _rpc) {
|
||||||
if (e) {
|
if (e) {
|
||||||
w.abort();
|
w.abort();
|
||||||
throw e;
|
throw e;
|
||||||
|
@ -233,3 +247,6 @@ var nt = nThen(function (w) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (config.debugReplName) {
|
||||||
|
require('replify')({ name: config.debugReplName, app: debuggableStore });
|
||||||
|
}
|
|
@ -553,6 +553,7 @@ define([
|
||||||
var $loading, $container;
|
var $loading, $container;
|
||||||
if ($('#' + LOADING).length) {
|
if ($('#' + LOADING).length) {
|
||||||
$loading = $('#' + LOADING); //.show();
|
$loading = $('#' + LOADING); //.show();
|
||||||
|
$loading.css('display', '');
|
||||||
$loading.removeClass('cp-loading-hidden');
|
$loading.removeClass('cp-loading-hidden');
|
||||||
if (loadingText) {
|
if (loadingText) {
|
||||||
$('#' + LOADING).find('p').text(loadingText);
|
$('#' + LOADING).find('p').text(loadingText);
|
||||||
|
|
|
@ -1687,7 +1687,10 @@ define([
|
||||||
Messages.creation_ownedTitle,
|
Messages.creation_ownedTitle,
|
||||||
createHelper(Messages.creation_owned1 + '\n' + Messages.creation_owned2)
|
createHelper(Messages.creation_owned1 + '\n' + Messages.creation_owned2)
|
||||||
]),
|
]),
|
||||||
setHTML(h('p'), Messages.creation_owned1 + '<br>' + Messages.creation_owned2),
|
h('div.cp-creation-help-container', [
|
||||||
|
setHTML(h('p'), Messages.creation_owned1),
|
||||||
|
setHTML(h('p'), Messages.creation_owned2)
|
||||||
|
]),
|
||||||
h('input#cp-creation-owned-true.cp-creation-owned-value', {
|
h('input#cp-creation-owned-true.cp-creation-owned-value', {
|
||||||
type: 'radio',
|
type: 'radio',
|
||||||
name: 'cp-creation-owned',
|
name: 'cp-creation-owned',
|
||||||
|
@ -1715,7 +1718,10 @@ define([
|
||||||
Messages.creation_expireTitle,
|
Messages.creation_expireTitle,
|
||||||
createHelper(Messages.creation_expire1, Messages.creation_expire2)
|
createHelper(Messages.creation_expire1, Messages.creation_expire2)
|
||||||
]),
|
]),
|
||||||
setHTML(h('p'), Messages.creation_expire1 + '<br>' + Messages.creation_expire2),
|
h('div.cp-creation-help-container', [
|
||||||
|
setHTML(h('p'), Messages.creation_expire1),
|
||||||
|
setHTML(h('p'), Messages.creation_expire2)
|
||||||
|
]),
|
||||||
h('input#cp-creation-expire-false.cp-creation-expire-value', {
|
h('input#cp-creation-expire-false.cp-creation-expire-value', {
|
||||||
type: 'radio',
|
type: 'radio',
|
||||||
name: 'cp-creation-expire',
|
name: 'cp-creation-expire',
|
||||||
|
|
|
@ -13,7 +13,6 @@ define([
|
||||||
$(function () {
|
$(function () {
|
||||||
var $main = $('#mainBlock');
|
var $main = $('#mainBlock');
|
||||||
var $checkImport = $('#import-recent');
|
var $checkImport = $('#import-recent');
|
||||||
var Messages = Cryptpad.Messages;
|
|
||||||
|
|
||||||
// main block is hidden in case javascript is disabled
|
// main block is hidden in case javascript is disabled
|
||||||
$main.removeClass('hidden');
|
$main.removeClass('hidden');
|
||||||
|
@ -61,90 +60,15 @@ define([
|
||||||
|
|
||||||
hashing = true;
|
hashing = true;
|
||||||
var shouldImport = $checkImport[0].checked;
|
var shouldImport = $checkImport[0].checked;
|
||||||
|
var uname = $uname.val();
|
||||||
// setTimeout 100ms to remove the keyboard on mobile devices before the loading screen pops up
|
var passwd = $passwd.val();
|
||||||
window.setTimeout(function () {
|
Login.loginOrRegisterUI(uname, passwd, false, shouldImport, Test.testing, function () {
|
||||||
UI.addLoadingScreen({
|
if (test) {
|
||||||
loadingText: Messages.login_hashing,
|
localStorage.clear();
|
||||||
hideTips: true,
|
test.pass();
|
||||||
});
|
return true;
|
||||||
// We need a setTimeout(cb, 0) otherwise the loading screen is only displayed after hashing the password
|
}
|
||||||
window.setTimeout(function () {
|
});
|
||||||
loginReady(function () {
|
|
||||||
var uname = $uname.val();
|
|
||||||
var passwd = $passwd.val();
|
|
||||||
Login.loginOrRegister(uname, passwd, false, function (err, result) {
|
|
||||||
if (!err) {
|
|
||||||
var proxy = result.proxy;
|
|
||||||
|
|
||||||
// successful validation and user already exists
|
|
||||||
// set user hash in localStorage and redirect to drive
|
|
||||||
if (!proxy.login_name) {
|
|
||||||
result.proxy.login_name = result.userName;
|
|
||||||
}
|
|
||||||
|
|
||||||
proxy.edPrivate = result.edPrivate;
|
|
||||||
proxy.edPublic = result.edPublic;
|
|
||||||
|
|
||||||
proxy.curvePrivate = result.curvePrivate;
|
|
||||||
proxy.curvePublic = result.curvePublic;
|
|
||||||
|
|
||||||
Feedback.send('LOGIN', true);
|
|
||||||
Realtime.whenRealtimeSyncs(result.realtime, function() {
|
|
||||||
LocalStore.login(result.userHash, result.userName, function () {
|
|
||||||
hashing = false;
|
|
||||||
if (test) {
|
|
||||||
localStorage.clear();
|
|
||||||
test.pass();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (shouldImport) {
|
|
||||||
sessionStorage.migrateAnonDrive = 1;
|
|
||||||
}
|
|
||||||
if (sessionStorage.redirectTo) {
|
|
||||||
var h = sessionStorage.redirectTo;
|
|
||||||
var parser = document.createElement('a');
|
|
||||||
parser.href = h;
|
|
||||||
if (parser.origin === window.location.origin) {
|
|
||||||
delete sessionStorage.redirectTo;
|
|
||||||
window.location.href = h;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
window.location.href = '/drive/';
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
switch (err) {
|
|
||||||
case 'NO_SUCH_USER':
|
|
||||||
UI.removeLoadingScreen(function () {
|
|
||||||
UI.alert(Messages.login_noSuchUser, function () {
|
|
||||||
hashing = false;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 'INVAL_USER':
|
|
||||||
UI.removeLoadingScreen(function () {
|
|
||||||
UI.alert(Messages.login_invalUser, function () {
|
|
||||||
hashing = false;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 'INVAL_PASS':
|
|
||||||
UI.removeLoadingScreen(function () {
|
|
||||||
UI.alert(Messages.login_invalPass, function () {
|
|
||||||
hashing = false;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
default: // UNHANDLED ERROR
|
|
||||||
UI.errorLoadingScreen(Messages.login_unhandledError);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}, 0);
|
|
||||||
}, 100);
|
|
||||||
});
|
});
|
||||||
$('#register').on('click', function () {
|
$('#register').on('click', function () {
|
||||||
if (sessionStorage) {
|
if (sessionStorage) {
|
||||||
|
|
|
@ -55,39 +55,6 @@ define([
|
||||||
|
|
||||||
var registering = false;
|
var registering = false;
|
||||||
var test;
|
var test;
|
||||||
var logMeIn = function (result) {
|
|
||||||
LocalStore.setUserHash(result.userHash);
|
|
||||||
|
|
||||||
var proxy = result.proxy;
|
|
||||||
proxy.edPublic = result.edPublic;
|
|
||||||
proxy.edPrivate = result.edPrivate;
|
|
||||||
proxy.curvePublic = result.curvePublic;
|
|
||||||
proxy.curvePrivate = result.curvePrivate;
|
|
||||||
|
|
||||||
Feedback.send('REGISTRATION', true);
|
|
||||||
|
|
||||||
Realtime.whenRealtimeSyncs(result.realtime, function () {
|
|
||||||
LocalStore.login(result.userHash, result.userName, function () {
|
|
||||||
registering = false;
|
|
||||||
if (test) {
|
|
||||||
localStorage.clear();
|
|
||||||
test.pass();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (sessionStorage.redirectTo) {
|
|
||||||
var h = sessionStorage.redirectTo;
|
|
||||||
var parser = document.createElement('a');
|
|
||||||
parser.href = h;
|
|
||||||
if (parser.origin === window.location.origin) {
|
|
||||||
delete sessionStorage.redirectTo;
|
|
||||||
window.location.href = h;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
window.location.href = '/drive/';
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
$register.click(function () {
|
$register.click(function () {
|
||||||
if (registering) {
|
if (registering) {
|
||||||
|
@ -125,89 +92,14 @@ define([
|
||||||
function (yes) {
|
function (yes) {
|
||||||
if (!yes) { return; }
|
if (!yes) { return; }
|
||||||
|
|
||||||
|
Login.loginOrRegisterUI(uname, passwd, true, shouldImport, Test.testing, function () {
|
||||||
|
if (test) {
|
||||||
|
localStorage.clear();
|
||||||
|
test.pass();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
registering = true;
|
registering = true;
|
||||||
// setTimeout 100ms to remove the keyboard on mobile devices before the loading screen pops up
|
|
||||||
window.setTimeout(function () {
|
|
||||||
UI.addLoadingScreen({
|
|
||||||
loadingText: Messages.login_hashing,
|
|
||||||
hideTips: true,
|
|
||||||
});
|
|
||||||
// We need a setTimeout(cb, 0) otherwise the loading screen is only displayed after hashing the password
|
|
||||||
window.setTimeout(function () {
|
|
||||||
Login.loginOrRegister(uname, passwd, true, function (err, result) {
|
|
||||||
var proxy;
|
|
||||||
if (result) { proxy = result.proxy; }
|
|
||||||
|
|
||||||
if (err) {
|
|
||||||
switch (err) {
|
|
||||||
case 'NO_SUCH_USER':
|
|
||||||
UI.removeLoadingScreen(function () {
|
|
||||||
UI.alert(Messages.login_noSuchUser, function () {
|
|
||||||
registering = false;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 'INVAL_USER':
|
|
||||||
UI.removeLoadingScreen(function () {
|
|
||||||
UI.alert(Messages.login_invalUser, function () {
|
|
||||||
registering = false;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 'INVAL_PASS':
|
|
||||||
UI.removeLoadingScreen(function () {
|
|
||||||
UI.alert(Messages.login_invalPass, function () {
|
|
||||||
registering = false;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 'PASS_TOO_SHORT':
|
|
||||||
UI.removeLoadingScreen(function () {
|
|
||||||
var warning = Messages._getKey('register_passwordTooShort', [
|
|
||||||
Cred.MINIMUM_PASSWORD_LENGTH
|
|
||||||
]);
|
|
||||||
UI.alert(warning, function () {
|
|
||||||
registering = false;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 'ALREADY_REGISTERED':
|
|
||||||
// logMeIn should reset registering = false
|
|
||||||
UI.removeLoadingScreen(function () {
|
|
||||||
UI.confirm(Messages.register_alreadyRegistered, function (yes) {
|
|
||||||
if (!yes) { return; }
|
|
||||||
proxy.login_name = uname;
|
|
||||||
|
|
||||||
if (!proxy[Constants.displayNameKey]) {
|
|
||||||
proxy[Constants.displayNameKey] = uname;
|
|
||||||
}
|
|
||||||
LocalStore.eraseTempSessionValues();
|
|
||||||
logMeIn(result);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
default: // UNHANDLED ERROR
|
|
||||||
registering = false;
|
|
||||||
UI.errorLoadingScreen(Messages.login_unhandledError);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Test.testing) { return void logMeIn(result); }
|
|
||||||
|
|
||||||
LocalStore.eraseTempSessionValues();
|
|
||||||
if (shouldImport) {
|
|
||||||
sessionStorage.migrateAnonDrive = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
proxy.login_name = uname;
|
|
||||||
proxy[Constants.displayNameKey] = uname;
|
|
||||||
sessionStorage.createReadme = 1;
|
|
||||||
|
|
||||||
logMeIn(result);
|
|
||||||
});
|
|
||||||
}, 0);
|
|
||||||
}, 200);
|
|
||||||
}, {
|
}, {
|
||||||
ok: Messages.register_writtenPassword,
|
ok: Messages.register_writtenPassword,
|
||||||
cancel: Messages.register_cancel,
|
cancel: Messages.register_cancel,
|
||||||
|
|
|
@ -70,6 +70,10 @@ define([
|
||||||
|
|
||||||
var makeCheckbox = function (id, cb) {
|
var makeCheckbox = function (id, cb) {
|
||||||
var entry = APP.lm.proxy.data[id];
|
var entry = APP.lm.proxy.data[id];
|
||||||
|
if (!entry || typeof(entry) !== 'object') {
|
||||||
|
return void console.log('entry undefined');
|
||||||
|
}
|
||||||
|
|
||||||
var checked = entry.state === 1 ?
|
var checked = entry.state === 1 ?
|
||||||
'cp-app-todo-task-checkbox-checked fa-check-square-o':
|
'cp-app-todo-task-checkbox-checked fa-check-square-o':
|
||||||
'cp-app-todo-task-checkbox-unchecked fa-square-o';
|
'cp-app-todo-task-checkbox-unchecked fa-square-o';
|
||||||
|
@ -92,6 +96,7 @@ define([
|
||||||
};
|
};
|
||||||
|
|
||||||
var addTaskUI = function (el, animate) {
|
var addTaskUI = function (el, animate) {
|
||||||
|
if (!el) { return; }
|
||||||
var $taskDiv = $('<div>', {
|
var $taskDiv = $('<div>', {
|
||||||
'class': 'cp-app-todo-task'
|
'class': 'cp-app-todo-task'
|
||||||
});
|
});
|
||||||
|
@ -108,6 +113,9 @@ define([
|
||||||
.appendTo($taskDiv);
|
.appendTo($taskDiv);
|
||||||
|
|
||||||
var entry = APP.lm.proxy.data[el];
|
var entry = APP.lm.proxy.data[el];
|
||||||
|
if (!entry || typeof(entry) !== 'object') {
|
||||||
|
return void console.log('entry undefined');
|
||||||
|
}
|
||||||
|
|
||||||
if (entry.state) {
|
if (entry.state) {
|
||||||
$taskDiv.addClass('cp-app-todo-task-complete');
|
$taskDiv.addClass('cp-app-todo-task-complete');
|
||||||
|
|
|
@ -39,6 +39,24 @@ define([
|
||||||
if (typeof(proxy.data) !== 'object') { proxy.data = {}; }
|
if (typeof(proxy.data) !== 'object') { proxy.data = {}; }
|
||||||
if (!Array.isArray(proxy.order)) { proxy.order = []; }
|
if (!Array.isArray(proxy.order)) { proxy.order = []; }
|
||||||
if (typeof(proxy.type) !== 'string') { proxy.type = 'todo'; }
|
if (typeof(proxy.type) !== 'string') { proxy.type = 'todo'; }
|
||||||
|
|
||||||
|
// if a key exists in order, but there is no data for it...
|
||||||
|
// remove that key
|
||||||
|
var i = proxy.order.length - 1;
|
||||||
|
for (;i >= 0; i--) {
|
||||||
|
if (typeof(proxy.data[proxy.order[i]]) === 'undefined') {
|
||||||
|
console.log('removing todo entry with no data at [%s]', i);
|
||||||
|
proxy.order.splice(i, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if you have data, but it's not in the order array...
|
||||||
|
// add it to the order array...
|
||||||
|
Object.keys(proxy.data).forEach(function (key) {
|
||||||
|
if (proxy.order.indexOf(key) > -1) { return; }
|
||||||
|
console.log("restoring entry with missing key");
|
||||||
|
proxy.order.unshift(key);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/* add (id, obj) push id to order, add object to data */
|
/* add (id, obj) push id to order, add object to data */
|
||||||
|
|
Loading…
Reference in a new issue