mirror of https://github.com/zulip/zulip.git
security: Add tooling to nag users if a Zulip server is very old.
This will help ensure that users upgrade their Zulip server. Essentially rewritten by tabbott. Fixes part of #17826.
This commit is contained in:
parent
a2c7f35e5c
commit
8e2042d378
|
@ -80,6 +80,8 @@ export function initialize() {
|
|||
const ls = localstorage();
|
||||
if (page_params.insecure_desktop_app) {
|
||||
open($("[data-process='insecure-desktop-app']"));
|
||||
} else if (page_params.server_needs_upgrade) {
|
||||
open($("[data-process='server-needs-upgrade']"));
|
||||
} else if (page_params.warn_no_email === true && page_params.is_admin) {
|
||||
// if email has not been set up and the user is the admin,
|
||||
// display a warning to tell them to set up an email server.
|
||||
|
|
|
@ -45,6 +45,15 @@
|
|||
</div>
|
||||
<span class="close" data-dismiss="alert" aria-label="{{ _('Close') }}" role="button" tabindex=0>×</span>
|
||||
</div>
|
||||
<div data-process="server-needs-upgrade" class="alert alert-info red">
|
||||
<div data-step="1">
|
||||
{{ _("This Zulip server is running an old version and should be upgraded.") }}
|
||||
<a class="alert-link" href="https://zulip.readthedocs.io/en/latest/production/upgrade-or-modify.html" target="_blank" rel="noopener noreferrer">
|
||||
{{ _("Learn more.") }}
|
||||
</a>
|
||||
</div>
|
||||
<span class="close" data-dismiss="alert" aria-label="{{ _('Close') }}" role="button" tabindex=0>×</span>
|
||||
</div>
|
||||
<div data-process="bankruptcy" class="alert alert-info brankruptcy">
|
||||
<div data-step="1">
|
||||
{% trans count=page_params.unread_msgs.count %}
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
import calendar
|
||||
import datetime
|
||||
import os
|
||||
import time
|
||||
from dataclasses import dataclass
|
||||
from typing import Any, Dict, List, Optional, Tuple
|
||||
|
||||
import pytz
|
||||
from django.conf import settings
|
||||
from django.http import HttpRequest
|
||||
from django.utils import translation
|
||||
from django.utils.timezone import now as timezone_now
|
||||
from two_factor.utils import default_device
|
||||
|
||||
from zerver.lib.events import do_events_register
|
||||
|
@ -35,6 +39,33 @@ class UserPermissionInfo:
|
|||
show_webathena: bool
|
||||
|
||||
|
||||
# LAST_SERVER_UPGRADE_TIME is the last time the server had a version deployed.
|
||||
if settings.PRODUCTION: # nocoverage
|
||||
timestamp = os.path.basename(os.path.abspath(settings.DEPLOY_ROOT))
|
||||
LAST_SERVER_UPGRADE_TIME = datetime.datetime.strptime(timestamp, "%Y-%m-%d-%H-%M-%S").replace(
|
||||
tzinfo=pytz.utc
|
||||
)
|
||||
else:
|
||||
LAST_SERVER_UPGRADE_TIME = timezone_now()
|
||||
|
||||
|
||||
def is_outdated_server(user_profile: Optional[UserProfile]) -> bool:
|
||||
# TODO: We should ideally be using the minimum of this calculation
|
||||
# and the date the release tarball was generated.
|
||||
tzaware_last_upgrade_time = LAST_SERVER_UPGRADE_TIME
|
||||
deadline = tzaware_last_upgrade_time + datetime.timedelta(
|
||||
days=settings.SERVER_UPGRADE_NAG_DEADLINE
|
||||
)
|
||||
|
||||
if user_profile is None or not user_profile.is_realm_admin:
|
||||
# Administrators get warned at the deadline; all users 30 days later.
|
||||
deadline = deadline + datetime.timedelta(days=30)
|
||||
|
||||
if timezone_now() > deadline:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def get_furthest_read_time(user_profile: Optional[UserProfile]) -> Optional[float]:
|
||||
if user_profile is None:
|
||||
return time.time()
|
||||
|
@ -174,6 +205,7 @@ def build_page_params_for_home_page_load(
|
|||
test_suite=settings.TEST_SUITE,
|
||||
poll_timeout=settings.POLL_TIMEOUT,
|
||||
insecure_desktop_app=insecure_desktop_app,
|
||||
server_needs_upgrade=is_outdated_server(user_profile),
|
||||
login_page=settings.HOME_NOT_LOGGED_IN,
|
||||
root_domain_uri=settings.ROOT_DOMAIN_URI,
|
||||
save_stacktraces=settings.SAVE_FRONTEND_STACKTRACES,
|
||||
|
|
|
@ -5,6 +5,7 @@ from typing import Any
|
|||
from unittest.mock import patch
|
||||
|
||||
import orjson
|
||||
import pytz
|
||||
from django.conf import settings
|
||||
from django.http import HttpResponse
|
||||
from django.utils.timezone import now as timezone_now
|
||||
|
@ -17,10 +18,10 @@ from zerver.lib.actions import (
|
|||
do_create_user,
|
||||
)
|
||||
from zerver.lib.events import add_realm_logo_fields
|
||||
from zerver.lib.home import get_furthest_read_time
|
||||
from zerver.lib.home import LAST_SERVER_UPGRADE_TIME, get_furthest_read_time, is_outdated_server
|
||||
from zerver.lib.soft_deactivation import do_soft_deactivate_users
|
||||
from zerver.lib.test_classes import ZulipTestCase
|
||||
from zerver.lib.test_helpers import get_user_messages, queries_captured
|
||||
from zerver.lib.test_helpers import get_user_messages, override_settings, queries_captured
|
||||
from zerver.lib.users import compute_show_invites_and_add_streams
|
||||
from zerver.models import (
|
||||
DefaultStream,
|
||||
|
@ -211,6 +212,7 @@ class HomeTest(ZulipTestCase):
|
|||
"server_inline_image_preview",
|
||||
"server_inline_url_embed_preview",
|
||||
"server_name_changes_disabled",
|
||||
"server_needs_upgrade",
|
||||
"settings_send_digest_emails",
|
||||
"starred_message_counts",
|
||||
"starred_messages",
|
||||
|
@ -874,6 +876,27 @@ class HomeTest(ZulipTestCase):
|
|||
compute_navbar_logo_url(page_params), "/static/images/logo/zulip-org-logo.svg?version=0"
|
||||
)
|
||||
|
||||
@override_settings(SERVER_UPGRADE_NAG_DEADLINE=365)
|
||||
def test_is_outdated_server(self) -> None:
|
||||
# Check when server_upgrade_nag_deadline > last_server_upgrade_time
|
||||
hamlet = self.example_user("hamlet")
|
||||
iago = self.example_user("iago")
|
||||
now = LAST_SERVER_UPGRADE_TIME.replace(tzinfo=pytz.utc)
|
||||
with patch("zerver.lib.home.timezone_now", return_value=now + timedelta(days=10)):
|
||||
self.assertEqual(is_outdated_server(iago), False)
|
||||
self.assertEqual(is_outdated_server(hamlet), False)
|
||||
self.assertEqual(is_outdated_server(None), False)
|
||||
|
||||
with patch("zerver.lib.home.timezone_now", return_value=now + timedelta(days=397)):
|
||||
self.assertEqual(is_outdated_server(iago), True)
|
||||
self.assertEqual(is_outdated_server(hamlet), True)
|
||||
self.assertEqual(is_outdated_server(None), True)
|
||||
|
||||
with patch("zerver.lib.home.timezone_now", return_value=now + timedelta(days=380)):
|
||||
self.assertEqual(is_outdated_server(iago), True)
|
||||
self.assertEqual(is_outdated_server(hamlet), False)
|
||||
self.assertEqual(is_outdated_server(None), False)
|
||||
|
||||
def test_furthest_read_time(self) -> None:
|
||||
msg_id = self.send_test_message("hello!", sender_name="iago")
|
||||
|
||||
|
|
|
@ -441,3 +441,6 @@ NAGIOS_BOT_HOST = EXTERNAL_HOST
|
|||
|
||||
# Use half of the available CPUs for data import purposes.
|
||||
DEFAULT_DATA_EXPORT_IMPORT_PARALLELISM = (len(os.sched_getaffinity(0)) // 2) or 1
|
||||
|
||||
# How long after the last upgrade to nag users that the server is insecure
|
||||
SERVER_UPGRADE_NAG_DEADLINE = 365
|
||||
|
|
Loading…
Reference in New Issue