refactor: Flatten code in check_invite_limit().

Using early-exit here allows us to more easily
comment why there are certain exemptions to
this logic.

We also only require callers to pass in realm,
not the whole user object.
This commit is contained in:
Steve Howell 2018-08-21 20:13:14 +00:00 committed by Tim Abbott
parent cac9a02d6d
commit fe6680c316
1 changed files with 31 additions and 19 deletions

View File

@ -4435,35 +4435,47 @@ def estimate_recent_invites(realms: Iterable[Realm], *, days: int) -> int:
return 0 return 0
return recent_invites return recent_invites
def check_invite_limit(user: UserProfile, num_invitees: int) -> None: def check_invite_limit(realm: Realm, num_invitees: int) -> None:
'''Discourage using invitation emails as a vector for carrying spam.''' '''Discourage using invitation emails as a vector for carrying spam.'''
msg = _("You do not have enough remaining invites. " msg = _("You do not have enough remaining invites. "
"Please contact %s to have your limit raised. " "Please contact %s to have your limit raised. "
"No invitations were sent.") % (settings.ZULIP_ADMINISTRATOR,) "No invitations were sent.") % (settings.ZULIP_ADMINISTRATOR,)
if settings.OPEN_REALM_CREATION: if not settings.OPEN_REALM_CREATION:
recent_invites = estimate_recent_invites([user.realm], days=1) return
if num_invitees + recent_invites > user.realm.max_invites:
raise InvitationError(msg, [], sent_invitations=False)
default_max = settings.INVITES_DEFAULT_REALM_DAILY_MAX recent_invites = estimate_recent_invites([realm], days=1)
newrealm_age = datetime.timedelta(days=settings.INVITES_NEW_REALM_DAYS) if num_invitees + recent_invites > realm.max_invites:
if (user.realm.date_created > timezone_now() - newrealm_age raise InvitationError(msg, [], sent_invitations=False)
and user.realm.max_invites <= default_max):
new_realms = Realm.objects.filter( default_max = settings.INVITES_DEFAULT_REALM_DAILY_MAX
date_created__gte=timezone_now() - newrealm_age, newrealm_age = datetime.timedelta(days=settings.INVITES_NEW_REALM_DAYS)
_max_invites__lte=default_max, if realm.date_created <= timezone_now() - newrealm_age:
).all() # If this isn't a "newly-created" realm, we're done. The
for days, count in settings.INVITES_NEW_REALM_LIMIT_DAYS: # remaining code applies an aggregate limit across all
recent_invites = estimate_recent_invites(new_realms, days=days) # "new" realms, to address sudden bursts of spam realms.
if num_invitees + recent_invites > count: return
raise InvitationError(msg, [], sent_invitations=False)
if realm.max_invites > default_max:
# If a user is on a realm where we've bumped up
# max_invites, then we exempt them from invite limits.
return
new_realms = Realm.objects.filter(
date_created__gte=timezone_now() - newrealm_age,
_max_invites__lte=default_max,
).all()
for days, count in settings.INVITES_NEW_REALM_LIMIT_DAYS:
recent_invites = estimate_recent_invites(new_realms, days=days)
if num_invitees + recent_invites > count:
raise InvitationError(msg, [], sent_invitations=False)
def do_invite_users(user_profile: UserProfile, def do_invite_users(user_profile: UserProfile,
invitee_emails: SizedTextIterable, invitee_emails: SizedTextIterable,
streams: Iterable[Stream], streams: Iterable[Stream],
invite_as_admin: Optional[bool]=False) -> None: invite_as_admin: Optional[bool]=False) -> None:
check_invite_limit(user_profile, len(invitee_emails)) check_invite_limit(user_profile.realm, len(invitee_emails))
realm = user_profile.realm realm = user_profile.realm
if not realm.invite_required: if not realm.invite_required:
@ -4570,7 +4582,7 @@ def do_revoke_user_invite(prereg_user: PreregistrationUser) -> None:
notify_invites_changed(prereg_user) notify_invites_changed(prereg_user)
def do_resend_user_invite_email(prereg_user: PreregistrationUser) -> int: def do_resend_user_invite_email(prereg_user: PreregistrationUser) -> int:
check_invite_limit(prereg_user.referred_by, 1) check_invite_limit(prereg_user.referred_by.realm, 1)
prereg_user.invited_at = timezone_now() prereg_user.invited_at = timezone_now()
prereg_user.save() prereg_user.save()