mirror of https://github.com/zulip/zulip.git
invitations: Limit realms to 100 invites per day.
To guard against using zulip invites as a vector for spam. Stopgap measure until we figure out something better.
This commit is contained in:
parent
8dc0adbed8
commit
7d1c88f0fb
|
@ -3931,6 +3931,19 @@ def do_invite_users(user_profile: UserProfile,
|
||||||
streams: Iterable[Stream],
|
streams: Iterable[Stream],
|
||||||
invite_as_admin: Optional[bool]=False,
|
invite_as_admin: Optional[bool]=False,
|
||||||
body: Optional[str]=None) -> None:
|
body: Optional[str]=None) -> None:
|
||||||
|
if settings.OPEN_REALM_CREATION:
|
||||||
|
# Discourage using invitation emails as a vector for carrying spam
|
||||||
|
sent_invites = Confirmation.objects.filter(
|
||||||
|
realm=user_profile.realm,
|
||||||
|
date_sent__gte=timezone_now() - datetime.timedelta(days=1),
|
||||||
|
type=Confirmation.INVITATION).count()
|
||||||
|
if len(invitee_emails) + sent_invites > user_profile.realm.max_invites:
|
||||||
|
raise InvitationError(
|
||||||
|
_("You do not have enough remaining invites; "
|
||||||
|
"try again with fewer emails, or contact %s. "
|
||||||
|
"No invitations were sent." % (settings.ZULIP_ADMINISTRATOR)),
|
||||||
|
[], sent_invitations=False)
|
||||||
|
|
||||||
validated_emails = [] # type: List[Text]
|
validated_emails = [] # type: List[Text]
|
||||||
errors = [] # type: List[Tuple[Text, str]]
|
errors = [] # type: List[Tuple[Text, str]]
|
||||||
skipped = [] # type: List[Tuple[Text, str]]
|
skipped = [] # type: List[Tuple[Text, str]]
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.11.6 on 2017-11-30 04:58
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('zerver', '0124_stream_enable_notifications'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='realm',
|
||||||
|
name='max_invites',
|
||||||
|
field=models.IntegerField(default=100),
|
||||||
|
),
|
||||||
|
]
|
|
@ -170,6 +170,8 @@ class Realm(models.Model):
|
||||||
authentication_methods = BitField(flags=AUTHENTICATION_FLAGS,
|
authentication_methods = BitField(flags=AUTHENTICATION_FLAGS,
|
||||||
default=2**31 - 1) # type: BitHandler
|
default=2**31 - 1) # type: BitHandler
|
||||||
waiting_period_threshold = models.PositiveIntegerField(default=0) # type: int
|
waiting_period_threshold = models.PositiveIntegerField(default=0) # type: int
|
||||||
|
DEFAULT_MAX_INVITES = 100
|
||||||
|
max_invites = models.IntegerField(default=DEFAULT_MAX_INVITES) # type: int
|
||||||
|
|
||||||
# Define the types of the various automatically managed properties
|
# Define the types of the various automatically managed properties
|
||||||
property_types = dict(
|
property_types = dict(
|
||||||
|
|
|
@ -665,6 +665,25 @@ earl-test@zulip.com""", ["Denmark"]))
|
||||||
self.check_sent_emails(["bob-test@zulip.com", "carol-test@zulip.com",
|
self.check_sent_emails(["bob-test@zulip.com", "carol-test@zulip.com",
|
||||||
"dave-test@zulip.com", "earl-test@zulip.com"])
|
"dave-test@zulip.com", "earl-test@zulip.com"])
|
||||||
|
|
||||||
|
def test_invite_too_many_users(self) -> None:
|
||||||
|
# Only a light test of this pathway; e.g. doesn't test that
|
||||||
|
# the limit gets reset after 24 hours
|
||||||
|
self.login(self.example_email("iago"))
|
||||||
|
self.client_post("/json/invites",
|
||||||
|
{"invitee_emails": "1@zulip.com, 2@zulip.com",
|
||||||
|
"stream": ["Denmark"],
|
||||||
|
"custom_body": ''}),
|
||||||
|
|
||||||
|
self.assert_json_error(
|
||||||
|
self.client_post("/json/invites",
|
||||||
|
{"invitee_emails": ", ".join(
|
||||||
|
[str(i) for i in range(get_realm("zulip").max_invites - 1)]),
|
||||||
|
"stream": ["Denmark"],
|
||||||
|
"custom_body": ''}),
|
||||||
|
"You do not have enough remaining invites; "
|
||||||
|
"try again with fewer emails, or contact zulip-admin@example.com. "
|
||||||
|
"No invitations were sent.")
|
||||||
|
|
||||||
def test_missing_or_invalid_params(self) -> None:
|
def test_missing_or_invalid_params(self) -> None:
|
||||||
"""
|
"""
|
||||||
Tests inviting with various missing or invalid parameters.
|
Tests inviting with various missing or invalid parameters.
|
||||||
|
|
Loading…
Reference in New Issue