Add RealmAlias.allow_subdomains to model, frontend, and API.

Includes a database migration.

Fixes #1868.
This commit is contained in:
Harshit Bansal 2017-01-20 23:19:03 -08:00 committed by Tim Abbott
parent a16c48f0c4
commit 7d10cbc32b
15 changed files with 297 additions and 61 deletions

View File

@ -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);
}());

View File

@ -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 () {

View File

@ -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);

View File

@ -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;
}

View File

@ -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>

View File

@ -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}}

View File

@ -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

View File

@ -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)

View File

@ -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')]),
),
]

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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):

View File

@ -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,