mirror of https://github.com/xwiki-labs/cryptpad
Merge branch 'soon' into staging
This commit is contained in:
commit
9effb40f9f
|
@ -221,21 +221,21 @@ define([
|
||||||
// If they are trying to register,
|
// If they are trying to register,
|
||||||
// and the proxy is empty, then there is no 'legacy user' either
|
// and the proxy is empty, then there is no 'legacy user' either
|
||||||
// so we should just shut down this session and disconnect.
|
// so we should just shut down this session and disconnect.
|
||||||
rt.network.disconnect();
|
//rt.network.disconnect();
|
||||||
return; // proceed to the next async block
|
return; // proceed to the next async block
|
||||||
}
|
}
|
||||||
|
|
||||||
// they tried to just log in but there's no such user
|
// they tried to just log in but there's no such user
|
||||||
// and since we're here at all there is no modern-block
|
// and since we're here at all there is no modern-block
|
||||||
if (!isRegister && isProxyEmpty(rt.proxy)) {
|
if (!isRegister && isProxyEmpty(rt.proxy)) {
|
||||||
rt.network.disconnect(); // clean up after yourself
|
//rt.network.disconnect(); // clean up after yourself
|
||||||
waitFor.abort();
|
waitFor.abort();
|
||||||
return void cb('NO_SUCH_USER', res);
|
return void cb('NO_SUCH_USER', res);
|
||||||
}
|
}
|
||||||
|
|
||||||
// they tried to register, but those exact credentials exist
|
// they tried to register, but those exact credentials exist
|
||||||
if (isRegister && !isProxyEmpty(rt.proxy)) {
|
if (isRegister && !isProxyEmpty(rt.proxy)) {
|
||||||
rt.network.disconnect();
|
//rt.network.disconnect();
|
||||||
waitFor.abort();
|
waitFor.abort();
|
||||||
Feedback.send('LOGIN', true);
|
Feedback.send('LOGIN', true);
|
||||||
return void cb('ALREADY_REGISTERED', res);
|
return void cb('ALREADY_REGISTERED', res);
|
||||||
|
@ -247,6 +247,7 @@ define([
|
||||||
// so setting them is just a precaution to keep things in good shape
|
// so setting them is just a precaution to keep things in good shape
|
||||||
res.proxy = rt.proxy;
|
res.proxy = rt.proxy;
|
||||||
res.realtime = rt.realtime;
|
res.realtime = rt.realtime;
|
||||||
|
res.network = rt.network;
|
||||||
|
|
||||||
// they're registering...
|
// they're registering...
|
||||||
res.userHash = opt.userHash;
|
res.userHash = opt.userHash;
|
||||||
|
@ -317,6 +318,7 @@ define([
|
||||||
|
|
||||||
res.proxy = rt.proxy;
|
res.proxy = rt.proxy;
|
||||||
res.realtime = rt.realtime;
|
res.realtime = rt.realtime;
|
||||||
|
res.network = rt.network;
|
||||||
|
|
||||||
// they're registering...
|
// they're registering...
|
||||||
res.userHash = userHash;
|
res.userHash = userHash;
|
||||||
|
@ -328,14 +330,14 @@ define([
|
||||||
// this really shouldn't happen, but let's handle it anyway
|
// this really shouldn't happen, but let's handle it anyway
|
||||||
Feedback.send('EMPTY_LOGIN_WITH_BLOCK');
|
Feedback.send('EMPTY_LOGIN_WITH_BLOCK');
|
||||||
|
|
||||||
rt.network.disconnect(); // clean up after yourself
|
//rt.network.disconnect(); // clean up after yourself
|
||||||
waitFor.abort();
|
waitFor.abort();
|
||||||
return void cb('NO_SUCH_USER', res);
|
return void cb('NO_SUCH_USER', res);
|
||||||
}
|
}
|
||||||
|
|
||||||
// they tried to register, but those exact credentials exist
|
// they tried to register, but those exact credentials exist
|
||||||
if (isRegister && !isProxyEmpty(rt.proxy)) {
|
if (isRegister && !isProxyEmpty(rt.proxy)) {
|
||||||
rt.network.disconnect();
|
//rt.network.disconnect();
|
||||||
waitFor.abort();
|
waitFor.abort();
|
||||||
res.blockHash = blockHash;
|
res.blockHash = blockHash;
|
||||||
if (shouldImport) {
|
if (shouldImport) {
|
||||||
|
@ -462,7 +464,8 @@ define([
|
||||||
|
|
||||||
var proceed = function (result) {
|
var proceed = function (result) {
|
||||||
hashing = false;
|
hashing = false;
|
||||||
if (test && typeof test === "function" && test()) { return; }
|
// NOTE: test is also use as a cb for the install page
|
||||||
|
if (test && typeof test === "function" && test(result)) { return; }
|
||||||
LocalStore.clearLoginToken();
|
LocalStore.clearLoginToken();
|
||||||
Realtime.whenRealtimeSyncs(result.realtime, function () {
|
Realtime.whenRealtimeSyncs(result.realtime, function () {
|
||||||
Exports.redirect();
|
Exports.redirect();
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
define([
|
||||||
|
'/api/config',
|
||||||
|
'jquery',
|
||||||
|
'/common/hyperscript.js',
|
||||||
|
'/common/common-interface.js',
|
||||||
|
'/customize/messages.js',
|
||||||
|
'/customize/pages.js'
|
||||||
|
], function (Config, $, h, UI, Msg, Pages) {
|
||||||
|
Config.adminKeys = [];
|
||||||
|
return function () {
|
||||||
|
// Redirect to drive if this instance already has admins
|
||||||
|
if (Array.isArray(Config.adminKeys) && Config.adminKeys.length) {
|
||||||
|
document.location.href = '/drive/';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Msg.install_header = "CryptPad Install"; // XXX
|
||||||
|
Msg.install_notes = "<ul class=\"cp-notes-list\"><li>Create your first admin account using this form.</li>" +
|
||||||
|
"<li>Please note your password carefully. <span class=\"red\">If you lose it there is no way we can recover your data.</span></li></ul>"; // XXX
|
||||||
|
*/
|
||||||
|
Msg.install_token = "Install token";
|
||||||
|
|
||||||
|
document.title = Msg.install_header;
|
||||||
|
|
||||||
|
var frame = function (content) {
|
||||||
|
return [
|
||||||
|
h('div#cp-main', [
|
||||||
|
//Pages.infopageTopbar(),
|
||||||
|
h('div.container.cp-container', [
|
||||||
|
//h('div.row.cp-page-title', h('h1', Msg.install_header)),
|
||||||
|
h('div.row.cp-page-title', h('h1', Msg.register_header)),
|
||||||
|
].concat(content)),
|
||||||
|
Pages.infopageFooter(),
|
||||||
|
]),
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
return frame([
|
||||||
|
h('div.row.cp-register-det', [
|
||||||
|
h('div#data.hidden.col-md-6', [
|
||||||
|
h('h2', Msg.register_notes_title),
|
||||||
|
//Pages.setHTML(h('div.cp-register-notes'), Msg.install_notes)
|
||||||
|
Pages.setHTML(h('div.cp-register-notes'), Msg.register_notes)
|
||||||
|
]),
|
||||||
|
h('div.cp-reg-form.col-md-6', [
|
||||||
|
h('div#userForm.form-group.hidden', [
|
||||||
|
h('div.cp-register-instance', [
|
||||||
|
Msg._getKey('register_instance', [ Pages.Instance.name ]),
|
||||||
|
/*h('br'),
|
||||||
|
h('a', {
|
||||||
|
href: '/features.html'
|
||||||
|
}, Msg.register_whyRegister)*/
|
||||||
|
]),
|
||||||
|
h('input.form-control#installtoken', {
|
||||||
|
type: 'text',
|
||||||
|
placeholder: Msg.install_token
|
||||||
|
}),
|
||||||
|
h('input.form-control#username', {
|
||||||
|
type: 'text',
|
||||||
|
autocomplete: 'off',
|
||||||
|
autocorrect: 'off',
|
||||||
|
autocapitalize: 'off',
|
||||||
|
spellcheck: false,
|
||||||
|
placeholder: Msg.login_username,
|
||||||
|
autofocus: true,
|
||||||
|
}),
|
||||||
|
h('input.form-control#password', {
|
||||||
|
type: 'password',
|
||||||
|
placeholder: Msg.login_password,
|
||||||
|
}),
|
||||||
|
h('input.form-control#password-confirm', {
|
||||||
|
type: 'password',
|
||||||
|
placeholder: Msg.login_confirm,
|
||||||
|
}),
|
||||||
|
/*h('div.checkbox-container', [
|
||||||
|
UI.createCheckbox('import-recent', Msg.register_importRecent, true)
|
||||||
|
]),*/
|
||||||
|
h('button#register', Msg.login_register)
|
||||||
|
])
|
||||||
|
]),
|
||||||
|
])
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
|
||||||
|
});
|
||||||
|
|
|
@ -0,0 +1,126 @@
|
||||||
|
@import (reference) "../include/infopages.less";
|
||||||
|
@import (reference) "../include/colortheme-all.less";
|
||||||
|
@import (reference) "../include/alertify.less";
|
||||||
|
@import (reference) "../include/checkmark.less";
|
||||||
|
@import (reference) "../include/forms.less";
|
||||||
|
|
||||||
|
&.cp-page-install {
|
||||||
|
.infopages_main();
|
||||||
|
.forms_main();
|
||||||
|
|
||||||
|
.alertify_main();
|
||||||
|
.checkmark_main(20px);
|
||||||
|
|
||||||
|
.cp-container {
|
||||||
|
.form-group {
|
||||||
|
.cp-register-instance {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
#register {
|
||||||
|
&.btn {
|
||||||
|
padding: .5rem .5rem;
|
||||||
|
}
|
||||||
|
margin-top: 16px;
|
||||||
|
font-size: 1.25em;
|
||||||
|
min-width: 30%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
padding-bottom: 3em;
|
||||||
|
min-height: 5vh;
|
||||||
|
}
|
||||||
|
.alertify {
|
||||||
|
// workaround for alertify making empty p
|
||||||
|
p:empty {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 600px) {
|
||||||
|
nav .btn-danger {
|
||||||
|
line-height: inherit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
.cp-restricted-registration {
|
||||||
|
text-align: center !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cp-register-det {
|
||||||
|
#data {
|
||||||
|
|
||||||
|
p {
|
||||||
|
li {
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
.fa {
|
||||||
|
padding-right: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
h3 {
|
||||||
|
font-weight: 700;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.cp-reg-form {
|
||||||
|
img {
|
||||||
|
margin-top: 0px;
|
||||||
|
position: relative;
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#userForm {
|
||||||
|
padding: 15px;
|
||||||
|
background-color: @cp_static-card-bg;
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
|
margin-bottom: 100px;
|
||||||
|
border-radius: @infopages-radius-L;
|
||||||
|
.cp-shadow();
|
||||||
|
.form-control {
|
||||||
|
border-radius: @infopages-radius;
|
||||||
|
color: @cryptpad_text_col;
|
||||||
|
background-color: @cp_forms-bg;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
&:focus {
|
||||||
|
border-color: @cryptpad_color_brand;
|
||||||
|
}
|
||||||
|
.tools_placeholder-color();
|
||||||
|
}
|
||||||
|
.checkbox-container {
|
||||||
|
color: @cryptpad_text_col;
|
||||||
|
}
|
||||||
|
button#register {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cp-register-notes {
|
||||||
|
ul.cp-notes-list {
|
||||||
|
list-style: none;
|
||||||
|
margin-left: 0;
|
||||||
|
padding-left: 30px;
|
||||||
|
position: relative;
|
||||||
|
li {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
&::before {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
font-family: "FontAwesome";
|
||||||
|
content: "\f071";
|
||||||
|
}
|
||||||
|
.red {
|
||||||
|
background-color: @cp_static-danger;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -53,6 +53,8 @@ $(function () {
|
||||||
|
|
||||||
if (/^\/register\//.test(pathname)) {
|
if (/^\/register\//.test(pathname)) {
|
||||||
require([ '/register/main.js' ], function () {});
|
require([ '/register/main.js' ], function () {});
|
||||||
|
} else if (/^\/install\//.test(pathname)) {
|
||||||
|
require([ '/install/main.js' ], function () {});
|
||||||
} else if (/^\/login\//.test(pathname)) {
|
} else if (/^\/login\//.test(pathname)) {
|
||||||
require([ '/login/main.js' ], function () {});
|
require([ '/login/main.js' ], function () {});
|
||||||
} else if (/^\/($|^\/index\.html$)/.test(pathname)) {
|
} else if (/^\/($|^\/index\.html$)/.test(pathname)) {
|
||||||
|
|
|
@ -777,6 +777,25 @@ var commands = {
|
||||||
REMOVE_DOCUMENT: removeDocument,
|
REMOVE_DOCUMENT: removeDocument,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// addFirstAdmin is an anon_rpc command
|
||||||
|
Admin.addFirstAdmin = function (Env, data, cb) {
|
||||||
|
var token = data.token;
|
||||||
|
if (token !== Env.installToken) { return void cb('FORBIDDEN'); }
|
||||||
|
if (Array.isArray(Env.admins) && Env.admins.length) { return void cb('EEXISTS'); }
|
||||||
|
|
||||||
|
var key = data.edPublic;
|
||||||
|
if (token.length !== 64 || data.edPublic.length !== 44) { return void cb('INVALID_ARGS'); }
|
||||||
|
|
||||||
|
adminDecree(Env, null, function (err) {
|
||||||
|
if (err) { return void cb(err); }
|
||||||
|
Env.flushCache();
|
||||||
|
cb();
|
||||||
|
}, ['ADD_FIRST_ADMIN', [
|
||||||
|
'ADD_ADMIN_KEY',
|
||||||
|
[key]
|
||||||
|
]], "");
|
||||||
|
};
|
||||||
|
|
||||||
Admin.command = function (Env, safeKey, data, _cb, Server) {
|
Admin.command = function (Env, safeKey, data, _cb, Server) {
|
||||||
var cb = Util.once(Util.mkAsync(_cb));
|
var cb = Util.once(Util.mkAsync(_cb));
|
||||||
|
|
||||||
|
|
|
@ -322,6 +322,34 @@ commands.RM_QUOTA = function (Env, args) {
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
commands.ADD_INSTALL_TOKEN = function (Env, args) {
|
||||||
|
if (!Array.isArray(args) || args.length !== 1 || !args[0]) {
|
||||||
|
throw new Error("INVALID_ARGS");
|
||||||
|
}
|
||||||
|
|
||||||
|
var token = args[0];
|
||||||
|
|
||||||
|
// XXX check length, etc. ?
|
||||||
|
|
||||||
|
Env.installToken = token;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
commands.ADD_ADMIN_KEY = function (Env, args) {
|
||||||
|
if (!Array.isArray(args) || args.length !== 1 || !args[0]) {
|
||||||
|
throw new Error("INVALID_ARGS");
|
||||||
|
}
|
||||||
|
|
||||||
|
Env.admins = Env.admins || [];
|
||||||
|
|
||||||
|
|
||||||
|
var key = Keys.canonicalize(args[0]);
|
||||||
|
if (!key) { throw new Error("INVALID_KEY"); }
|
||||||
|
Env.admins.push(key);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
// [<command>, <args>, <author>, <time>]
|
// [<command>, <args>, <author>, <time>]
|
||||||
var handleCommand = Decrees.handleCommand = function (Env, line) {
|
var handleCommand = Decrees.handleCommand = function (Env, line) {
|
||||||
var command = line[0];
|
var command = line[0];
|
||||||
|
|
|
@ -22,6 +22,7 @@ const UNAUTHENTICATED_CALLS = {
|
||||||
WRITE_PRIVATE_MESSAGE: Channel.writePrivateMessage,
|
WRITE_PRIVATE_MESSAGE: Channel.writePrivateMessage,
|
||||||
DELETE_MAILBOX_MESSAGE: Channel.deleteMailboxMessage,
|
DELETE_MAILBOX_MESSAGE: Channel.deleteMailboxMessage,
|
||||||
GET_METADATA: Metadata.getMetadata,
|
GET_METADATA: Metadata.getMetadata,
|
||||||
|
ADD_FIRST_ADMIN: Admin.addFirstAdmin
|
||||||
};
|
};
|
||||||
|
|
||||||
var isUnauthenticateMessage = function (msg) {
|
var isUnauthenticateMessage = function (msg) {
|
||||||
|
|
|
@ -74,7 +74,7 @@ Stats.instanceData = function (Env) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Admins can opt-in to providing more detailed information about the extent of the instance's usage
|
// Admins can opt-in to providing more detailed information about the extent of the instance's usage
|
||||||
if (!Env.provideAggregateStatistics) {
|
if (Env.provideAggregateStatistics) {
|
||||||
// check how many instances provide stats before we put more work into it
|
// check how many instances provide stats before we put more work into it
|
||||||
data.providesAggregateStatistics = true;
|
data.providesAggregateStatistics = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
"get-folder-size": "^2.0.1",
|
"get-folder-size": "^2.0.1",
|
||||||
"netflux-websocket": "^0.1.20",
|
"netflux-websocket": "^0.1.20",
|
||||||
"nthen": "0.1.8",
|
"nthen": "0.1.8",
|
||||||
|
"prompt-confirm": "^2.0.4",
|
||||||
"pull-stream": "^3.6.1",
|
"pull-stream": "^3.6.1",
|
||||||
"saferphore": "0.0.1",
|
"saferphore": "0.0.1",
|
||||||
"sortify": "^1.0.4",
|
"sortify": "^1.0.4",
|
||||||
|
@ -50,6 +51,8 @@
|
||||||
"test": "node scripts/TestSelenium.js",
|
"test": "node scripts/TestSelenium.js",
|
||||||
"test-rpc": "cd scripts/tests && node test-rpc",
|
"test-rpc": "cd scripts/tests && node test-rpc",
|
||||||
"evict-inactive": "node scripts/evict-inactive.js",
|
"evict-inactive": "node scripts/evict-inactive.js",
|
||||||
"build": "node scripts/build.js"
|
"build": "node scripts/build.js",
|
||||||
|
"clear": "node scripts/clear.js",
|
||||||
|
"installtoken": "node scripts/install.js"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
var prompt = require('prompt-confirm');
|
||||||
|
const p = new prompt('Are you sure? This will permanently delete all existing data on your instance.');
|
||||||
|
|
||||||
|
const nThen = require("nthen");
|
||||||
|
const Fs = require("fs");
|
||||||
|
const Path = require("path");
|
||||||
|
|
||||||
|
var config = require("../lib/load-config");
|
||||||
|
var Hash = require('../www/common/common-hash');
|
||||||
|
var Env = require("../lib/env").create(config);
|
||||||
|
Env.Log = { error: console.log };
|
||||||
|
|
||||||
|
var keyOrDefaultString = function (key, def) {
|
||||||
|
return Path.resolve(typeof(config[key]) === 'string'? config[key]: def);
|
||||||
|
};
|
||||||
|
var paths = Env.paths;
|
||||||
|
p.ask(function (answer) {
|
||||||
|
if (!answer) {
|
||||||
|
console.log('Abort');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log('Deleting all data...');
|
||||||
|
var n = nThen;
|
||||||
|
Object.values(paths).forEach(function (path) {
|
||||||
|
console.log(`Deleting ${path}`);
|
||||||
|
Fs.rmSync(path, { recursive: true, force: true });
|
||||||
|
console.log('Deleted');
|
||||||
|
});
|
||||||
|
console.log('Success');
|
||||||
|
});
|
|
@ -0,0 +1,41 @@
|
||||||
|
const nThen = require("nthen");
|
||||||
|
const Fs = require("fs");
|
||||||
|
const Path = require("path");
|
||||||
|
const Decrees = require("../lib/decrees");
|
||||||
|
|
||||||
|
var config = require("../lib/load-config");
|
||||||
|
var Hash = require('../www/common/common-hash');
|
||||||
|
var Env = require("../lib/env").create(config);
|
||||||
|
|
||||||
|
Env.Log = { error: console.log };
|
||||||
|
|
||||||
|
var path = Path.join(Env.paths.decree, 'decree.ndjson');
|
||||||
|
var token;
|
||||||
|
nThen(function (w) {
|
||||||
|
Decrees.load(Env, w(function (err) {
|
||||||
|
if (err) {
|
||||||
|
console.error(err);
|
||||||
|
w.abort();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (Env.installToken) {
|
||||||
|
console.log('Existing token');
|
||||||
|
token = Env.installToken;
|
||||||
|
}
|
||||||
|
// XXX IF ADMINS ABORT?
|
||||||
|
}));
|
||||||
|
}).nThen(function (w) {
|
||||||
|
if (Env.installToken) { return; }
|
||||||
|
console.log(Env.paths.decree);
|
||||||
|
token = Hash.createChannelId() + Hash.createChannelId();
|
||||||
|
var decree = ["ADD_INSTALL_TOKEN",[token],"",+new Date()];
|
||||||
|
Fs.appendFile(path, JSON.stringify(decree) + '\n', w(function (err) {
|
||||||
|
if (err) { console.log(err); return; }
|
||||||
|
}));
|
||||||
|
}).nThen(function () {
|
||||||
|
console.log('Install token:');
|
||||||
|
console.log(token);
|
||||||
|
var url = config.httpUnsafeOrigin + '/install/';
|
||||||
|
console.log(`Please visit ${url} to create your first admin user`);
|
||||||
|
|
||||||
|
});
|
|
@ -1530,6 +1530,7 @@ define([
|
||||||
[
|
[
|
||||||
'application_config.js',
|
'application_config.js',
|
||||||
'pages.js',
|
'pages.js',
|
||||||
|
'pages/index.js',
|
||||||
].forEach(resource => {
|
].forEach(resource => {
|
||||||
// sort this above errors and warnings and style in a neutral color.
|
// sort this above errors and warnings and style in a neutral color.
|
||||||
var A = `/customize.dist/${resource}`;
|
var A = `/customize.dist/${resource}`;
|
||||||
|
@ -1712,7 +1713,7 @@ define([
|
||||||
var href = `/customize/${asset}`;
|
var href = `/customize/${asset}`;
|
||||||
return h('li', [
|
return h('li', [
|
||||||
h('a', {
|
h('a', {
|
||||||
href: `href?${+new Date()}`,
|
href: `${href}?${+new Date()}`,
|
||||||
target: '_blank',
|
target: '_blank',
|
||||||
}, href),
|
}, href),
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -148,7 +148,7 @@ define([
|
||||||
// if metadata is too large, drop the thumbnail.
|
// if metadata is too large, drop the thumbnail.
|
||||||
if (plaintext.length > 65535) {
|
if (plaintext.length > 65535) {
|
||||||
var temp = JSON.parse(JSON.stringify(metadata));
|
var temp = JSON.parse(JSON.stringify(metadata));
|
||||||
delete metadata.thumbnail;
|
delete temp.thumbnail;
|
||||||
plaintext = Nacl.util.decodeUTF8(JSON.stringify(temp));
|
plaintext = Nacl.util.decodeUTF8(JSON.stringify(temp));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<!-- If this file is not called customize.dist/src/template.html, it is generated -->
|
||||||
|
<head>
|
||||||
|
<title data-localization="main_title">CryptPad: Collaboration suite, encrypted and open-source</title>
|
||||||
|
<meta content="text/html; charset=utf-8" http-equiv="content-type"/>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||||
|
<link rel="icon" type="image/png" href="/customize/favicon/main-favicon.png" id="favicon"/>
|
||||||
|
<script src="/customize/pre-loading.js?ver=1.1"></script>
|
||||||
|
<link href="/customize/src/pre-loading.css?ver=1.0" rel="stylesheet" type="text/css">
|
||||||
|
<script async data-bootload="/customize/template.js" data-main="/common/boot.js?ver=1.0" src="/bower_components/requirejs/require.js?ver=2.3.5"></script>
|
||||||
|
</head>
|
||||||
|
<body class="html">
|
||||||
|
<noscript></noscript>
|
||||||
|
|
|
@ -0,0 +1,179 @@
|
||||||
|
define([
|
||||||
|
'jquery',
|
||||||
|
'/customize/login.js',
|
||||||
|
'/common/cryptpad-common.js',
|
||||||
|
'/common/common-credential.js',
|
||||||
|
'/common/common-interface.js',
|
||||||
|
'/common/common-util.js',
|
||||||
|
'/common/common-realtime.js',
|
||||||
|
'/common/common-constants.js',
|
||||||
|
'/common/common-feedback.js',
|
||||||
|
'/common/outer/local-store.js',
|
||||||
|
'/common/hyperscript.js',
|
||||||
|
'/customize/pages.js',
|
||||||
|
'/common/rpc.js',
|
||||||
|
|
||||||
|
'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
|
||||||
|
], function ($, Login, Cryptpad, /*Test,*/ Cred, UI, Util, Realtime, Constants, Feedback, LocalStore, h, Pages, Rpc) {
|
||||||
|
if (window.top !== window) { return; }
|
||||||
|
var Messages = Cryptpad.Messages;
|
||||||
|
$(function () {
|
||||||
|
if (LocalStore.isLoggedIn()) {
|
||||||
|
// already logged in, redirect to drive
|
||||||
|
document.location.href = '/drive/';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// text and password input fields
|
||||||
|
var $token = $('#installtoken');
|
||||||
|
var $uname = $('#username');
|
||||||
|
var $passwd = $('#password');
|
||||||
|
var $confirm = $('#password-confirm');
|
||||||
|
|
||||||
|
[ $token, $uname, $passwd, $confirm]
|
||||||
|
.some(function ($el) { if (!$el.val()) { $el.focus(); return true; } });
|
||||||
|
|
||||||
|
// checkboxes
|
||||||
|
var $register = $('button#register');
|
||||||
|
|
||||||
|
var registering = false;
|
||||||
|
|
||||||
|
var I_REALLY_WANT_TO_USE_MY_EMAIL_FOR_MY_USERNAME = false;
|
||||||
|
var br = function () { return h('br'); };
|
||||||
|
|
||||||
|
// If the token is provided in the URL, hide the field
|
||||||
|
var token;
|
||||||
|
if (window.location.hash) {
|
||||||
|
var hash = window.location.hash.slice(1);
|
||||||
|
if (hash.length === 64) {
|
||||||
|
token = hash;
|
||||||
|
$token.hide();
|
||||||
|
console.log(`Install token: ${token}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var registerClick = function () {
|
||||||
|
var uname = $uname.val().trim();
|
||||||
|
// trim whitespace surrounding the username since it is otherwise included in key derivation
|
||||||
|
// most people won't realize that its presence is significant
|
||||||
|
$uname.val(uname);
|
||||||
|
|
||||||
|
var passwd = $passwd.val();
|
||||||
|
var confirmPassword = $confirm.val();
|
||||||
|
|
||||||
|
if (!token) { token = $token.val().trim(); }
|
||||||
|
|
||||||
|
var shouldImport = false;
|
||||||
|
var doesAccept;
|
||||||
|
try {
|
||||||
|
// if this throws there's either a horrible bug (which someone will report)
|
||||||
|
// or the instance admins did not configure a terms page.
|
||||||
|
doesAccept = true;
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Cred.isEmail(uname) && !I_REALLY_WANT_TO_USE_MY_EMAIL_FOR_MY_USERNAME) {
|
||||||
|
var emailWarning = [
|
||||||
|
Messages.register_emailWarning0,
|
||||||
|
br(), br(),
|
||||||
|
Messages.register_emailWarning1,
|
||||||
|
br(), br(),
|
||||||
|
Messages.register_emailWarning2,
|
||||||
|
br(), br(),
|
||||||
|
Messages.register_emailWarning3,
|
||||||
|
];
|
||||||
|
|
||||||
|
Feedback.send("EMAIL_USERNAME_WARNING", true);
|
||||||
|
|
||||||
|
return void UI.confirm(emailWarning, function (yes) {
|
||||||
|
if (!yes) { return; }
|
||||||
|
I_REALLY_WANT_TO_USE_MY_EMAIL_FOR_MY_USERNAME = true;
|
||||||
|
registerClick();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* basic validation */
|
||||||
|
if (!Cred.isLongEnoughPassword(passwd)) {
|
||||||
|
var warning = Messages._getKey('register_passwordTooShort', [
|
||||||
|
Cred.MINIMUM_PASSWORD_LENGTH
|
||||||
|
]);
|
||||||
|
return void UI.alert(warning, function () {
|
||||||
|
registering = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (passwd !== confirmPassword) { // do their passwords match?
|
||||||
|
return void UI.alert(Messages.register_passwordsDontMatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Pages.customURLs.terms && !doesAccept) { // do they accept the terms of service? (if they exist)
|
||||||
|
return void UI.alert(Messages.register_mustAcceptTerms);
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(function () {
|
||||||
|
var span = h('span', [
|
||||||
|
h('h2', [
|
||||||
|
h('i.fa.fa-warning'),
|
||||||
|
' ',
|
||||||
|
Messages.register_warning,
|
||||||
|
]),
|
||||||
|
Messages.register_warning_note
|
||||||
|
]);
|
||||||
|
|
||||||
|
UI.confirm(span,
|
||||||
|
function (yes) {
|
||||||
|
if (!yes) { return; }
|
||||||
|
|
||||||
|
Login.loginOrRegisterUI(uname, passwd, true, shouldImport, false, function (data) {
|
||||||
|
var proxy = data.proxy;
|
||||||
|
if (!proxy || !proxy.edPublic) { UI.alert(Messages.error); return true; }
|
||||||
|
|
||||||
|
Rpc.createAnonymous(data.network, function (e, call) {
|
||||||
|
if (e) { UI.alert(Messages.error); return console.error(e); }
|
||||||
|
var anon_rpc = call;
|
||||||
|
|
||||||
|
anon_rpc.send('ADD_FIRST_ADMIN', {
|
||||||
|
token: token,
|
||||||
|
edPublic: proxy.edPublic
|
||||||
|
}, function (e) {
|
||||||
|
if (e) { UI.alert(Messages.error); return console.error(e); }
|
||||||
|
window.location.href = '/drive/';
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
registering = true;
|
||||||
|
}, {
|
||||||
|
ok: Messages.register_writtenPassword,
|
||||||
|
cancel: Messages.register_cancel,
|
||||||
|
/* If we're certain that we aren't using these "*Class" APIs
|
||||||
|
anywhere else then we can deprecate them and make this a
|
||||||
|
custom modal in common-interface (or here). */
|
||||||
|
cancelClass: 'btn.btn-cancel.btn-register',
|
||||||
|
okClass: 'btn.btn-danger.btn-register',
|
||||||
|
reverseOrder: true,
|
||||||
|
done: function ($dialog) {
|
||||||
|
$dialog.find('> div').addClass('half');
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}, 150);
|
||||||
|
};
|
||||||
|
|
||||||
|
$register.click(registerClick);
|
||||||
|
|
||||||
|
var clickRegister = Util.notAgainForAnother(function () {
|
||||||
|
$register.click();
|
||||||
|
}, 500);
|
||||||
|
|
||||||
|
$register.on('keypress', function (e) {
|
||||||
|
if (e.which === 13) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
return clickRegister();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue