mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-03 21:43:21 +00:00 
			
		
		
		
	settings: Add support for Hangouts as the video chat provider.
The only thing that's annoying about this feature is that you need to be a paying G Suite customer to use it.
This commit is contained in:
		@@ -493,6 +493,7 @@ function test_sync_realm_settings() {
 | 
			
		||||
    simulate_auth_methods();
 | 
			
		||||
 | 
			
		||||
    $('#id_realm_create_stream_permission').change = set_callback('realm_create_stream_permission');
 | 
			
		||||
    $('#id_realm_video_chat_provider').change = set_callback('realm_video_chat_provider');
 | 
			
		||||
    $('#id_realm_invite_required').change = set_callback('change_invite_required');
 | 
			
		||||
    $('#id_realm_restricted_to_domain').change = set_callback('id_realm_restricted_to_domain');
 | 
			
		||||
    $('#id_realm_allow_message_editing').change = set_callback('change_message_editing');
 | 
			
		||||
 
 | 
			
		||||
@@ -30,6 +30,7 @@ function _setup_page() {
 | 
			
		||||
    var options = {
 | 
			
		||||
        custom_profile_field_types: page_params.custom_profile_field_types,
 | 
			
		||||
        realm_name: page_params.realm_name,
 | 
			
		||||
        realm_available_video_chat_providers: page_params.realm_available_video_chat_providers,
 | 
			
		||||
        realm_description: page_params.realm_description,
 | 
			
		||||
        realm_restricted_to_domain: page_params.realm_restricted_to_domain,
 | 
			
		||||
        realm_invite_required: page_params.realm_invite_required,
 | 
			
		||||
 
 | 
			
		||||
@@ -924,8 +924,13 @@ exports.initialize = function () {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        var video_call_link;
 | 
			
		||||
        var video_call_id = util.random_int(100000000000000, 999999999999999);
 | 
			
		||||
        var video_call_link = page_params.jitsi_server_url + "/" +  video_call_id;
 | 
			
		||||
        if (page_params.realm_video_chat_provider === "Google Hangouts") {
 | 
			
		||||
            video_call_link = "https://hangouts.google.com/hangouts/_/" + page_params.realm_google_hangouts_domain + "/" + video_call_id;
 | 
			
		||||
        } else {
 | 
			
		||||
            video_call_link = page_params.jitsi_server_url + "/" +  video_call_id;
 | 
			
		||||
        }
 | 
			
		||||
        var video_call_link_text = '[' + _('Click to join video call') + '](' + video_call_link + ')';
 | 
			
		||||
        compose_ui.insert_syntax_and_focus(video_call_link_text);
 | 
			
		||||
    });
 | 
			
		||||
 
 | 
			
		||||
@@ -63,6 +63,7 @@ exports.dispatch_normal_event = function dispatch_normal_event(event) {
 | 
			
		||||
            description: noop,
 | 
			
		||||
            email_changes_disabled: settings_account.update_email_change_display,
 | 
			
		||||
            disallow_disposable_email_addresses: noop,
 | 
			
		||||
            google_hangouts_domain: noop,
 | 
			
		||||
            inline_image_preview: noop,
 | 
			
		||||
            inline_url_embed_preview: noop,
 | 
			
		||||
            invite_by_admins_only: noop,
 | 
			
		||||
@@ -76,6 +77,7 @@ exports.dispatch_normal_event = function dispatch_normal_event(event) {
 | 
			
		||||
            send_welcome_emails: noop,
 | 
			
		||||
            signup_notifications_stream_id: noop,
 | 
			
		||||
            restricted_to_domain: noop,
 | 
			
		||||
            video_chat_provider: noop,
 | 
			
		||||
            waiting_period_threshold: noop,
 | 
			
		||||
        };
 | 
			
		||||
        if (event.op === 'update' && _.has(realm_settings, event.property)) {
 | 
			
		||||
 
 | 
			
		||||
@@ -39,6 +39,14 @@ var org_settings = {
 | 
			
		||||
            type: 'bool',
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
    video_chat: {
 | 
			
		||||
        video_chat_provider: {
 | 
			
		||||
            type: 'text',
 | 
			
		||||
        },
 | 
			
		||||
        google_hangouts_domain: {
 | 
			
		||||
            type: 'text',
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
    user_defaults: {
 | 
			
		||||
        default_language: {
 | 
			
		||||
            type: 'text',
 | 
			
		||||
@@ -136,6 +144,17 @@ function set_add_emoji_permission_dropdown() {
 | 
			
		||||
    $("#id_realm_add_emoji_by_admins_only").val(get_property_value("realm_add_emoji_by_admins_only"));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function set_video_chat_provider_dropdown() {
 | 
			
		||||
    var chat_provider = page_params.realm_video_chat_provider;
 | 
			
		||||
    $("#id_realm_video_chat_provider").val(chat_provider);
 | 
			
		||||
    if (chat_provider === "Google Hangouts") {
 | 
			
		||||
        $("#google_hangouts_domain").show();
 | 
			
		||||
        $("#id_realm_google_hangouts_domain").val(page_params.realm_google_hangouts_domain);
 | 
			
		||||
    } else {
 | 
			
		||||
        $("#google_hangouts_domain").hide();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.populate_realm_domains = function (realm_domains) {
 | 
			
		||||
    if (!meta.loaded) {
 | 
			
		||||
        return;
 | 
			
		||||
@@ -280,6 +299,8 @@ function update_dependent_subsettings(property_name) {
 | 
			
		||||
    } else if (property_name === 'realm_restricted_to_domain') {
 | 
			
		||||
        settings_ui.disable_sub_setting_onchange(page_params.realm_restricted_to_domain,
 | 
			
		||||
            "id_realm_disallow_disposable_email_addresses", false);
 | 
			
		||||
    } else if (property_name === 'realm_video_chat_provider' || property_name === 'realm_google_hangouts_domain') {
 | 
			
		||||
        set_video_chat_provider_dropdown();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -397,6 +418,7 @@ function _set_up() {
 | 
			
		||||
 | 
			
		||||
    set_create_stream_permission_dropdown();
 | 
			
		||||
    set_add_emoji_permission_dropdown();
 | 
			
		||||
    set_video_chat_provider_dropdown();
 | 
			
		||||
 | 
			
		||||
    $("#id_realm_restricted_to_domain").change(function () {
 | 
			
		||||
        settings_ui.disable_sub_setting_onchange(this.checked, "id_realm_disallow_disposable_email_addresses", false);
 | 
			
		||||
@@ -593,6 +615,16 @@ function _set_up() {
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    $("#id_realm_video_chat_provider").change(function (e) {
 | 
			
		||||
        var video_chat_provider = e.target.value;
 | 
			
		||||
        var node = $("#google_hangouts_domain");
 | 
			
		||||
        if (video_chat_provider === "Google Hangouts") {
 | 
			
		||||
            node.show();
 | 
			
		||||
        } else {
 | 
			
		||||
            node.hide();
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    $(".organization form.org-authentications-form").off('submit').on('submit', function (e) {
 | 
			
		||||
        var authentication_methods_status = $("#admin-realm-authentication-methods-status").expectOne();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -91,6 +91,28 @@
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <div id="org-video-chat" class="org-subsection-parent">
 | 
			
		||||
            <div class="subsection-header">
 | 
			
		||||
                <h3>{{t "Video chat provider" }}</h3>
 | 
			
		||||
                {{ partial "settings-save-discard-widget" "section_name" "video-chat" }}
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="inline-block organization-settings-parent">
 | 
			
		||||
                <div class="input-group">
 | 
			
		||||
                    <select name="realm_video_chat_provider" id="id_realm_video_chat_provider">
 | 
			
		||||
                        {{#each realm_available_video_chat_providers}}
 | 
			
		||||
                        <option value='{{this}}'>{{this}}</option>
 | 
			
		||||
                        {{/each}}
 | 
			
		||||
                    </select>
 | 
			
		||||
                    <div id="google_hangouts_domain">
 | 
			
		||||
                        <label>{{t 'Domain for your <a href="https://gsuite.google.com" target="_blank">G Suite team</a> (required)' }}:</label>
 | 
			
		||||
                        <input type="text" id="id_realm_google_hangouts_domain"
 | 
			
		||||
                          name="realm_google_hangouts_domain"
 | 
			
		||||
                          class="admin-realm-google-hangouts-domain"/>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <div id="org-user-defaults" class="org-subsection-parent">
 | 
			
		||||
            <div class="subsection-header">
 | 
			
		||||
                <h3>{{t "Default user settings" }}</h3>
 | 
			
		||||
 
 | 
			
		||||
@@ -235,7 +235,7 @@
 | 
			
		||||
            <h3>VIDEO CALLS</h3>
 | 
			
		||||
            <p>
 | 
			
		||||
                Create and join video calls with a single click. Powered
 | 
			
		||||
                by Jitsi.
 | 
			
		||||
                by your choice of Jitsi or Google Hangouts.
 | 
			
		||||
            </p>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="feature-block">
 | 
			
		||||
 
 | 
			
		||||
@@ -168,6 +168,7 @@ def fetch_initial_state_data(user_profile: UserProfile,
 | 
			
		||||
        state['max_icon_file_size'] = settings.MAX_ICON_FILE_SIZE
 | 
			
		||||
        state['realm_bot_domain'] = realm.get_bot_domain()
 | 
			
		||||
        state['realm_uri'] = realm.uri
 | 
			
		||||
        state['realm_available_video_chat_providers'] = realm.VIDEO_CHAT_PROVIDERS
 | 
			
		||||
        state['realm_presence_disabled'] = realm.presence_disabled
 | 
			
		||||
        state['realm_show_digest_email'] = realm.show_digest_email and settings.SEND_DIGEST_EMAILS
 | 
			
		||||
        state['realm_is_zephyr_mirror_realm'] = realm.is_zephyr_mirror_realm
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										20
									
								
								zerver/migrations/0159_realm_google_hangouts_domain.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								zerver/migrations/0159_realm_google_hangouts_domain.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
# Generated by Django 1.11.11 on 2018-04-23 16:37
 | 
			
		||||
from __future__ import unicode_literals
 | 
			
		||||
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ('zerver', '0158_realm_video_chat_provider'),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.AddField(
 | 
			
		||||
            model_name='realm',
 | 
			
		||||
            name='google_hangouts_domain',
 | 
			
		||||
            field=models.TextField(default=''),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
@@ -139,6 +139,7 @@ class Realm(models.Model):
 | 
			
		||||
    MAX_REALM_NAME_LENGTH = 40
 | 
			
		||||
    MAX_REALM_SUBDOMAIN_LENGTH = 40
 | 
			
		||||
    MAX_VIDEO_CHAT_PROVIDER_LENGTH = 40
 | 
			
		||||
    MAX_GOOGLE_HANGOUTS_DOMAIN_LENGTH = 255  # This is just the maximum domain length by RFC
 | 
			
		||||
    VIDEO_CHAT_PROVIDERS = [u"Jitsi", u"Google Hangouts"]
 | 
			
		||||
    AUTHENTICATION_FLAGS = [u'Google', u'Email', u'GitHub', u'LDAP', u'Dev', u'RemoteUser']
 | 
			
		||||
    SUBDOMAIN_FOR_ROOT_DOMAIN = ''
 | 
			
		||||
@@ -194,6 +195,7 @@ class Realm(models.Model):
 | 
			
		||||
    # See upload_quota_bytes; don't interpret upload_quota_gb directly.
 | 
			
		||||
    upload_quota_gb = models.IntegerField(null=True)  # type: Optional[int]
 | 
			
		||||
    video_chat_provider = models.CharField(default=u"Jitsi", max_length=MAX_VIDEO_CHAT_PROVIDER_LENGTH)
 | 
			
		||||
    google_hangouts_domain = models.TextField(default="")
 | 
			
		||||
 | 
			
		||||
    # Define the types of the various automatically managed properties
 | 
			
		||||
    property_types = dict(
 | 
			
		||||
@@ -207,6 +209,7 @@ class Realm(models.Model):
 | 
			
		||||
        description=Text,
 | 
			
		||||
        disallow_disposable_email_addresses=bool,
 | 
			
		||||
        email_changes_disabled=bool,
 | 
			
		||||
        google_hangouts_domain=Text,
 | 
			
		||||
        invite_required=bool,
 | 
			
		||||
        invite_by_admins_only=bool,
 | 
			
		||||
        inline_image_preview=bool,
 | 
			
		||||
@@ -217,6 +220,7 @@ class Realm(models.Model):
 | 
			
		||||
        name_changes_disabled=bool,
 | 
			
		||||
        restricted_to_domain=bool,
 | 
			
		||||
        send_welcome_emails=bool,
 | 
			
		||||
        video_chat_provider=Text,
 | 
			
		||||
        waiting_period_threshold=int,
 | 
			
		||||
    )  # type: Dict[str, Union[type, Tuple[type, ...]]]
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1250,6 +1250,8 @@ class EventsRegisterTest(ZulipTestCase):
 | 
			
		||||
            name=[u'Zulip', u'New Name'],
 | 
			
		||||
            waiting_period_threshold=[10, 20],
 | 
			
		||||
            bot_creation_policy=[Realm.BOT_CREATION_EVERYONE],
 | 
			
		||||
            video_chat_provider=[u'Google Hangouts', u'Jitsi'],
 | 
			
		||||
            google_hangouts_domain=[u"zulip.com", u"zulip.org"],
 | 
			
		||||
        )  # type: Dict[str, Any]
 | 
			
		||||
 | 
			
		||||
        vals = test_values.get(name)
 | 
			
		||||
 
 | 
			
		||||
@@ -112,6 +112,7 @@ class HomeTest(ZulipTestCase):
 | 
			
		||||
            "realm_allow_message_deleting",
 | 
			
		||||
            "realm_allow_message_editing",
 | 
			
		||||
            "realm_authentication_methods",
 | 
			
		||||
            "realm_available_video_chat_providers",
 | 
			
		||||
            "realm_bot_creation_policy",
 | 
			
		||||
            "realm_bot_domain",
 | 
			
		||||
            "realm_bots",
 | 
			
		||||
@@ -128,6 +129,7 @@ class HomeTest(ZulipTestCase):
 | 
			
		||||
            "realm_embedded_bots",
 | 
			
		||||
            "realm_emoji",
 | 
			
		||||
            "realm_filters",
 | 
			
		||||
            "realm_google_hangouts_domain",
 | 
			
		||||
            "realm_icon_source",
 | 
			
		||||
            "realm_icon_url",
 | 
			
		||||
            "realm_inline_image_preview",
 | 
			
		||||
@@ -152,6 +154,7 @@ class HomeTest(ZulipTestCase):
 | 
			
		||||
            "realm_uri",
 | 
			
		||||
            "realm_user_groups",
 | 
			
		||||
            "realm_users",
 | 
			
		||||
            "realm_video_chat_provider",
 | 
			
		||||
            "realm_waiting_period_threshold",
 | 
			
		||||
            "root_domain_uri",
 | 
			
		||||
            "save_stacktraces",
 | 
			
		||||
 
 | 
			
		||||
@@ -305,6 +305,34 @@ class RealmTest(ZulipTestCase):
 | 
			
		||||
        result = self.client_patch('/json/realm', req)
 | 
			
		||||
        self.assert_json_error(result, 'Invalid bot creation policy')
 | 
			
		||||
 | 
			
		||||
    def test_change_video_chat_provider(self) -> None:
 | 
			
		||||
        self.assertEqual(get_realm('zulip').video_chat_provider, "Jitsi")
 | 
			
		||||
        email = self.example_email("iago")
 | 
			
		||||
        self.login(email)
 | 
			
		||||
 | 
			
		||||
        req = {"video_chat_provider": ujson.dumps("Google Hangouts")}
 | 
			
		||||
        result = self.client_patch('/json/realm', req)
 | 
			
		||||
        self.assert_json_error(result, "Invalid domain: Domain can't be empty.")
 | 
			
		||||
 | 
			
		||||
        req = {
 | 
			
		||||
            "video_chat_provider": ujson.dumps("Google Hangouts"),
 | 
			
		||||
            "google_hangouts_domain": ujson.dumps("invaliddomain"),
 | 
			
		||||
        }
 | 
			
		||||
        result = self.client_patch('/json/realm', req)
 | 
			
		||||
        self.assert_json_error(result, "Invalid domain: Domain must have at least one dot (.)")
 | 
			
		||||
 | 
			
		||||
        req = {
 | 
			
		||||
            "video_chat_provider": ujson.dumps("Google Hangouts"),
 | 
			
		||||
            "google_hangouts_domain": ujson.dumps("zulip.com"),
 | 
			
		||||
        }
 | 
			
		||||
        result = self.client_patch('/json/realm', req)
 | 
			
		||||
        self.assert_json_success(result)
 | 
			
		||||
        self.assertEqual(get_realm('zulip').video_chat_provider, "Google Hangouts")
 | 
			
		||||
 | 
			
		||||
        req = {"video_chat_provider": ujson.dumps("Jitsi")}
 | 
			
		||||
        result = self.client_patch('/json/realm', req)
 | 
			
		||||
        self.assert_json_success(result)
 | 
			
		||||
        self.assertEqual(get_realm('zulip').video_chat_provider, "Jitsi")
 | 
			
		||||
 | 
			
		||||
class RealmAPITest(ZulipTestCase):
 | 
			
		||||
 | 
			
		||||
@@ -340,6 +368,8 @@ class RealmAPITest(ZulipTestCase):
 | 
			
		||||
            name=[u'Zulip', u'New Name'],
 | 
			
		||||
            waiting_period_threshold=[10, 20],
 | 
			
		||||
            bot_creation_policy=[1, 2],
 | 
			
		||||
            video_chat_provider=[u'Jitsi', u'Hangouts'],
 | 
			
		||||
            google_hangouts_domain=[u'zulip.com', u'zulip.org'],
 | 
			
		||||
        )  # type: Dict[str, Any]
 | 
			
		||||
        vals = test_values.get(name)
 | 
			
		||||
        if Realm.property_types[name] is bool:
 | 
			
		||||
 
 | 
			
		||||
@@ -20,6 +20,7 @@ from zerver.lib.request import has_request_variables, REQ, JsonableError
 | 
			
		||||
from zerver.lib.response import json_success, json_error
 | 
			
		||||
from zerver.lib.validator import check_string, check_dict, check_bool, check_int
 | 
			
		||||
from zerver.lib.streams import access_stream_by_id
 | 
			
		||||
from zerver.lib.domains import validate_domain
 | 
			
		||||
from zerver.models import Realm, UserProfile
 | 
			
		||||
from zerver.forms import check_subdomain_available as check_subdomain
 | 
			
		||||
 | 
			
		||||
@@ -54,6 +55,8 @@ def update_realm(
 | 
			
		||||
        send_welcome_emails: Optional[bool]=REQ(validator=check_bool, default=None),
 | 
			
		||||
        bot_creation_policy: Optional[int]=REQ(converter=to_not_negative_int_or_none, default=None),
 | 
			
		||||
        default_twenty_four_hour_time: Optional[bool]=REQ(validator=check_bool, default=None),
 | 
			
		||||
        video_chat_provider: Optional[Text]=REQ(validator=check_string, default=None),
 | 
			
		||||
        google_hangouts_domain: Optional[Text]=REQ(validator=check_string, default=None)
 | 
			
		||||
) -> HttpResponse:
 | 
			
		||||
    realm = user_profile.realm
 | 
			
		||||
 | 
			
		||||
@@ -67,6 +70,11 @@ def update_realm(
 | 
			
		||||
        return json_error(_("Organization name is too long."))
 | 
			
		||||
    if authentication_methods is not None and True not in list(authentication_methods.values()):
 | 
			
		||||
        return json_error(_("At least one authentication method must be enabled."))
 | 
			
		||||
    if video_chat_provider == "Google Hangouts":
 | 
			
		||||
        try:
 | 
			
		||||
            validate_domain(google_hangouts_domain)
 | 
			
		||||
        except ValidationError as e:
 | 
			
		||||
            return json_error(_('Invalid domain: {}').format(e.messages[0]))
 | 
			
		||||
 | 
			
		||||
    # Additional validation of permissions values to add new bot
 | 
			
		||||
    if bot_creation_policy is not None and bot_creation_policy not in Realm.BOT_CREATION_POLICY_TYPES:
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user