2021-05-28 15:57:08 +02:00
|
|
|
from django.conf import settings
|
|
|
|
from django.utils.translation import gettext as _
|
|
|
|
|
2022-08-14 19:42:55 +02:00
|
|
|
from corporate.lib.stripe import LicenseLimitError, get_latest_seat_count, get_seat_count
|
2024-09-19 14:37:02 +02:00
|
|
|
from corporate.models import CustomerPlan, get_current_plan_by_realm
|
2024-04-02 06:38:38 +02:00
|
|
|
from zerver.actions.create_user import send_group_direct_message_to_admins
|
2021-05-28 15:57:08 +02:00
|
|
|
from zerver.lib.exceptions import InvitationError
|
2023-12-15 01:16:00 +01:00
|
|
|
from zerver.models import Realm, UserProfile
|
|
|
|
from zerver.models.users import get_system_bot
|
2021-05-28 15:57:08 +02:00
|
|
|
|
|
|
|
|
2024-09-19 14:37:02 +02:00
|
|
|
def get_plan_if_manual_license_management_enforced(realm: Realm) -> CustomerPlan | None:
|
2021-05-28 15:57:08 +02:00
|
|
|
plan = get_current_plan_by_realm(realm)
|
2024-09-19 14:37:02 +02:00
|
|
|
if plan is None or plan.automanage_licenses or plan.customer.exempt_from_license_number_check:
|
|
|
|
return None
|
|
|
|
return plan
|
|
|
|
|
|
|
|
|
|
|
|
def generate_licenses_low_warning_message_if_required(realm: Realm) -> str | None:
|
|
|
|
plan = get_plan_if_manual_license_management_enforced(realm)
|
|
|
|
if plan is None:
|
2021-05-28 15:57:08 +02:00
|
|
|
return None
|
|
|
|
|
|
|
|
licenses_remaining = plan.licenses() - get_latest_seat_count(realm)
|
|
|
|
if licenses_remaining > 3:
|
|
|
|
return None
|
|
|
|
|
|
|
|
format_kwargs = {
|
2024-09-19 14:17:02 +02:00
|
|
|
"billing_page_link": "/billing/",
|
2021-05-28 15:57:08 +02:00
|
|
|
"deactivate_user_help_page_link": "/help/deactivate-or-reactivate-a-user",
|
|
|
|
}
|
|
|
|
|
|
|
|
if licenses_remaining <= 0:
|
|
|
|
return _(
|
|
|
|
"Your organization has no Zulip licenses remaining and can no longer accept new users. "
|
|
|
|
"Please [increase the number of licenses]({billing_page_link}) or "
|
|
|
|
"[deactivate inactive users]({deactivate_user_help_page_link}) to allow new users to join."
|
|
|
|
).format(**format_kwargs)
|
|
|
|
|
|
|
|
return {
|
|
|
|
1: _(
|
|
|
|
"Your organization has only one Zulip license remaining. You can "
|
|
|
|
"[increase the number of licenses]({billing_page_link}) or [deactivate inactive users]({deactivate_user_help_page_link}) "
|
|
|
|
"to allow more than one user to join."
|
|
|
|
),
|
|
|
|
2: _(
|
|
|
|
"Your organization has only two Zulip licenses remaining. You can "
|
|
|
|
"[increase the number of licenses]({billing_page_link}) or [deactivate inactive users]({deactivate_user_help_page_link}) "
|
|
|
|
"to allow more than two users to join."
|
|
|
|
),
|
|
|
|
3: _(
|
|
|
|
"Your organization has only three Zulip licenses remaining. You can "
|
|
|
|
"[increase the number of licenses]({billing_page_link}) or [deactivate inactive users]({deactivate_user_help_page_link}) "
|
|
|
|
"to allow more than three users to join."
|
|
|
|
),
|
|
|
|
}[licenses_remaining].format(**format_kwargs)
|
|
|
|
|
|
|
|
|
2024-04-02 06:38:38 +02:00
|
|
|
def send_user_unable_to_signup_group_direct_message_to_admins(
|
2021-05-28 15:57:08 +02:00
|
|
|
realm: Realm, user_email: str
|
|
|
|
) -> None:
|
|
|
|
message = _(
|
2024-09-05 20:16:54 +02:00
|
|
|
"A new user ({email}) was unable to join because your organization does not have enough "
|
|
|
|
"Zulip licenses. To allow new users to join, make sure that the [number of licenses for "
|
|
|
|
"the current and next billing period]({billing_page_link}) is greater than the current "
|
|
|
|
"number of users."
|
2021-05-28 15:57:08 +02:00
|
|
|
).format(
|
|
|
|
email=user_email,
|
2024-09-19 14:17:02 +02:00
|
|
|
billing_page_link="/billing/",
|
2021-05-28 15:57:08 +02:00
|
|
|
)
|
|
|
|
|
2024-04-02 06:38:38 +02:00
|
|
|
send_group_direct_message_to_admins(
|
2021-07-09 18:33:09 +02:00
|
|
|
get_system_bot(settings.NOTIFICATION_BOT, realm.id), realm, message
|
2021-05-28 15:57:08 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
|
2024-09-19 14:37:02 +02:00
|
|
|
def check_spare_licenses_available(
|
|
|
|
realm: Realm, plan: CustomerPlan, extra_non_guests_count: int = 0, extra_guests_count: int = 0
|
2021-05-28 15:57:08 +02:00
|
|
|
) -> None:
|
2024-09-05 20:16:54 +02:00
|
|
|
seat_count = get_seat_count(
|
2022-08-14 19:42:55 +02:00
|
|
|
realm, extra_non_guests_count=extra_non_guests_count, extra_guests_count=extra_guests_count
|
2024-09-05 20:16:54 +02:00
|
|
|
)
|
|
|
|
current_licenses = plan.licenses()
|
|
|
|
renewal_licenses = plan.licenses_at_next_renewal()
|
|
|
|
if current_licenses < seat_count or (renewal_licenses and renewal_licenses < seat_count):
|
2023-02-04 02:07:20 +01:00
|
|
|
raise LicenseLimitError
|
2021-05-28 15:57:08 +02:00
|
|
|
|
|
|
|
|
|
|
|
def check_spare_licenses_available_for_registering_new_user(
|
2022-08-14 19:42:55 +02:00
|
|
|
realm: Realm,
|
|
|
|
user_email_to_add: str,
|
|
|
|
role: int,
|
2021-05-28 15:57:08 +02:00
|
|
|
) -> None:
|
2024-09-19 14:37:02 +02:00
|
|
|
plan = get_plan_if_manual_license_management_enforced(realm)
|
|
|
|
if plan is None:
|
|
|
|
return
|
|
|
|
|
2021-05-28 15:57:08 +02:00
|
|
|
try:
|
2022-08-14 19:42:55 +02:00
|
|
|
if role == UserProfile.ROLE_GUEST:
|
2024-09-19 14:37:02 +02:00
|
|
|
check_spare_licenses_available(realm, plan, extra_guests_count=1)
|
2022-08-14 19:42:55 +02:00
|
|
|
else:
|
2024-09-19 14:37:02 +02:00
|
|
|
check_spare_licenses_available(realm, plan, extra_non_guests_count=1)
|
2021-05-28 15:57:08 +02:00
|
|
|
except LicenseLimitError:
|
2024-04-02 06:38:38 +02:00
|
|
|
send_user_unable_to_signup_group_direct_message_to_admins(realm, user_email_to_add)
|
2021-05-28 15:57:08 +02:00
|
|
|
raise
|
|
|
|
|
|
|
|
|
2022-08-14 19:42:55 +02:00
|
|
|
def check_spare_licenses_available_for_inviting_new_users(
|
|
|
|
realm: Realm, extra_non_guests_count: int = 0, extra_guests_count: int = 0
|
|
|
|
) -> None:
|
2024-09-19 14:37:02 +02:00
|
|
|
plan = get_plan_if_manual_license_management_enforced(realm)
|
|
|
|
if plan is None:
|
|
|
|
return
|
|
|
|
|
2021-05-28 15:57:08 +02:00
|
|
|
try:
|
2024-09-19 14:37:02 +02:00
|
|
|
check_spare_licenses_available(realm, plan, extra_non_guests_count, extra_guests_count)
|
2021-05-28 15:57:08 +02:00
|
|
|
except LicenseLimitError:
|
2024-09-05 20:16:54 +02:00
|
|
|
message = _(
|
|
|
|
"Your organization does not have enough Zulip licenses. Invitations were not sent."
|
|
|
|
)
|
2021-05-28 15:57:08 +02:00
|
|
|
raise InvitationError(message, [], sent_invitations=False, license_limit_reached=True)
|