settings: Make INVITATION_LINK_VALIDITY_MINUTES optional.

Type inference does not work when the default value of `REQ` is
non-optional while `ResultT` is optional. Mypy tries to unify
`json_validator` with `Validator[int]` in `invite_users_backend` instead
of the desired `Validator[Optional[int]]` because of the presence of the
default value `settings.INVITATION_LINK_VALIDITY_MINUTES`, which is
inferred to be an `int`. Mypy does not resort to a less specific type but
instead gives up early.

This issue applies to invite_users_backend and generate_multiuse_invite_backend
in zerver.views.invite.

There might be a way that we can add an overload to get around this, but
it's probably not worth the complexity until it comes up again more frequently.

We do in fact allow `invite_expires_in_minutes` to be `None` in places
like `do_invite_users`, `invite_users_backend`, etc, and we have
`settings.INVITATION_LINK_VALIDITY_MINUTES` as the default for them. So
it makes sense to allow having an optional value for this setting. And
since there isn't a way to independently set the value of this constant,
we move it to a different place.

TODO:

This is a temporary fix that should be refactored when the bug is fixed.

The encountered mypy issue: https://github.com/python/mypy/issues/13234

Signed-off-by: Zixuan James Li <p359101898@gmail.com>
This commit is contained in:
Zixuan James Li 2022-07-19 16:59:47 -04:00 committed by Tim Abbott
parent b17affc3da
commit fe9ed2e69d
4 changed files with 12 additions and 9 deletions

View File

@ -111,7 +111,7 @@ from zerver.models import (
)
from zerver.views.auth import redirect_and_log_into_subdomain, start_two_factor_auth
from zerver.views.development.registration import confirmation_key
from zerver.views.invite import get_invitee_emails_set
from zerver.views.invite import INVITATION_LINK_VALIDITY_MINUTES, get_invitee_emails_set
from zerver.views.registration import accounts_home
from zproject.backends import ExternalAuthDataDict, ExternalAuthResult
@ -1110,7 +1110,7 @@ class InviteUserBase(ZulipTestCase):
self,
invitee_emails: str,
stream_names: Sequence[str],
invite_expires_in_minutes: Optional[int] = settings.INVITATION_LINK_VALIDITY_MINUTES,
invite_expires_in_minutes: Optional[int] = INVITATION_LINK_VALIDITY_MINUTES,
body: str = "",
invite_as: int = PreregistrationUser.INVITE_AS["MEMBER"],
) -> "TestHttpResponse":

View File

@ -17,6 +17,7 @@ from zerver.lib.email_notifications import enqueue_welcome_emails
from zerver.lib.request import REQ, has_request_variables
from zerver.lib.response import json_success
from zerver.models import Realm, get_realm, get_realm_stream, get_user_by_delivery_email
from zerver.views.invite import INVITATION_LINK_VALIDITY_MINUTES
from zproject.email_backends import get_forward_address, set_forward_address
ZULIP_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../../")
@ -71,7 +72,7 @@ def generate_all_emails(request: HttpRequest) -> HttpResponse:
registered_email = "hamlet@zulip.com"
unregistered_email_1 = "new-person@zulip.com"
unregistered_email_2 = "new-person-2@zulip.com"
invite_expires_in_minutes = settings.INVITATION_LINK_VALIDITY_MINUTES
invite_expires_in_minutes = INVITATION_LINK_VALIDITY_MINUTES
realm = get_realm("zulip")
other_realm = Realm.objects.exclude(string_id="zulip").first()
user = get_user_by_delivery_email(registered_email, realm)

View File

@ -21,6 +21,12 @@ from zerver.lib.streams import access_stream_by_id
from zerver.lib.validator import check_int, check_list, check_none_or
from zerver.models import MultiuseInvite, PreregistrationUser, Stream, UserProfile
# Convert INVITATION_LINK_VALIDITY_DAYS into minutes.
# Because mypy fails to correctly infer the type of the validator, we want this constant
# to be Optional[int] to avoid a mypy error when using it as the default value.
# https://github.com/python/mypy/issues/13234
INVITATION_LINK_VALIDITY_MINUTES: Optional[int] = 24 * 60 * settings.INVITATION_LINK_VALIDITY_DAYS
def check_if_owner_required(invited_as: int, user_profile: UserProfile) -> None:
if (
@ -37,7 +43,7 @@ def invite_users_backend(
user_profile: UserProfile,
invitee_emails_raw: str = REQ("invitee_emails"),
invite_expires_in_minutes: Optional[int] = REQ(
json_validator=check_none_or(check_int), default=settings.INVITATION_LINK_VALIDITY_MINUTES
json_validator=check_none_or(check_int), default=INVITATION_LINK_VALIDITY_MINUTES
),
invite_as: int = REQ(json_validator=check_int, default=PreregistrationUser.INVITE_AS["MEMBER"]),
stream_ids: List[int] = REQ(json_validator=check_list(check_int)),
@ -175,7 +181,7 @@ def generate_multiuse_invite_backend(
request: HttpRequest,
user_profile: UserProfile,
invite_expires_in_minutes: Optional[int] = REQ(
json_validator=check_none_or(check_int), default=settings.INVITATION_LINK_VALIDITY_MINUTES
json_validator=check_none_or(check_int), default=INVITATION_LINK_VALIDITY_MINUTES
),
invite_as: int = REQ(json_validator=check_int, default=PreregistrationUser.INVITE_AS["MEMBER"]),
stream_ids: Sequence[int] = REQ(json_validator=check_list(check_int), default=[]),

View File

@ -39,7 +39,6 @@ from .configured_settings import (
EXTERNAL_URI_SCHEME,
EXTRA_INSTALLED_APPS,
GOOGLE_OAUTH2_CLIENT_ID,
INVITATION_LINK_VALIDITY_DAYS,
IS_DEV_DROPLET,
LOCAL_UPLOADS_DIR,
MEMCACHED_LOCATION,
@ -1197,9 +1196,6 @@ AUTH_LDAP_BIND_PASSWORD = get_secret("auth_ldap_bind_password", "")
# MISC SETTINGS
########################################################################
# Convert INVITATION_LINK_VALIDITY_DAYS into minutes.
INVITATION_LINK_VALIDITY_MINUTES = 24 * 60 * INVITATION_LINK_VALIDITY_DAYS
if PRODUCTION:
# Filter out user data
DEFAULT_EXCEPTION_REPORTER_FILTER = "zerver.filters.ZulipExceptionReporterFilter"