From 50045c08d04d0d5fb436170cd88f3beb05a5088b Mon Sep 17 00:00:00 2001 From: ansuz Date: Mon, 26 Apr 2021 18:31:33 +0530 Subject: [PATCH] WIP restrict registration --- customize.dist/login.js | 4 ++++ customize.dist/pages.js | 11 +++++++++-- customize.dist/template.js | 1 - lib/commands/block.js | 7 ++++++- lib/env.js | 1 + server.js | 1 + www/admin/inner.js | 4 ++-- www/checkup/main.js | 10 +++++++++- www/login/main.js | 10 ---------- www/register/main.js | 18 +++++++----------- www/settings/inner.js | 1 + 11 files changed, 40 insertions(+), 28 deletions(-) diff --git a/customize.dist/login.js b/customize.dist/login.js index 7024734ed..fa950afc2 100644 --- a/customize.dist/login.js +++ b/customize.dist/login.js @@ -534,6 +534,10 @@ define([ }); }); break; + case 'E_RESTRICTED': + Messages.register_restrictedError = "Registration is restricted on this instance"; // XXX + UI.errorLoadingScreen(Messages.register_restrictedError); // XXX + break; default: // UNHANDLED ERROR hashing = false; UI.errorLoadingScreen(Messages.login_unhandledError); diff --git a/customize.dist/pages.js b/customize.dist/pages.js index f8d7ad15c..43254ad27 100644 --- a/customize.dist/pages.js +++ b/customize.dist/pages.js @@ -4,7 +4,8 @@ define([ '/customize/application_config.js', '/customize/messages.js', 'jquery', -], function (h, Language, AppConfig, Msg, $) { + '/api/config', +], function (h, Language, AppConfig, Msg, $, ApiConfig) { var Pages = {}; Pages.setHTML = function (e, html) { @@ -157,10 +158,16 @@ define([ Pages.infopageTopbar = function () { var rightLinks; var username = window.localStorage.getItem('User_name'); + var registerLink; + + if (!ApiConfig.restrictRegistration) { + registerLink = h('a.nav-item.nav-link.cp-register-btn', { href: '/register/'}, Msg.login_register); + } + if (username === null) { rightLinks = [ h('a.nav-item.nav-link.cp-login-btn', { href: '/login/'}, Msg.login_login), - h('a.nav-item.nav-link.cp-register-btn', { href: '/register/'}, Msg.login_register) + registerLink, ]; } else { rightLinks = h('a.nav-item.nav-link.cp-user-btn', { href: '/drive/' }, [ diff --git a/customize.dist/template.js b/customize.dist/template.js index 7721339f3..0e9b3f2b9 100644 --- a/customize.dist/template.js +++ b/customize.dist/template.js @@ -50,7 +50,6 @@ $(function () { } else if (/^\/login\//.test(pathname)) { require([ '/login/main.js' ], function () {}); } else if (/^\/($|^\/index\.html$)/.test(pathname)) { - // TODO use different top bar require([ '/customize/main.js', ], function () {}); } else { require([ '/customize/main.js', ], function () {}); diff --git a/lib/commands/block.js b/lib/commands/block.js index 3a264c167..8d2db4f16 100644 --- a/lib/commands/block.js +++ b/lib/commands/block.js @@ -86,12 +86,17 @@ var createLoginBlockPath = function (Env, publicKey) { // FIXME BLOCKS return Path.join(Env.paths.block, safeKey.slice(0, 2), safeKey); }; -Block.writeLoginBlock = function (Env, safeKey, msg, cb) { // FIXME BLOCKS +Block.writeLoginBlock = function (Env, safeKey, msg, _cb) { // FIXME BLOCKS + var cb = Util.once(Util.mkAsync(_cb)); //console.log(msg); var publicKey = msg[0]; var signature = msg[1]; var block = msg[2]; + if (Env.restrictRegistration /* && notAlreadyRegistered */) { // XXX restricted-registration + return void cb("E_RESTRICTED"); + } + validateLoginBlock(Env, publicKey, signature, block, function (e, validatedBlock) { if (e) { return void cb(e); } if (!(validatedBlock instanceof Uint8Array)) { return void cb('E_INVALID_BLOCK'); } diff --git a/lib/env.js b/lib/env.js index b879d102f..b3ed7cf35 100644 --- a/lib/env.js +++ b/lib/env.js @@ -89,6 +89,7 @@ module.exports.create = function (config) { } }, + restrictRegistration: false, allowSubscriptions: config.allowSubscriptions === true, blockDailyCheck: config.blockDailyCheck === true, diff --git a/server.js b/server.js index 443c16a52..3b49ce4d5 100644 --- a/server.js +++ b/server.js @@ -276,6 +276,7 @@ var serveConfig = makeRouteCache(function (host) { defaultStorageLimit: Env.defaultStorageLimit, maxUploadSize: Env.maxUploadSize, premiumUploadSize: Env.premiumUploadSize, + restrictRegistration: Env.restrictRegistration, // XXX restricted-registration }, null, '\t'), 'obj.httpSafeOrigin = ' + (function () { if (config.httpSafeOrigin) { return '"' + config.httpSafeOrigin + '"'; } diff --git a/www/admin/inner.js b/www/admin/inner.js index 332ff1fe3..844a27aea 100644 --- a/www/admin/inner.js +++ b/www/admin/inner.js @@ -53,7 +53,7 @@ define([ 'cp-admin-update-limit', 'cp-admin-archive', 'cp-admin-unarchive', - // 'cp-admin-registration', + 'cp-admin-registration', // XXX restricted-registration ], 'quota': [ // Msg.admin_cat_quota 'cp-admin-defaultlimit', @@ -254,7 +254,7 @@ define([ create['registration'] = function () { var key = 'registration'; var $div = makeBlock(key, true); // Msg.admin_registrationHint, .admin_registrationTitle, .admin_registrationButton - var $button = $div.find('button'); + var $button = $div.find('button'); // XXX restricted-registration: a checkbox might be better. it's easy to misinterpret the verb "OPEN" as an adjective var state = APP.instanceStatus.restrictRegistration; if (state) { $button.text(Messages.admin_registrationAllow); diff --git a/www/checkup/main.js b/www/checkup/main.js index 68d35a12e..f02b11c9e 100644 --- a/www/checkup/main.js +++ b/www/checkup/main.js @@ -243,7 +243,7 @@ define([ opt.keys = secret.keys; opt.channelHex = secret.channel; - var RT, rpc, exists; + var RT, rpc, exists, restricted; nThen(function (waitFor) { Util.fetch(blockUrl, waitFor(function (err) { @@ -285,6 +285,12 @@ define([ // Write block if (exists) { return; } rpc.writeLoginBlock(blockRequest, waitFor(function (e) { + // we should tolerate restricted registration + // and proceed to clean up after any data we've created + if (e === 'E_RESTRICTED') { + restricted = true; + return void cb(true); + } if (e) { waitFor.abort(); console.error("Can't write login block", e); @@ -292,6 +298,7 @@ define([ } })); }).nThen(function (waitFor) { + if (restricted) { return; } // Read block Util.fetch(blockUrl, waitFor(function (e) { if (e) { @@ -303,6 +310,7 @@ define([ }).nThen(function (waitFor) { // Remove block rpc.removeLoginBlock(removeRequest, waitFor(function (e) { + if (restricted) { return; } // an ENOENT is expected in the case of restricted registration, but we call this anyway to clean up any mess from previous tests. if (e) { waitFor.abort(); console.error("Can't remove login block", e); diff --git a/www/login/main.js b/www/login/main.js index 5023e0b19..cb03e17f3 100644 --- a/www/login/main.js +++ b/www/login/main.js @@ -11,21 +11,11 @@ define([ 'css!/bower_components/components-font-awesome/css/font-awesome.min.css', ], function ($, Cryptpad, Login, UI, Realtime, Feedback, LocalStore, Test) { $(function () { - var $main = $('#mainBlock'); var $checkImport = $('#import-recent'); - - // main block is hidden in case javascript is disabled - $main.removeClass('hidden'); - - // Make sure we don't display non-translated content (empty button) - $main.find('#data').removeClass('hidden'); - if (LocalStore.isLoggedIn()) { // already logged in, redirect to drive document.location.href = '/drive/'; return; - } else { - $main.find('#userForm').removeClass('hidden'); } /* Log in UI */ diff --git a/www/register/main.js b/www/register/main.js index b241fd4e5..b86b07b48 100644 --- a/www/register/main.js +++ b/www/register/main.js @@ -11,26 +11,22 @@ define([ '/common/common-feedback.js', '/common/outer/local-store.js', '/common/hyperscript.js', + '/api/config', 'css!/bower_components/components-font-awesome/css/font-awesome.min.css', -], function ($, Login, Cryptpad, Test, Cred, UI, Util, Realtime, Constants, Feedback, LocalStore, h) { +], function ($, Login, Cryptpad, Test, Cred, UI, Util, Realtime, Constants, Feedback, LocalStore, h, ApiConfig) { var Messages = Cryptpad.Messages; - + Messages.register_registrationIsClosed = "REGISTRATION IS CLOSED ON THIS INSTANCE."; // XXX $(function () { - var $main = $('#mainBlock'); - - // main block is hidden in case javascript is disabled - $main.removeClass('hidden'); - - // Make sure we don't display non-translated content (empty button) - $main.find('#data').removeClass('hidden'); + if (ApiConfig.restrictRegistration) { + return void UI.alert(Messages.register_registrationIsClosed); // XXX restricted-registration better UI ? + // remove the form and display text instead of an alert that people will probably dismiss? + } if (LocalStore.isLoggedIn()) { // already logged in, redirect to drive document.location.href = '/drive/'; return; - } else { - $main.find('#userForm').removeClass('hidden'); } // text and password input fields diff --git a/www/settings/inner.js b/www/settings/inner.js index 758b90069..4ffdfe530 100644 --- a/www/settings/inner.js +++ b/www/settings/inner.js @@ -593,6 +593,7 @@ define([ $(form).appendTo($div); var updateBlock = function(data, cb) { +// XXX restricted-registration registered users should be able to change their password even if registration is closed. Include proof of ownership of their existing block when requesting the creation of a new one sframeChan.query('Q_CHANGE_USER_PASSWORD', data, function(err, obj) { if (err || obj.error) { return void cb({ error: err || obj.error }); } cb(obj);