Add option for hosting each realm on its own subdomain.

This adds support for running a Zulip production server with each
realm on its own unique subdomain, e.g. https://realm_name.example.com.

This patch includes a ton of important features:
* Configuring the Zulip sesion middleware to issue cookier correctly
  for the subdomains case.
* Throwing an error if the user tries to visit an invalid subdomain.
* Runs a portion of the Casper tests with REALMS_HAVE_SUBDOMAINS
  enabled to test the subdomain signup process.
* Updating our integrations documentation to refer to the current subdomain.
* Enforces that users can only login to the subdomain of their realm
  (but does not restrict the API; that will be tightened in a future commit).

Note that toggling settings.REALMS_HAVE_SUBDOMAINS on a live server is
not supported without manual intervention (the main problem will be
adding "subdomain" values for all the existing realms).

[substantially modified by tabbott as part of merging]
This commit is contained in:
hackerkid
2016-07-19 18:05:08 +05:30
committed by Tim Abbott
parent 15f6cc7c84
commit ea39fb2556
25 changed files with 442 additions and 82 deletions

View File

@@ -1,3 +1,4 @@
var REALMS_HAVE_SUBDOMAINS = casper.cli.get('subdomains');
var common = (function () {
var exports = {};
@@ -83,7 +84,13 @@ exports.then_log_in = function (credentials) {
};
exports.start_and_log_in = function (credentials, viewport) {
casper.start('http://127.0.0.1:9981/accounts/login', function () {
var log_in_url = "";
if (REALMS_HAVE_SUBDOMAINS) {
log_in_url = "http://zulip.zulipdev.com:9981/accounts/login";
} else {
log_in_url = "http://localhost:9981/accounts/login";
}
casper.start(log_in_url, function () {
exports.initialize_casper(viewport);
log_in(credentials);
});

View File

@@ -2,9 +2,20 @@ var common = require('../casper_lib/common.js').common;
var email = 'alice@test.example.com';
var domain = 'test.example.com';
var subdomain = 'testsubdomain';
var organization_name = 'Awesome Organization';
var REALMS_HAVE_SUBDOMAINS = casper.cli.get('subdomains');
var host;
var realm_host;
casper.start('http://127.0.0.1:9981/create_realm/');
if (REALMS_HAVE_SUBDOMAINS) {
host = 'zulipdev.com:9981';
realm_host = subdomain + '.' + host;
} else {
host = realm_host = 'localhost:9981';
}
casper.start('http://' + host + '/create_realm/');
casper.then(function () {
// Submit the email for realm creation
@@ -21,12 +32,12 @@ casper.then(function () {
});
// Special endpoint enabled only during tests for extracting confirmation key
casper.thenOpen('http://127.0.0.1:9981/confirmation_key/');
casper.thenOpen('http://' + host + '/confirmation_key/');
// Open the confirmation URL
casper.then(function () {
var confirmation_key = JSON.parse(this.getPageContent()).confirmation_key;
var confirmation_url = 'http://127.0.0.1:9981/accounts/do_confirm/' + confirmation_key;
var confirmation_url = 'http://' + host + '/accounts/do_confirm/' + confirmation_key;
this.thenOpen(confirmation_url);
});
@@ -47,16 +58,26 @@ casper.then(function () {
casper.then(function () {
this.waitForSelector('form[action^="/accounts/register/"]', function () {
this.fill('form[action^="/accounts/register/"]', {
full_name: 'Alice',
realm_name: organization_name,
password: 'password',
terms: true
}, true);
if (REALMS_HAVE_SUBDOMAINS) {
this.fill('form[action^="/accounts/register/"]', {
full_name: 'Alice',
realm_name: organization_name,
realm_subdomain: subdomain,
password: 'password',
terms: true
}, true);
} else {
this.fill('form[action^="/accounts/register/"]', {
full_name: 'Alice',
realm_name: organization_name,
password: 'password',
terms: true
}, true);
}
});
this.waitWhileSelector('form[action^="/accounts/register/"]', function () {
casper.test.assertUrlMatch('http://127.0.0.1:9981/invite/', 'Invite more users page loaded');
casper.test.assertUrlMatch(realm_host + '/invite/', 'Invite more users page loaded');
});
});
@@ -75,7 +96,7 @@ casper.then(function () {
});
this.waitWhileSelector('#submit_invitation', function () {
this.test.assertUrlMatch('http://127.0.0.1:9981/', 'Realm created and logged in');
this.test.assertUrlMatch(realm_host, 'Realm created and logged in');
});
});

View File

@@ -1,7 +1,14 @@
var common = require('../casper_lib/common.js').common;
var REALMS_HAVE_SUBDOMAINS = casper.cli.get('subdomains');
var realm_url = "";
if (REALMS_HAVE_SUBDOMAINS) {
realm_url = "http://zulip.zulipdev.com:9981/";
} else {
realm_url = "http://localhost:9981/";
}
// Start of test script.
casper.start('http://127.0.0.1:9981/', common.initialize_casper);
casper.start(realm_url, common.initialize_casper);
casper.then(function () {
casper.test.assertHttpStatus(302);

View File

@@ -1,5 +1,6 @@
var common = require('../casper_lib/common.js').common;
var test_credentials = require('../../var/casper/test_credentials.js').test_credentials;
var REALMS_HAVE_SUBDOMAINS = casper.cli.get('subdomains');
common.start_and_log_in();
@@ -166,7 +167,14 @@ casper.waitForSelector("#default_language", function () {
casper.test.info("Opening German page through i18n url.");
});
casper.thenOpen('http://127.0.0.1:9981/de/#settings');
var settings_url = "";
if (REALMS_HAVE_SUBDOMAINS) {
settings_url = 'http://zulip.zulipdev.com:9981/de/#settings';
} else {
settings_url = 'http://localhost:9981/de/#settings';
}
casper.thenOpen(settings_url);
casper.waitForSelector("#settings-change-box", function check_url_preference() {
casper.test.info("Checking the i18n url language precedence.");

View File

@@ -144,7 +144,7 @@ casper.then(function () {
casper.waitForSelector('.admin-emoji-form', function () {
casper.fill('form.admin-emoji-form', {
'name': 'MouseFace',
'url': 'http://127.0.0.1:9991/static/images/integrations/logos/jenkins.png'
'url': 'http://localhost:9991/static/images/integrations/logos/jenkins.png'
});
casper.click('form.admin-emoji-form input.button');
});
@@ -159,7 +159,7 @@ casper.then(function () {
casper.then(function () {
casper.waitForSelector('.emoji_row', function () {
casper.test.assertSelectorHasText('.emoji_row .emoji_name', 'MouseFace');
casper.test.assertExists('.emoji_row img[src="http://127.0.0.1:9991/static/images/integrations/logos/jenkins.png"]');
casper.test.assertExists('.emoji_row img[src="http://localhost:9991/static/images/integrations/logos/jenkins.png"]');
casper.click('.emoji_row button.delete');
});
});

View File

@@ -64,8 +64,8 @@ def server_is_up(server):
except:
return False
def run_tests(files):
# type: (Iterable[str]) -> None
def run_tests(realms_have_subdomains, files):
# type: (bool, Iterable[str]) -> None
test_files = []
for file in files:
if not os.path.exists(file):
@@ -78,7 +78,7 @@ def run_tests(files):
if options.remote_debug:
remote_debug = "--remote-debugger-port=7777 --remote-debugger-autorun=yes"
cmd = "frontend_tests/casperjs/bin/casperjs %s test " % (remote_debug,)
cmd = "frontend_tests/casperjs/bin/casperjs %s test --subdomains=%s " % (remote_debug, realms_have_subdomains,)
if test_files:
cmd += ' '.join(test_files)
else:
@@ -115,5 +115,13 @@ Oops, the frontend tests failed. Tips for debugging:
sys.exit(ret)
run_tests(args)
# Run tests with REALMS_HAVE_SUBDOMAINS set to True
run_tests(False, args)
os.environ["EXTERNAL_HOST"] = "zulipdev.com:9981"
os.environ["REALMS_HAVE_SUBDOMAINS"] = "True"
# Run tests with REALMS_HAVE_SUBDOMAINS set to True
if len(args) == 0:
run_tests(True, ["00-realm-creation.js", "01-login.js", "02-site.js"])
else:
run_tests(True, args)
sys.exit(0)