realm: Remove Google Hangouts integration.

Google  has removed the Google Hangouts brand, thus we are removing
them as video chat provider option.
This commit removes Google Hangouts integration and make a migration
that sets all realms that are using Hangouts as their video chat
provider to the default, jitsi.

With changes by tabbott to improve the overall video call documentation.

Fixes: #15298.
This commit is contained in:
Clara Dantas
2020-06-14 18:36:14 -03:00
committed by Tim Abbott
parent f4ac4be851
commit ddbde66af5
17 changed files with 64 additions and 121 deletions

View File

@@ -943,10 +943,6 @@ run_test('initialize', () => {
id: 1, id: 1,
name: "Jitsi Meet", name: "Jitsi Meet",
}, },
google_hangouts: {
id: 2,
name: "Google Hangouts",
},
zoom: { zoom: {
id: 3, id: 3,
name: "Zoom", name: "Zoom",
@@ -1447,15 +1443,6 @@ run_test('on_events', () => {
handler(ev); handler(ev);
assert(!called); assert(!called);
page_params.realm_video_chat_provider =
page_params.realm_available_video_chat_providers.google_hangouts.id;
page_params.realm_google_hangouts_domain = 'zulip';
handler(ev);
video_link_regex = /\[Click to join video call\]\(https:\/\/hangouts.google.com\/hangouts\/\_\/zulip\/\d{15}\)/;
assert(video_link_regex.test(syntax_to_insert));
page_params.realm_video_chat_provider = page_params.realm_video_chat_provider =
page_params.realm_available_video_chat_providers.zoom.id; page_params.realm_available_video_chat_providers.zoom.id;
@@ -1735,11 +1722,4 @@ run_test('test_video_chat_button_toggle', () => {
page_params.jitsi_server_url = 'https://meet.jit.si'; page_params.jitsi_server_url = 'https://meet.jit.si';
compose.initialize(); compose.initialize();
assert.equal($("#below-compose-content .video_link").visible(), true); assert.equal($("#below-compose-content .video_link").visible(), true);
reset_jquery();
stub_out_video_calls();
page_params.realm_video_chat_provider =
page_params.realm_available_video_chat_providers.google_hangouts.id;
compose.initialize();
assert.equal($("#below-compose-content .video_link").visible(), true);
}); });

View File

@@ -755,10 +755,6 @@ run_test('set_up', () => {
id: 1, id: 1,
name: "Jitsi Meet", name: "Jitsi Meet",
}, },
google_hangouts: {
id: 2,
name: "Google Hangouts",
},
zoom: { zoom: {
id: 3, id: 3,
name: "Zoom", name: "Zoom",

View File

@@ -1083,10 +1083,7 @@ exports.initialize = function () {
return; return;
} }
if (page_params.realm_video_chat_provider === available_providers.google_hangouts.id) { if (available_providers.zoom
video_call_link = "https://hangouts.google.com/hangouts/_/" + page_params.realm_google_hangouts_domain + "/" + video_call_id;
insert_video_call_url(video_call_link, target_textarea);
} else if (available_providers.zoom
&& page_params.realm_video_chat_provider === available_providers.zoom.id) { && page_params.realm_video_chat_provider === available_providers.zoom.id) {
exports.abort_zoom(edit_message_id); exports.abort_zoom(edit_message_id);
const key = edit_message_id || ""; const key = edit_message_id || "";

View File

@@ -115,7 +115,6 @@ exports.dispatch_normal_event = function dispatch_normal_event(event) {
email_address_visibility: noop, email_address_visibility: noop,
email_changes_disabled: settings_account.update_email_change_display, email_changes_disabled: settings_account.update_email_change_display,
disallow_disposable_email_addresses: noop, disallow_disposable_email_addresses: noop,
google_hangouts_domain: noop,
inline_image_preview: noop, inline_image_preview: noop,
inline_url_embed_preview: noop, inline_url_embed_preview: noop,
invite_by_admins_only: noop, invite_by_admins_only: noop,

View File

@@ -213,15 +213,7 @@ function set_realm_waiting_period_dropdown() {
function set_video_chat_provider_dropdown() { function set_video_chat_provider_dropdown() {
const chat_provider_id = page_params.realm_video_chat_provider; const chat_provider_id = page_params.realm_video_chat_provider;
const available_providers = page_params.realm_available_video_chat_providers;
$("#id_realm_video_chat_provider").val(chat_provider_id); $("#id_realm_video_chat_provider").val(chat_provider_id);
if (chat_provider_id === available_providers.google_hangouts.id) {
$("#google_hangouts_domain").show();
$("#id_realm_google_hangouts_domain").val(page_params.realm_google_hangouts_domain);
} else {
$("#google_hangouts_domain").hide();
}
} }
function set_msg_edit_limit_dropdown() { function set_msg_edit_limit_dropdown() {
@@ -335,7 +327,6 @@ function update_dependent_subsettings(property_name) {
} else if (property_name === 'realm_waiting_period_threshold') { } else if (property_name === 'realm_waiting_period_threshold') {
set_realm_waiting_period_dropdown(); set_realm_waiting_period_dropdown();
} else if (property_name === 'realm_video_chat_provider' || } else if (property_name === 'realm_video_chat_provider' ||
property_name === 'realm_google_hangouts_domain' ||
property_name.startsWith('realm_zoom')) { property_name.startsWith('realm_zoom')) {
set_video_chat_provider_dropdown(); set_video_chat_provider_dropdown();
} else if (property_name === 'realm_msg_edit_limit_setting' || } else if (property_name === 'realm_msg_edit_limit_setting' ||
@@ -838,17 +829,6 @@ exports.build_page = function () {
waiting_period_threshold === 'custom_days'); waiting_period_threshold === 'custom_days');
}); });
$("#id_realm_video_chat_provider").change(function (e) {
const available_providers = page_params.realm_available_video_chat_providers;
const video_chat_provider_id = parseInt(e.target.value, 10);
if (video_chat_provider_id === available_providers.google_hangouts.id) {
$("#google_hangouts_domain").show();
} else {
$("#google_hangouts_domain").hide();
}
});
$("#id_realm_org_join_restrictions").change(function (e) { $("#id_realm_org_join_restrictions").change(function (e) {
const org_join_restrictions = e.target.value; const org_join_restrictions = e.target.value;
const node = $("#allowed_domains_label").parent(); const node = $("#allowed_domains_label").parent();

View File

@@ -631,7 +631,6 @@ input[type=checkbox] {
} }
} }
#google_hangouts_domain,
.organization-settings-parent div:first-of-type { .organization-settings-parent div:first-of-type {
margin-top: 10px; margin-top: 10px;
} }

View File

@@ -191,14 +191,6 @@
<option value='{{this.id}}'>{{this.name}}</option> <option value='{{this.id}}'>{{this.name}}</option>
{{/each}} {{/each}}
</select> </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"
autocomplete="off"
class="admin-realm-google-hangouts-domain setting-widget prop-element"
data-setting-widget-type="string"/>
</div>
</div> </div>
{{> dropdown_list_widget {{> dropdown_list_widget

View File

@@ -238,7 +238,7 @@
<h3>VIDEO CALLS</h3> <h3>VIDEO CALLS</h3>
<p> <p>
Create and join video calls with a single click. Powered Create and join video calls with a single click. Powered
by your choice of Zoom, Jitsi Meet, or Google Hangouts. by your choice of Jitsi Meet or Zoom.
</p> </p>
</a> </a>
<a class="feature-block" href="/help/configure-authentication-methods" target="_blank"> <a class="feature-block" href="/help/configure-authentication-methods" target="_blank">

View File

@@ -25,25 +25,23 @@ By default, Zulip integrates with
source video conferencing solution. Organization administrators can also source video conferencing solution. Organization administrators can also
change the organization's video chat provider. change the organization's video chat provider.
Note that the Google Hangouts integration requires a paid Google G
Suite account.
### Change your organization's video chat provider ### Change your organization's video chat provider
{start_tabs} {start_tabs}
{tab|google-hangouts} {tab|jitsi-meet}
{settings_tab|organization-settings} Zulip's default video chat provider is [Jitsi
Meet](https://meet.jit.si/).
1. Under **Other settings** set **Video chat provider** to **Google Hangouts**. You can also use Zulip with Jitsi Meet on-premise; to configure this,
just set `JITSI_SERVER_URL` in `/etc/zulip/settings.py`.
1. Enter the domain for your [G Suite team](https://gsuite.google.com/).
1. Click **Save changes**.
{tab|zoom} {tab|zoom}
Zulip supports Zoom as the video chat provider using an OAuth
integration. You can set it up as follows:
{settings_tab|organization-settings} {settings_tab|organization-settings}
1. Under **Other settings** set **Video chat provider** to **Zoom**. 1. Under **Other settings** set **Video chat provider** to **Zoom**.
@@ -61,12 +59,14 @@ If you would like to unlink Zoom from your Zulip account:
1. Click the **Uninstall** button next to the Zulip app. 1. Click the **Uninstall** button next to the Zulip app.
{tab|jitsi-on-premise} If you are self-hosting, you will need to [create a Zoom
application][zoom-configuration] to use this integration.
If you're running both Zulip and Jitsi Meet on-premise, just set {tab|disable}
`JITSI_SERVER_URL` in `/etc/zulip/settings.py`.
You can also disable the video call button for your community by You can also disable the video call button for your organization by
setting the provider to "None". setting the provider to "None".
{end_tabs} {end_tabs}
[zoom-configuration]: https://zulip.readthedocs.io/en/latest/production/zoom-configuration.html

View File

@@ -65,9 +65,9 @@ TAB_DISPLAY_NAMES = {
'allow-anyone-to-join': 'Allow anyone to join', 'allow-anyone-to-join': 'Allow anyone to join',
'restrict-by-email-domain': 'Restrict by email domain', 'restrict-by-email-domain': 'Restrict by email domain',
'google-hangouts': 'Google Hangouts',
'zoom': 'Zoom (experimental)', 'zoom': 'Zoom (experimental)',
'jitsi-on-premise': 'Jitsi on-premise', 'jitsi-meet': 'Jitsi Meet',
'disable': 'Disabled',
'chrome': 'Chrome', 'chrome': 'Chrome',
'firefox': 'Firefox', 'firefox': 'Firefox',

View File

@@ -510,8 +510,6 @@ HUBOT_INTEGRATIONS: List[HubotIntegration] = [
HubotIntegration('chartbeat', ['marketing'], display_name='Chartbeat'), HubotIntegration('chartbeat', ['marketing'], display_name='Chartbeat'),
HubotIntegration('darksky', ['misc'], display_name='Dark Sky', HubotIntegration('darksky', ['misc'], display_name='Dark Sky',
logo_alt='Dark Sky logo'), logo_alt='Dark Sky logo'),
HubotIntegration('google-hangouts', ['communication'], display_name='Google Hangouts',
logo_alt='Google Hangouts logo'),
HubotIntegration('instagram', ['misc'], display_name='Instagram', HubotIntegration('instagram', ['misc'], display_name='Instagram',
# _ needed to get around adblock plus # _ needed to get around adblock plus
logo='images/integrations/logos/instagra_m.svg'), logo='images/integrations/logos/instagra_m.svg'),

View File

@@ -0,0 +1,43 @@
# Generated by Django 2.2.13 on 2020-06-14 01:58
from django.db import migrations
from django.db.backends.postgresql.schema import DatabaseSchemaEditor
from django.db.migrations.state import StateApps
VIDEO_CHAT_PROVIDERS = {
'jitsi_meet': {
'name': "Jitsi Meet",
'id': 1,
},
'google_hangouts': {
'name': "Google Hangouts",
'id': 2,
},
}
def remove_google_hangouts_provider(apps: StateApps, schema_editor: DatabaseSchemaEditor) -> None:
# We are removing the Google Hangout integration because Google has
# removed the Hangouts brand. All the realms that used Hangouts as
# their video chat provided are now setted to the default, jitsi.
Realm = apps.get_model('zerver', 'Realm')
Realm.objects.filter(video_chat_provider=VIDEO_CHAT_PROVIDERS['google_hangouts']['id']).update(
video_chat_provider=VIDEO_CHAT_PROVIDERS['jitsi_meet']['id']
)
class Migration(migrations.Migration):
dependencies = [
('zerver', '0284_convert_realm_admins_to_realm_owners'),
]
operations = [
migrations.RemoveField(
model_name='realm',
name='google_hangouts_domain',
),
migrations.RunPython(
remove_google_hangouts_provider,
reverse_code=migrations.RunPython.noop,
elidable=True
),
]

View File

@@ -168,7 +168,7 @@ def clear_supported_auth_backends_cache() -> None:
class Realm(models.Model): class Realm(models.Model):
MAX_REALM_NAME_LENGTH = 40 MAX_REALM_NAME_LENGTH = 40
MAX_REALM_SUBDOMAIN_LENGTH = 40 MAX_REALM_SUBDOMAIN_LENGTH = 40
MAX_GOOGLE_HANGOUTS_DOMAIN_LENGTH = 255 # This is just the maximum domain length by RFC
INVITES_STANDARD_REALM_DAILY_MAX = 3000 INVITES_STANDARD_REALM_DAILY_MAX = 3000
MESSAGE_VISIBILITY_LIMITED = 10000 MESSAGE_VISIBILITY_LIMITED = 10000
AUTHENTICATION_FLAGS = ['Google', 'Email', 'GitHub', 'LDAP', 'Dev', AUTHENTICATION_FLAGS = ['Google', 'Email', 'GitHub', 'LDAP', 'Dev',
@@ -358,10 +358,8 @@ class Realm(models.Model):
'name': "Jitsi Meet", 'name': "Jitsi Meet",
'id': 1, 'id': 1,
}, },
'google_hangouts': { # ID 2 was used for the now-deleted Google Hangouts.
'name': "Google Hangouts", # ID 3 reserved for optional Zoom, see below.
'id': 2,
},
} }
if settings.VIDEO_ZOOM_CLIENT_ID is not None and settings.VIDEO_ZOOM_CLIENT_SECRET is not None: if settings.VIDEO_ZOOM_CLIENT_ID is not None and settings.VIDEO_ZOOM_CLIENT_SECRET is not None:
VIDEO_CHAT_PROVIDERS['zoom'] = { VIDEO_CHAT_PROVIDERS['zoom'] = {
@@ -369,7 +367,6 @@ class Realm(models.Model):
'id': 3, 'id': 3,
} }
video_chat_provider = models.PositiveSmallIntegerField(default=VIDEO_CHAT_PROVIDERS['jitsi_meet']['id']) video_chat_provider = models.PositiveSmallIntegerField(default=VIDEO_CHAT_PROVIDERS['jitsi_meet']['id'])
google_hangouts_domain = models.TextField(default="")
default_code_block_language: Optional[str] = models.TextField(null=True, default=None) default_code_block_language: Optional[str] = models.TextField(null=True, default=None)
@@ -388,7 +385,6 @@ class Realm(models.Model):
disallow_disposable_email_addresses=bool, disallow_disposable_email_addresses=bool,
email_address_visibility=int, email_address_visibility=int,
email_changes_disabled=bool, email_changes_disabled=bool,
google_hangouts_domain=str,
invite_required=bool, invite_required=bool,
invite_by_admins_only=bool, invite_by_admins_only=bool,
inline_image_preview=bool, inline_image_preview=bool,

View File

@@ -1649,9 +1649,7 @@ class EventsRegisterTest(ZulipTestCase):
bot_creation_policy=[Realm.BOT_CREATION_EVERYONE], bot_creation_policy=[Realm.BOT_CREATION_EVERYONE],
video_chat_provider=[ video_chat_provider=[
Realm.VIDEO_CHAT_PROVIDERS['jitsi_meet']['id'], Realm.VIDEO_CHAT_PROVIDERS['jitsi_meet']['id'],
Realm.VIDEO_CHAT_PROVIDERS['google_hangouts']['id'],
], ],
google_hangouts_domain=["zulip.com", "zulip.org"],
default_code_block_language=['python', 'javascript'], default_code_block_language=['python', 'javascript'],
) )

View File

@@ -159,7 +159,6 @@ class HomeTest(ZulipTestCase):
"realm_embedded_bots", "realm_embedded_bots",
"realm_emoji", "realm_emoji",
"realm_filters", "realm_filters",
"realm_google_hangouts_domain",
"realm_icon_source", "realm_icon_source",
"realm_icon_url", "realm_icon_url",
"realm_incoming_webhook_bots", "realm_incoming_webhook_bots",

View File

@@ -551,26 +551,6 @@ class RealmTest(ZulipTestCase):
self.assertEqual(get_realm('zulip').video_chat_provider, self.assertEqual(get_realm('zulip').video_chat_provider,
Realm.VIDEO_CHAT_PROVIDERS['disabled']['id']) Realm.VIDEO_CHAT_PROVIDERS['disabled']['id'])
req = {"video_chat_provider": ujson.dumps(Realm.VIDEO_CHAT_PROVIDERS['google_hangouts']['id'])}
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(Realm.VIDEO_CHAT_PROVIDERS['google_hangouts']['id']),
"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(Realm.VIDEO_CHAT_PROVIDERS['google_hangouts']['id']),
"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,
Realm.VIDEO_CHAT_PROVIDERS['google_hangouts']['id'])
req = {"video_chat_provider": ujson.dumps(Realm.VIDEO_CHAT_PROVIDERS['jitsi_meet']['id'])} req = {"video_chat_provider": ujson.dumps(Realm.VIDEO_CHAT_PROVIDERS['jitsi_meet']['id'])}
result = self.client_patch('/json/realm', req) result = self.client_patch('/json/realm', req)
self.assert_json_success(result) self.assert_json_success(result)
@@ -721,15 +701,10 @@ class RealmAPITest(ZulipTestCase):
Realm.EMAIL_ADDRESS_VISIBILITY_ADMINS, Realm.EMAIL_ADDRESS_VISIBILITY_ADMINS,
Realm.EMAIL_ADDRESS_VISIBILITY_NOBODY], Realm.EMAIL_ADDRESS_VISIBILITY_NOBODY],
video_chat_provider=[ video_chat_provider=[
dict(
video_chat_provider=ujson.dumps(Realm.VIDEO_CHAT_PROVIDERS['google_hangouts']['id']),
google_hangouts_domain=ujson.dumps('zulip.com'),
),
dict( dict(
video_chat_provider=ujson.dumps(Realm.VIDEO_CHAT_PROVIDERS['jitsi_meet']['id']), video_chat_provider=ujson.dumps(Realm.VIDEO_CHAT_PROVIDERS['jitsi_meet']['id']),
), ),
], ],
google_hangouts_domain=['zulip.com', 'zulip.org'],
) )
vals = test_values.get(name) vals = test_values.get(name)
@@ -740,8 +715,6 @@ class RealmAPITest(ZulipTestCase):
if name == 'video_chat_provider': if name == 'video_chat_provider':
self.set_up_db(name, vals[0][name]) self.set_up_db(name, vals[0][name])
realm = self.update_with_api_multiple_value(vals[1])
self.assertEqual(getattr(realm, name), ujson.loads(vals[1][name]))
realm = self.update_with_api_multiple_value(vals[0]) realm = self.update_with_api_multiple_value(vals[0])
self.assertEqual(getattr(realm, name), ujson.loads(vals[0][name])) self.assertEqual(getattr(realm, name), ujson.loads(vals[0][name]))
else: else:

View File

@@ -19,7 +19,6 @@ from zerver.lib.actions import (
do_set_realm_property, do_set_realm_property,
do_set_realm_signup_notifications_stream, do_set_realm_signup_notifications_stream,
) )
from zerver.lib.domains import validate_domain
from zerver.lib.exceptions import OrganizationOwnerRequired from zerver.lib.exceptions import OrganizationOwnerRequired
from zerver.lib.i18n import get_available_language_codes from zerver.lib.i18n import get_available_language_codes
from zerver.lib.request import REQ, JsonableError, has_request_variables from zerver.lib.request import REQ, JsonableError, has_request_variables
@@ -85,7 +84,6 @@ def update_realm(
Realm.EMAIL_ADDRESS_VISIBILITY_TYPES), default=None), Realm.EMAIL_ADDRESS_VISIBILITY_TYPES), default=None),
default_twenty_four_hour_time: Optional[bool]=REQ(validator=check_bool, default=None), default_twenty_four_hour_time: Optional[bool]=REQ(validator=check_bool, default=None),
video_chat_provider: Optional[int]=REQ(validator=check_int, default=None), video_chat_provider: Optional[int]=REQ(validator=check_int, default=None),
google_hangouts_domain: Optional[str]=REQ(validator=check_string, default=None),
default_code_block_language: Optional[str]=REQ(validator=check_string, default=None), default_code_block_language: Optional[str]=REQ(validator=check_string, default=None),
digest_weekday: Optional[int]=REQ(validator=check_int_in(Realm.DIGEST_WEEKDAY_VALUES), default=None), digest_weekday: Optional[int]=REQ(validator=check_int_in(Realm.DIGEST_WEEKDAY_VALUES), default=None),
) -> HttpResponse: ) -> HttpResponse:
@@ -107,11 +105,6 @@ def update_realm(
if (video_chat_provider is not None and if (video_chat_provider is not None and
video_chat_provider not in {p['id'] for p in Realm.VIDEO_CHAT_PROVIDERS.values()}): video_chat_provider not in {p['id'] for p in Realm.VIDEO_CHAT_PROVIDERS.values()}):
return json_error(_("Invalid video_chat_provider {}").format(video_chat_provider)) return json_error(_("Invalid video_chat_provider {}").format(video_chat_provider))
if video_chat_provider == Realm.VIDEO_CHAT_PROVIDERS['google_hangouts']['id']:
try:
validate_domain(google_hangouts_domain)
except ValidationError as e:
return json_error(_('Invalid domain: {}').format(e.messages[0]))
if message_retention_days is not None: if message_retention_days is not None:
if not user_profile.is_realm_owner: if not user_profile.is_realm_owner: