mirror of https://github.com/zulip/zulip.git
Add RealmAlias.allow_subdomains to model, frontend, and API.
Includes a database migration. Fixes #1868.
This commit is contained in:
parent
a16c48f0c4
commit
7d10cbc32b
|
@ -97,6 +97,7 @@ function render(template_name, args) {
|
|||
var args = {
|
||||
alias: {
|
||||
domain: 'zulip.org',
|
||||
allow_subdomains: true,
|
||||
},
|
||||
};
|
||||
html += render("admin-alias-list", args);
|
||||
|
@ -104,11 +105,15 @@ function render(template_name, args) {
|
|||
|
||||
var button = $(html).find('.btn');
|
||||
var domain = $(html).find('.domain');
|
||||
var row = button.closest('tr');
|
||||
var subdomains_checkbox = row.find('.allow-subdomains');
|
||||
|
||||
assert.equal(button.text().trim(), "Remove");
|
||||
assert(button.hasClass("delete_alias"));
|
||||
assert.equal(domain.text(), "zulip.org");
|
||||
|
||||
assert.equal(subdomains_checkbox.prop('checked'), true);
|
||||
|
||||
global.write_handlebars_output("admin-alias-list", html);
|
||||
}());
|
||||
|
||||
|
|
|
@ -212,8 +212,8 @@ exports.populate_realm_aliases = function (aliases) {
|
|||
return;
|
||||
}
|
||||
|
||||
var domains_list = _.map(page_params.domains, function (ADomain) {
|
||||
return ADomain.domain;
|
||||
var domains_list = _.map(aliases, function (alias) {
|
||||
return (alias.allow_subdomains ? "*." + alias.domain : alias.domain);
|
||||
});
|
||||
var domains = domains_list.join(', ');
|
||||
if (domains.length === 0) {
|
||||
|
@ -955,17 +955,19 @@ function _setup_page() {
|
|||
});
|
||||
});
|
||||
|
||||
$("#add_alias").click(function () {
|
||||
$("#submit-add-alias").click(function () {
|
||||
var aliases_info = $("#realm_aliases_modal").find(".aliases_info");
|
||||
var data = {
|
||||
domain: JSON.stringify($("#new_alias").val()),
|
||||
domain: JSON.stringify($("#add-alias-widget .new-alias-domain").val()),
|
||||
allow_subdomains: JSON.stringify($("#add-alias-widget .new-alias-allow-subdomains").prop("checked")),
|
||||
};
|
||||
|
||||
channel.post({
|
||||
url: "/json/realm/domains",
|
||||
data: data,
|
||||
success: function () {
|
||||
$("#new_alias").val("");
|
||||
$("#add-alias-widget .new-alias-domain").val("");
|
||||
$("#add-alias-widget .new-alias-allow-subdomains").prop("checked", false);
|
||||
aliases_info.removeClass("text-error");
|
||||
aliases_info.addClass("text-success");
|
||||
aliases_info.text("Added successfully!");
|
||||
|
@ -978,6 +980,38 @@ function _setup_page() {
|
|||
});
|
||||
});
|
||||
|
||||
$("#alias_table").on("change", ".allow-subdomains", function (e) {
|
||||
e.stopPropagation();
|
||||
var aliases_info = $("#realm_aliases_modal").find(".aliases_info");
|
||||
var domain = $(this).parents("tr").find(".domain").text();
|
||||
var allow_subdomains = $(this).prop('checked');
|
||||
var url = '/json/realm/domains/' + domain;
|
||||
var data = {
|
||||
allow_subdomains: JSON.stringify(allow_subdomains),
|
||||
};
|
||||
|
||||
channel.patch({
|
||||
url: url,
|
||||
data: data,
|
||||
success: function () {
|
||||
aliases_info.removeClass("text-error");
|
||||
aliases_info.addClass("text-success");
|
||||
if (allow_subdomains) {
|
||||
aliases_info.text(i18n.t("Update successful: Subdomains allowed for __domain__",
|
||||
{domain: domain}));
|
||||
} else {
|
||||
aliases_info.text(i18n.t("Update successful: Subdomains no longer allowed for __domain__",
|
||||
{domain: domain}));
|
||||
}
|
||||
},
|
||||
error: function (xhr) {
|
||||
aliases_info.removeClass("text-success");
|
||||
aliases_info.addClass("text-error");
|
||||
aliases_info.text(JSON.parse(xhr.responseText).msg);
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
exports.setup_page = function () {
|
||||
|
|
|
@ -108,10 +108,17 @@ function dispatch_normal_event(event) {
|
|||
break;
|
||||
|
||||
case 'realm_domains':
|
||||
var i;
|
||||
if (event.op === 'add') {
|
||||
page_params.domains.push(event.alias);
|
||||
} else if (event.op === 'change') {
|
||||
for (i = 0; i < page_params.domains.length; i += 1) {
|
||||
if (page_params.domains[i].domain === event.alias.domain) {
|
||||
page_params.domains[i].allow_subdomains = event.alias.allow_subdomains;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (event.op === 'remove') {
|
||||
var i;
|
||||
for (i = 0; i < page_params.domains.length; i += 1) {
|
||||
if (page_params.domains[i].domain === event.domain) {
|
||||
page_params.domains.splice(i, 1);
|
||||
|
@ -121,6 +128,7 @@ function dispatch_normal_event(event) {
|
|||
}
|
||||
admin.populate_realm_aliases(page_params.domains);
|
||||
break;
|
||||
|
||||
case 'realm_user':
|
||||
if (event.op === 'add') {
|
||||
people.add_in_realm(event.person);
|
||||
|
|
|
@ -437,12 +437,12 @@ input[type=checkbox].inline-block {
|
|||
padding: 10px 15px;
|
||||
}
|
||||
|
||||
#administration #new_alias {
|
||||
#administration .new-alias-domain {
|
||||
width: 130px;
|
||||
margin-bottom: auto;
|
||||
padding: 0px 2px;
|
||||
}
|
||||
|
||||
#administration #add_alias {
|
||||
#administration #submit-add-alias {
|
||||
width: 75px;
|
||||
}
|
||||
|
|
|
@ -83,14 +83,16 @@
|
|||
<table class="table table-condensed table-stripped" id="alias_table">
|
||||
<thead>
|
||||
<th>{{t "Domain" }}</th>
|
||||
<th>{{t "Allow Subdomains"}}</th>
|
||||
<th>{{t "Action" }}</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td><input type="text" id="new_alias" placeholder={{t "acme.com" }}></input></td>
|
||||
<td><button type="button" class="btn btn-primary" id="add_alias">{{t "Add" }}</button></td>
|
||||
<tr id="add-alias-widget">
|
||||
<td><input type="text" class="new-alias-domain" placeholder={{t "acme.com" }}></input></td>
|
||||
<td><input type="checkbox" class="new-alias-allow-subdomains"></input></td>
|
||||
<td><button type="button" class="btn btn-primary" id="submit-add-alias">{{t "Add" }}</button></td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
{{#with alias}}
|
||||
<tr>
|
||||
<td class="domain">{{domain}}</td>
|
||||
<td><input type="checkbox" class="allow-subdomains" {{#if allow_subdomains}}checked{{/if}}></input></td>
|
||||
<td><button class="btn btn-danger btn-sm delete_alias">{{t "Remove" }}</button></td>
|
||||
</tr>
|
||||
{{/with}}
|
||||
|
|
|
@ -3616,17 +3616,27 @@ def get_emails_from_user_ids(user_ids):
|
|||
|
||||
def get_realm_aliases(realm):
|
||||
# type: (Realm) -> List[Dict[str, Text]]
|
||||
return list(realm.realmalias_set.values('domain'))
|
||||
return list(realm.realmalias_set.values('domain', 'allow_subdomains'))
|
||||
|
||||
def do_add_realm_alias(realm, domain):
|
||||
# type: (Realm, Text) -> (RealmAlias)
|
||||
alias = RealmAlias.objects.create(realm=realm, domain=domain)
|
||||
def do_add_realm_alias(realm, domain, allow_subdomains):
|
||||
# type: (Realm, Text, bool) -> (RealmAlias)
|
||||
alias = RealmAlias.objects.create(realm=realm, domain=domain,
|
||||
allow_subdomains=allow_subdomains)
|
||||
event = dict(type="realm_domains", op="add",
|
||||
alias=dict(domain=alias.domain,
|
||||
))
|
||||
allow_subdomains=alias.allow_subdomains))
|
||||
send_event(event, active_user_ids(realm))
|
||||
return alias
|
||||
|
||||
def do_change_realm_alias(alias, allow_subdomains):
|
||||
# type: (RealmAlias, bool) -> None
|
||||
alias.allow_subdomains = allow_subdomains
|
||||
alias.save(update_fields=['allow_subdomains'])
|
||||
event = dict(type="realm_domains", op="change",
|
||||
alias=dict(domain=alias.domain,
|
||||
allow_subdomains=alias.allow_subdomains))
|
||||
send_event(event, active_user_ids(alias.realm))
|
||||
|
||||
def do_remove_realm_alias(alias):
|
||||
# type: (RealmAlias) -> None
|
||||
realm = alias.realm
|
||||
|
|
|
@ -6,7 +6,10 @@ from typing import Any
|
|||
from argparse import ArgumentParser
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.management.base import BaseCommand
|
||||
from zerver.models import Realm, RealmAlias, get_realm, can_add_alias
|
||||
from django.db.utils import IntegrityError
|
||||
from django.utils.translation import ugettext as _
|
||||
from zerver.models import get_realm, can_add_alias, \
|
||||
Realm, RealmAlias
|
||||
from zerver.lib.actions import get_realm_aliases
|
||||
from zerver.lib.domains import validate_domain
|
||||
import sys
|
||||
|
@ -26,6 +29,11 @@ class Command(BaseCommand):
|
|||
type=str,
|
||||
default="show",
|
||||
help='What operation to do (add, show, remove).')
|
||||
parser.add_argument('--allow-subdomains',
|
||||
dest='allow_subdomains',
|
||||
action="store_true",
|
||||
default=False,
|
||||
help='Whether subdomains are allowed or not.')
|
||||
parser.add_argument('alias', metavar='<alias>', type=str, nargs='?',
|
||||
help="alias to add or remove")
|
||||
|
||||
|
@ -35,7 +43,10 @@ class Command(BaseCommand):
|
|||
if options["op"] == "show":
|
||||
print("Aliases for %s:" % (realm.domain,))
|
||||
for alias in get_realm_aliases(realm):
|
||||
print(alias["domain"])
|
||||
if alias["allow_subdomains"]:
|
||||
print(alias["domain"] + " (subdomains allowed)")
|
||||
else:
|
||||
print(alias["domain"] + " (subdomains not allowed)")
|
||||
sys.exit(0)
|
||||
|
||||
domain = options['alias'].strip().lower()
|
||||
|
@ -45,14 +56,23 @@ class Command(BaseCommand):
|
|||
print(e.messages[0])
|
||||
sys.exit(1)
|
||||
if options["op"] == "add":
|
||||
if not can_add_alias(domain):
|
||||
print("A Realm already exists for this domain, cannot add it as an alias for another realm!")
|
||||
try:
|
||||
if not can_add_alias(domain):
|
||||
print(_("The domain %(domain)s belongs to another organization.") % {'domain': domain})
|
||||
sys.exit(1)
|
||||
RealmAlias.objects.create(realm=realm, domain=domain,
|
||||
allow_subdomains=options["allow_subdomains"])
|
||||
sys.exit(0)
|
||||
except IntegrityError:
|
||||
print(_("The domain %(domain)s is already a part of your organization.") % {'domain': domain})
|
||||
sys.exit(1)
|
||||
RealmAlias.objects.create(realm=realm, domain=domain)
|
||||
sys.exit(0)
|
||||
elif options["op"] == "remove":
|
||||
RealmAlias.objects.get(realm=realm, domain=domain).delete()
|
||||
sys.exit(0)
|
||||
try:
|
||||
RealmAlias.objects.get(realm=realm, domain=domain).delete()
|
||||
sys.exit(0)
|
||||
except RealmAlias.DoesNotExist:
|
||||
print("No such entry found!")
|
||||
sys.exit(1)
|
||||
else:
|
||||
self.print_help("./manage.py", "realm_alias")
|
||||
sys.exit(1)
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.10.5 on 2017-01-25 20:55
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('zerver', '0050_userprofile_avatar_version'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='realmalias',
|
||||
name='allow_subdomains',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='realmalias',
|
||||
unique_together=set([('realm', 'domain')]),
|
||||
),
|
||||
]
|
|
@ -283,6 +283,10 @@ class RealmAlias(models.Model):
|
|||
realm = models.ForeignKey(Realm, null=True) # type: Optional[Realm]
|
||||
# should always be stored lowercase
|
||||
domain = models.CharField(max_length=80, db_index=True) # type: Text
|
||||
allow_subdomains = models.BooleanField(default=False)
|
||||
|
||||
class Meta(object):
|
||||
unique_together = ("realm", "domain")
|
||||
|
||||
def can_add_alias(domain):
|
||||
# type: (Text) -> bool
|
||||
|
@ -315,11 +319,19 @@ def get_realm_by_email_domain(email):
|
|||
if settings.REALMS_HAVE_SUBDOMAINS:
|
||||
raise GetRealmByDomainException(
|
||||
"Cannot get realm from email domain when settings.REALMS_HAVE_SUBDOMAINS = True")
|
||||
try:
|
||||
alias = RealmAlias.objects.select_related('realm').get(domain = email_to_domain(email))
|
||||
domain = email_to_domain(email)
|
||||
query = RealmAlias.objects.select_related('realm')
|
||||
alias = query.filter(domain=domain).first()
|
||||
if alias is not None:
|
||||
return alias.realm
|
||||
except RealmAlias.DoesNotExist:
|
||||
return None
|
||||
else:
|
||||
query = query.filter(allow_subdomains=True)
|
||||
while len(domain) > 0:
|
||||
subdomain, sep, domain = domain.partition('.')
|
||||
alias = query.filter(domain=domain).first()
|
||||
if alias is not None:
|
||||
return alias.realm
|
||||
return None
|
||||
|
||||
# Is a user with the given email address allowed to be in the given realm?
|
||||
# (This function does not check whether the user has been invited to the realm.
|
||||
|
@ -330,11 +342,20 @@ def email_allowed_for_realm(email, realm):
|
|||
if not realm.restricted_to_domain:
|
||||
return True
|
||||
domain = email_to_domain(email)
|
||||
return RealmAlias.objects.filter(realm = realm, domain = domain).exists()
|
||||
query = RealmAlias.objects.filter(realm=realm)
|
||||
if query.filter(domain=domain).exists():
|
||||
return True
|
||||
else:
|
||||
query = query.filter(allow_subdomains=True)
|
||||
while len(domain) > 0:
|
||||
subdomain, sep, domain = domain.partition('.')
|
||||
if query.filter(domain=domain).exists():
|
||||
return True
|
||||
return False
|
||||
|
||||
def list_of_domains_for_realm(realm):
|
||||
# type: (Realm) -> List[Text]
|
||||
return list(RealmAlias.objects.filter(realm=realm).values('domain'))
|
||||
# type: (Realm) -> List[Dict[str, Union[str, bool]]]
|
||||
return list(RealmAlias.objects.filter(realm=realm).values('domain', 'allow_subdomains'))
|
||||
|
||||
class RealmEmoji(ModelReprMixin, models.Model):
|
||||
author = models.ForeignKey('UserProfile', blank=True, null=True)
|
||||
|
|
|
@ -819,10 +819,11 @@ class EventsRegisterTest(ZulipTestCase):
|
|||
('op', equals('add')),
|
||||
('alias', check_dict([
|
||||
('domain', check_string),
|
||||
('allow_subdomains', check_bool),
|
||||
])),
|
||||
])
|
||||
realm = get_realm('zulip')
|
||||
events = self.do_test(lambda: do_add_realm_alias(realm, 'zulip.org'))
|
||||
events = self.do_test(lambda: do_add_realm_alias(realm, 'zulip.org', False))
|
||||
error = schema_checker('events[0]', events[0])
|
||||
self.assert_on_error(error)
|
||||
|
||||
|
|
|
@ -1,77 +1,169 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import absolute_import
|
||||
|
||||
from zerver.lib.actions import do_change_is_admin, do_create_realm
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db.utils import IntegrityError
|
||||
|
||||
from zerver.lib.actions import do_change_is_admin, \
|
||||
do_create_realm, do_change_realm_alias
|
||||
from zerver.lib.domains import validate_domain
|
||||
from zerver.lib.test_classes import ZulipTestCase
|
||||
from zerver.models import get_realm, get_realm_by_email_domain, \
|
||||
get_user_profile_by_email, GetRealmByDomainException, RealmAlias
|
||||
from zerver.models import email_allowed_for_realm, get_realm, \
|
||||
get_realm_by_email_domain, get_user_profile_by_email, \
|
||||
GetRealmByDomainException, RealmAlias
|
||||
|
||||
import ujson
|
||||
|
||||
|
||||
class RealmAliasTest(ZulipTestCase):
|
||||
|
||||
def test_list(self):
|
||||
def test_list_aliases(self):
|
||||
# type: () -> None
|
||||
self.login("iago@zulip.com")
|
||||
realm = get_realm('zulip')
|
||||
alias = RealmAlias(realm=realm, domain='zulip.org')
|
||||
alias.save()
|
||||
RealmAlias.objects.create(realm=realm, domain='acme.com', allow_subdomains=True)
|
||||
result = self.client_get("/json/realm/domains")
|
||||
self.assert_json_success(result)
|
||||
self.assertEqual(200, result.status_code)
|
||||
content = ujson.loads(result.content)
|
||||
self.assertEqual(len(content['domains']), 2)
|
||||
received = ujson.dumps(ujson.loads(result.content)['domains'], sort_keys=True)
|
||||
expected = ujson.dumps([{'domain': 'zulip.com', 'allow_subdomains': False},
|
||||
{'domain': 'acme.com', 'allow_subdomains': True}],
|
||||
sort_keys=True)
|
||||
self.assertEqual(received, expected)
|
||||
|
||||
def test_not_realm_admin(self):
|
||||
# type: () -> None
|
||||
self.login("hamlet@zulip.com")
|
||||
result = self.client_post("/json/realm/domains")
|
||||
self.assert_json_error(result, 'Must be a realm administrator')
|
||||
result = self.client_patch("/json/realm/domains/15")
|
||||
self.assert_json_error(result, 'Must be a realm administrator')
|
||||
result = self.client_delete("/json/realm/domains/15")
|
||||
self.assert_json_error(result, 'Must be a realm administrator')
|
||||
|
||||
def test_create(self):
|
||||
def test_create_alias(self):
|
||||
# type: () -> None
|
||||
self.login("iago@zulip.com")
|
||||
data = {'domain': ujson.dumps('')}
|
||||
data = {'domain': ujson.dumps(''),
|
||||
'allow_subdomains': ujson.dumps(True)}
|
||||
result = self.client_post("/json/realm/domains", info=data)
|
||||
self.assert_json_error(result, 'Invalid domain: Domain can\'t be empty.')
|
||||
|
||||
data = {'domain': ujson.dumps('zulip.org')}
|
||||
data['domain'] = ujson.dumps('acme.com')
|
||||
result = self.client_post("/json/realm/domains", info=data)
|
||||
self.assert_json_success(result)
|
||||
realm = get_realm('zulip')
|
||||
self.assertTrue(RealmAlias.objects.filter(realm=realm, domain='acme.com',
|
||||
allow_subdomains=True).exists())
|
||||
|
||||
result = self.client_post("/json/realm/domains", info=data)
|
||||
self.assert_json_error(result, 'The domain zulip.org is already a part of your organization.')
|
||||
self.assert_json_error(result, 'The domain acme.com is already a part of your organization.')
|
||||
|
||||
self.login("sipbtest@mit.edu")
|
||||
mit_user_profile = get_user_profile_by_email("sipbtest@mit.edu")
|
||||
do_change_is_admin(mit_user_profile, True)
|
||||
result = self.client_post("/json/realm/domains", info=data)
|
||||
self.assert_json_error(result, 'The domain zulip.org belongs to another organization.')
|
||||
self.assert_json_error(result, 'The domain acme.com belongs to another organization.')
|
||||
with self.settings(REALMS_HAVE_SUBDOMAINS=True):
|
||||
result = self.client_post("/json/realm/domains", info=data,
|
||||
HTTP_HOST=mit_user_profile.realm.host)
|
||||
self.assert_json_success(result)
|
||||
|
||||
def test_delete(self):
|
||||
def test_patch_alias(self):
|
||||
# type: () -> None
|
||||
self.login("iago@zulip.com")
|
||||
realm = get_realm('zulip')
|
||||
RealmAlias.objects.create(realm=realm, domain='zulip.org')
|
||||
aliases_count = RealmAlias.objects.count()
|
||||
RealmAlias.objects.create(realm=realm, domain='acme.com',
|
||||
allow_subdomains=False)
|
||||
data = {
|
||||
'allow_subdomains': ujson.dumps(True),
|
||||
}
|
||||
url = "/json/realm/domains/acme.com"
|
||||
result = self.client_patch(url, data)
|
||||
self.assert_json_success(result)
|
||||
self.assertTrue(RealmAlias.objects.filter(realm=realm, domain='acme.com',
|
||||
allow_subdomains=True).exists())
|
||||
|
||||
url = "/json/realm/domains/non-existent.com"
|
||||
result = self.client_patch(url, data)
|
||||
self.assertEqual(result.status_code, 400)
|
||||
self.assert_json_error(result, 'No entry found for domain non-existent.com.')
|
||||
|
||||
def test_delete_alias(self):
|
||||
# type: () -> None
|
||||
self.login("iago@zulip.com")
|
||||
realm = get_realm('zulip')
|
||||
RealmAlias.objects.create(realm=realm, domain='acme.com')
|
||||
result = self.client_delete("/json/realm/domains/non-existent.com")
|
||||
self.assertEqual(result.status_code, 400)
|
||||
self.assert_json_error(result, 'No entry found for domain non-existent.com.')
|
||||
|
||||
result = self.client_delete("/json/realm/domains/zulip.org")
|
||||
result = self.client_delete("/json/realm/domains/acme.com")
|
||||
self.assert_json_success(result)
|
||||
self.assertEqual(RealmAlias.objects.count(), aliases_count - 1)
|
||||
self.assertFalse(RealmAlias.objects.filter(domain='acme.com').exists())
|
||||
|
||||
def test_get_realm_by_email_domain(self):
|
||||
# type: () -> None
|
||||
realm1, created = do_create_realm('testrealm1', 'Test Realm 1')
|
||||
realm2, created = do_create_realm('testrealm2', 'Test Realm 2')
|
||||
realm3, created = do_create_realm('testrealm3', 'Test Realm 3')
|
||||
|
||||
alias1 = RealmAlias.objects.create(realm=realm1, domain='test1.com', allow_subdomains=True)
|
||||
alias2 = RealmAlias.objects.create(realm=realm2, domain='test2.test1.com', allow_subdomains=False)
|
||||
RealmAlias.objects.create(realm=realm3, domain='test3.test2.test1.com', allow_subdomains=True)
|
||||
|
||||
self.assertEqual(get_realm_by_email_domain('user@zulip.com').string_id, 'zulip')
|
||||
self.assertEqual(get_realm_by_email_domain('user@fakedomain.com'), None)
|
||||
self.assertEqual(get_realm_by_email_domain('user@test1.com').string_id, 'testrealm1')
|
||||
self.assertEqual(get_realm_by_email_domain('user@test2.test1.com').string_id, 'testrealm2')
|
||||
self.assertEqual(get_realm_by_email_domain('user@test3.test2.test1.com').string_id, 'testrealm3')
|
||||
self.assertEqual(get_realm_by_email_domain('user@test2.test1.com').string_id, 'testrealm2')
|
||||
self.assertEqual(get_realm_by_email_domain('user@test2.test2.test1.com').string_id, 'testrealm1')
|
||||
self.assertEqual(get_realm_by_email_domain('user@test1.test3.test2.test1.com').string_id, 'testrealm3')
|
||||
|
||||
do_change_realm_alias(alias1, False)
|
||||
self.assertEqual(get_realm_by_email_domain('user@test1.test1.com'), None)
|
||||
self.assertEqual(get_realm_by_email_domain('user@test1.com').string_id, 'testrealm1')
|
||||
|
||||
do_change_realm_alias(alias2, True)
|
||||
self.assertEqual(get_realm_by_email_domain('user@test2.test1.com').string_id, 'testrealm2')
|
||||
self.assertEqual(get_realm_by_email_domain('user@test2.test2.test1.com').string_id, 'testrealm2')
|
||||
|
||||
with self.settings(REALMS_HAVE_SUBDOMAINS = True), (
|
||||
self.assertRaises(GetRealmByDomainException)):
|
||||
get_realm_by_email_domain('user@zulip.com')
|
||||
|
||||
def test_email_allowed_for_realm(self):
|
||||
# type: () -> None
|
||||
realm1, created = do_create_realm('testrealm1', 'Test Realm 1', restricted_to_domain=True)
|
||||
realm2, created = do_create_realm('testrealm2', 'Test Realm 2', restricted_to_domain=True)
|
||||
|
||||
alias = RealmAlias.objects.create(realm=realm1, domain='test1.com', allow_subdomains=False)
|
||||
RealmAlias.objects.create(realm=realm2, domain='test2.test1.com', allow_subdomains=True)
|
||||
|
||||
self.assertEqual(email_allowed_for_realm('user@test1.com', realm1), True)
|
||||
self.assertEqual(email_allowed_for_realm('user@test2.test1.com', realm1), False)
|
||||
self.assertEqual(email_allowed_for_realm('user@test2.test1.com', realm2), True)
|
||||
self.assertEqual(email_allowed_for_realm('user@test3.test2.test1.com', realm2), True)
|
||||
self.assertEqual(email_allowed_for_realm('user@test3.test1.com', realm2), False)
|
||||
|
||||
do_change_realm_alias(alias, True)
|
||||
self.assertEqual(email_allowed_for_realm('user@test1.com', realm1), True)
|
||||
self.assertEqual(email_allowed_for_realm('user@test2.test1.com', realm1), True)
|
||||
self.assertEqual(email_allowed_for_realm('user@test2.com', realm1), False)
|
||||
|
||||
def test_realm_aliases_uniqueness(self):
|
||||
# type: () -> None
|
||||
realm = get_realm('zulip')
|
||||
with self.settings(REALMS_HAVE_SUBDOMAINS=True), self.assertRaises(IntegrityError):
|
||||
RealmAlias.objects.create(realm=realm, domain='zulip.com', allow_subdomains=True)
|
||||
|
||||
def test_validate_domain(self):
|
||||
# type: () -> None
|
||||
invalid_domains = ['', 'test', 't.', 'test.', '.com', '-test', 'test...com',
|
||||
'test-', 'test_domain.com', 'test.-domain.com']
|
||||
for domain in invalid_domains:
|
||||
with self.assertRaises(ValidationError):
|
||||
validate_domain(domain)
|
||||
|
||||
valid_domains = ['acme.com', 'x-x.y.3.z']
|
||||
for domain in valid_domains:
|
||||
validate_domain(domain)
|
||||
|
|
|
@ -766,6 +766,8 @@ def same_realm_zephyr_user(user_profile, email):
|
|||
|
||||
domain = email_to_domain(email)
|
||||
|
||||
# Assumes allow_subdomains=False for all RealmAlias's corresponding to
|
||||
# these realms.
|
||||
return user_profile.realm.is_zephyr_mirror_realm and \
|
||||
RealmAlias.objects.filter(realm=user_profile.realm, domain=domain).exists()
|
||||
|
||||
|
@ -781,6 +783,8 @@ def same_realm_irc_user(user_profile, email):
|
|||
|
||||
domain = email_to_domain(email).replace("irc.", "")
|
||||
|
||||
# Assumes allow_subdomains=False for all RealmAlias's corresponding to
|
||||
# these realms.
|
||||
return RealmAlias.objects.filter(realm=user_profile.realm, domain=domain).exists()
|
||||
|
||||
def same_realm_jabber_user(user_profile, email):
|
||||
|
@ -794,6 +798,8 @@ def same_realm_jabber_user(user_profile, email):
|
|||
# Zulip users, this is where you would do any translation.
|
||||
domain = email_to_domain(email)
|
||||
|
||||
# Assumes allow_subdomains=False for all RealmAlias's corresponding to
|
||||
# these realms.
|
||||
return RealmAlias.objects.filter(realm=user_profile.realm, domain=domain).exists()
|
||||
|
||||
# We do not @require_login for send_message_backend, since it is used
|
||||
|
|
|
@ -4,12 +4,12 @@ from django.core.exceptions import ValidationError
|
|||
from django.http import HttpRequest, HttpResponse
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from zerver.decorator import has_request_variables, REQ, require_realm_admin
|
||||
from zerver.lib.actions import get_realm_aliases, do_add_realm_alias, \
|
||||
do_remove_realm_alias
|
||||
from zerver.decorator import has_request_variables, require_realm_admin, REQ
|
||||
from zerver.lib.actions import do_add_realm_alias, do_change_realm_alias, \
|
||||
do_remove_realm_alias, get_realm_aliases
|
||||
from zerver.lib.domains import validate_domain
|
||||
from zerver.lib.response import json_error, json_success
|
||||
from zerver.lib.validator import check_string
|
||||
from zerver.lib.validator import check_bool, check_string
|
||||
from zerver.models import can_add_alias, RealmAlias, UserProfile
|
||||
|
||||
from typing import Text
|
||||
|
@ -21,8 +21,8 @@ def list_aliases(request, user_profile):
|
|||
|
||||
@require_realm_admin
|
||||
@has_request_variables
|
||||
def create_alias(request, user_profile, domain=REQ(validator=check_string)):
|
||||
# type: (HttpRequest, UserProfile, Text) -> (HttpResponse)
|
||||
def create_alias(request, user_profile, domain=REQ(validator=check_string), allow_subdomains=REQ(validator=check_bool)):
|
||||
# type: (HttpRequest, UserProfile, Text, bool) -> (HttpResponse)
|
||||
domain = domain.strip().lower()
|
||||
try:
|
||||
validate_domain(domain)
|
||||
|
@ -32,9 +32,20 @@ def create_alias(request, user_profile, domain=REQ(validator=check_string)):
|
|||
return json_error(_("The domain %(domain)s is already a part of your organization.") % {'domain': domain})
|
||||
if not can_add_alias(domain):
|
||||
return json_error(_("The domain %(domain)s belongs to another organization.") % {'domain': domain})
|
||||
alias = do_add_realm_alias(user_profile.realm, domain)
|
||||
alias = do_add_realm_alias(user_profile.realm, domain, allow_subdomains)
|
||||
return json_success({'new_domain': [alias.id, alias.domain]})
|
||||
|
||||
@require_realm_admin
|
||||
@has_request_variables
|
||||
def patch_alias(request, user_profile, domain, allow_subdomains=REQ(validator=check_bool)):
|
||||
# type: (HttpRequest, UserProfile, Text, bool) -> (HttpResponse)
|
||||
try:
|
||||
alias = RealmAlias.objects.get(realm=user_profile.realm, domain=domain)
|
||||
do_change_realm_alias(alias, allow_subdomains)
|
||||
except RealmAlias.DoesNotExist:
|
||||
return json_error(_('No entry found for domain %(domain)s.' % {'domain': domain}))
|
||||
return json_success()
|
||||
|
||||
@require_realm_admin
|
||||
@has_request_variables
|
||||
def delete_alias(request, user_profile, domain):
|
||||
|
|
|
@ -165,12 +165,13 @@ v1_api_and_json_patterns = [
|
|||
# Returns a 204, used by desktop app to verify connectivity status
|
||||
url(r'generate_204$', zerver.views.registration.generate_204, name='zerver.views.registration.generate_204'),
|
||||
|
||||
# realm/aliases -> zerver.views.realm_aliases
|
||||
# realm/domains -> zerver.views.realm_aliases
|
||||
url(r'^realm/domains$', rest_dispatch,
|
||||
{'GET': 'zerver.views.realm_aliases.list_aliases',
|
||||
'POST': 'zerver.views.realm_aliases.create_alias'}),
|
||||
url(r'^realm/domains/(?P<domain>\S+)$', rest_dispatch,
|
||||
{'DELETE': 'zerver.views.realm_aliases.delete_alias'}),
|
||||
{'PATCH': 'zerver.views.realm_aliases.patch_alias',
|
||||
'DELETE': 'zerver.views.realm_aliases.delete_alias'}),
|
||||
|
||||
# realm/emoji -> zerver.views.realm_emoji
|
||||
url(r'^realm/emoji$', rest_dispatch,
|
||||
|
|
Loading…
Reference in New Issue