mirror of https://github.com/zulip/zulip.git
registration: Collect organization type on sign-up.
This commit is contained in:
parent
43f3f9221d
commit
faa695e86d
|
@ -400,7 +400,8 @@ html {
|
|||
|
||||
input[type="text"],
|
||||
input[type="email"],
|
||||
input[type="password"] {
|
||||
input[type="password"],
|
||||
select {
|
||||
padding: 10px 32px 10px 12px;
|
||||
margin: 25px 0 5px;
|
||||
|
||||
|
@ -458,9 +459,11 @@ html {
|
|||
input[type="text"]:focus + label,
|
||||
input[type="email"]:focus + label,
|
||||
input[type="password"]:focus + label,
|
||||
select:focus + label,
|
||||
input[type="text"]:valid + label,
|
||||
input[type="email"]:valid + label,
|
||||
input[type="password"]:valid + label {
|
||||
input[type="password"]:valid + label,
|
||||
select:valid + label {
|
||||
left: 0;
|
||||
transform: translateY(0) translateX(0);
|
||||
pointer-events: auto;
|
||||
|
@ -470,6 +473,12 @@ html {
|
|||
color: hsl(0, 0%, 27%);
|
||||
}
|
||||
|
||||
/* The width of the "Organization name" text box
|
||||
right above this one is also 326px. */
|
||||
select {
|
||||
width: 326px;
|
||||
}
|
||||
|
||||
p.text-error {
|
||||
display: block;
|
||||
padding: 0;
|
||||
|
|
|
@ -47,6 +47,20 @@ Form is validated both client-side using jquery-validate (see signup.js) and ser
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="input-box">
|
||||
<div class="inline-block relative">
|
||||
<select name="realm_type" id="realm_type">
|
||||
{% for realm_type in sorted_realm_types %}
|
||||
{% if not realm_type.hidden %}
|
||||
<option value="{{ realm_type.id }}">{{ _(realm_type.name) }}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<label for="realm_type" class="inline-block label-title">{{ _('Organization type') }}</label>
|
||||
</div>
|
||||
|
||||
<div class="input-box">
|
||||
<label class="static org-url">
|
||||
{{ _('Organization URL') }}
|
||||
|
|
|
@ -114,6 +114,7 @@ class RegistrationForm(forms.Form):
|
|||
# actually required for a realm
|
||||
password = forms.CharField(widget=forms.PasswordInput, max_length=MAX_PASSWORD_LENGTH)
|
||||
realm_subdomain = forms.CharField(max_length=Realm.MAX_REALM_SUBDOMAIN_LENGTH, required=False)
|
||||
realm_type = forms.IntegerField(required=False)
|
||||
|
||||
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
||||
# Since the superclass doesn't except random extra kwargs, we
|
||||
|
|
|
@ -627,6 +627,7 @@ Output:
|
|||
default_stream_groups: Sequence[str] = [],
|
||||
source_realm_id: str = "",
|
||||
key: Optional[str] = None,
|
||||
realm_type: Optional[int] = Realm.ORG_TYPES["business"]["id"],
|
||||
**kwargs: Any,
|
||||
) -> HttpResponse:
|
||||
"""
|
||||
|
@ -643,6 +644,7 @@ Output:
|
|||
"full_name": full_name,
|
||||
"realm_name": realm_name,
|
||||
"realm_subdomain": realm_subdomain,
|
||||
"realm_type": realm_type,
|
||||
"key": key if key is not None else find_key_by_email(email),
|
||||
"timezone": timezone,
|
||||
"terms": True,
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
# Generated by Django 3.2.4 on 2021-07-06 20:34
|
||||
|
||||
from django.db import migrations, models
|
||||
from django.db.backends.postgresql.schema import DatabaseSchemaEditor
|
||||
from django.db.migrations.state import StateApps
|
||||
|
||||
|
||||
def reset_realm_org_type(apps: StateApps, schema_editor: DatabaseSchemaEditor) -> None:
|
||||
UNSPECIFIED = 0
|
||||
Realm = apps.get_model("zerver", "Realm")
|
||||
Realm.objects.all().update(org_type=UNSPECIFIED)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("zerver", "0332_realmuserdefault"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="realm",
|
||||
name="org_type",
|
||||
field=models.PositiveSmallIntegerField(
|
||||
choices=[
|
||||
(0, "Unspecified"),
|
||||
(10, "Business"),
|
||||
(20, "Open-source project"),
|
||||
(30, "Education"),
|
||||
(40, "Research"),
|
||||
(50, "Event or conference"),
|
||||
(60, "Non-profit (registered)"),
|
||||
(70, "Government"),
|
||||
(80, "Political group"),
|
||||
(90, "Community"),
|
||||
(100, "Personal"),
|
||||
(1000, "Other"),
|
||||
],
|
||||
default=0,
|
||||
),
|
||||
),
|
||||
migrations.RunPython(
|
||||
reset_realm_org_type, reverse_code=migrations.RunPython.noop, elidable=True
|
||||
),
|
||||
]
|
|
@ -404,10 +404,86 @@ class Realm(models.Model):
|
|||
# Messages older than this message ID in the organization are inaccessible.
|
||||
first_visible_message_id: int = models.IntegerField(default=0)
|
||||
|
||||
# Valid org_types are {CORPORATE, COMMUNITY}
|
||||
CORPORATE = 1
|
||||
COMMUNITY = 2
|
||||
org_type: int = models.PositiveSmallIntegerField(default=CORPORATE)
|
||||
# Valid org types
|
||||
ORG_TYPES: Dict[str, Dict[str, Any]] = {
|
||||
"unspecified": {
|
||||
"name": "Unspecified",
|
||||
"id": 0,
|
||||
"hidden": True,
|
||||
"display_order": 0,
|
||||
},
|
||||
"business": {
|
||||
"name": "Business",
|
||||
"id": 10,
|
||||
"hidden": False,
|
||||
"display_order": 1,
|
||||
},
|
||||
"opensource": {
|
||||
"name": "Open-source project",
|
||||
"id": 20,
|
||||
"hidden": False,
|
||||
"display_order": 2,
|
||||
},
|
||||
"education": {
|
||||
"name": "Education",
|
||||
"id": 30,
|
||||
"hidden": False,
|
||||
"display_order": 3,
|
||||
},
|
||||
"research": {
|
||||
"name": "Research",
|
||||
"id": 40,
|
||||
"hidden": False,
|
||||
"display_order": 4,
|
||||
},
|
||||
"event": {
|
||||
"name": "Event or conference",
|
||||
"id": 50,
|
||||
"hidden": False,
|
||||
"display_order": 5,
|
||||
},
|
||||
"nonprofit": {
|
||||
"name": "Non-profit (registered)",
|
||||
"id": 60,
|
||||
"hidden": False,
|
||||
"display_order": 6,
|
||||
},
|
||||
"government": {
|
||||
"name": "Government",
|
||||
"id": 70,
|
||||
"hidden": False,
|
||||
"display_order": 7,
|
||||
},
|
||||
"political_group": {
|
||||
"name": "Political group",
|
||||
"id": 80,
|
||||
"hidden": False,
|
||||
"display_order": 8,
|
||||
},
|
||||
"community": {
|
||||
"name": "Community",
|
||||
"id": 90,
|
||||
"hidden": False,
|
||||
"display_order": 9,
|
||||
},
|
||||
"personal": {
|
||||
"name": "Personal",
|
||||
"id": 100,
|
||||
"hidden": False,
|
||||
"display_order": 100,
|
||||
},
|
||||
"other": {
|
||||
"name": "Other",
|
||||
"id": 1000,
|
||||
"hidden": False,
|
||||
"display_order": 1000,
|
||||
},
|
||||
}
|
||||
|
||||
org_type: int = models.PositiveSmallIntegerField(
|
||||
default=ORG_TYPES["unspecified"]["id"],
|
||||
choices=[(t["id"], t["name"]) for t in ORG_TYPES.values()],
|
||||
)
|
||||
|
||||
UPGRADE_TEXT_STANDARD = gettext_lazy("Available on Zulip Standard. Upgrade to access.")
|
||||
# plan_type controls various features around resource/feature
|
||||
|
|
|
@ -660,7 +660,7 @@ class RealmTest(ZulipTestCase):
|
|||
self.assertEqual(realm.description, "")
|
||||
self.assertTrue(realm.invite_required)
|
||||
self.assertEqual(realm.plan_type, Realm.LIMITED)
|
||||
self.assertEqual(realm.org_type, Realm.CORPORATE)
|
||||
self.assertEqual(realm.org_type, Realm.ORG_TYPES["unspecified"]["id"])
|
||||
self.assertEqual(type(realm.date_created), datetime.datetime)
|
||||
|
||||
self.assertTrue(
|
||||
|
@ -690,7 +690,7 @@ class RealmTest(ZulipTestCase):
|
|||
description="realm description",
|
||||
invite_required=False,
|
||||
plan_type=Realm.STANDARD_FREE,
|
||||
org_type=Realm.COMMUNITY,
|
||||
org_type=Realm.ORG_TYPES["community"]["id"],
|
||||
)
|
||||
self.assertEqual(realm.string_id, "realm_string_id")
|
||||
self.assertEqual(realm.name, "realm name")
|
||||
|
@ -699,7 +699,7 @@ class RealmTest(ZulipTestCase):
|
|||
self.assertEqual(realm.description, "realm description")
|
||||
self.assertFalse(realm.invite_required)
|
||||
self.assertEqual(realm.plan_type, Realm.STANDARD_FREE)
|
||||
self.assertEqual(realm.org_type, Realm.COMMUNITY)
|
||||
self.assertEqual(realm.org_type, Realm.ORG_TYPES["community"]["id"])
|
||||
self.assertEqual(realm.date_created, date_created)
|
||||
|
||||
self.assertTrue(
|
||||
|
|
|
@ -2869,7 +2869,7 @@ class RealmCreationTest(ZulipTestCase):
|
|||
self.assertEqual(user.role, UserProfile.ROLE_REALM_OWNER)
|
||||
|
||||
# Check defaults
|
||||
self.assertEqual(realm.org_type, Realm.CORPORATE)
|
||||
self.assertEqual(realm.org_type, Realm.ORG_TYPES["business"]["id"])
|
||||
self.assertEqual(realm.emails_restricted_to_domains, False)
|
||||
self.assertEqual(realm.invite_required, True)
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ from django.views.decorators.csrf import csrf_exempt
|
|||
from confirmation.models import Confirmation, create_confirmation_link
|
||||
from zerver.lib.response import json_success
|
||||
from zerver.lib.subdomains import get_subdomain
|
||||
from zerver.models import UserProfile
|
||||
from zerver.models import Realm, UserProfile
|
||||
from zerver.views.auth import create_preregistration_user
|
||||
from zerver.views.registration import accounts_register
|
||||
|
||||
|
@ -48,6 +48,7 @@ def register_development_realm(request: HttpRequest) -> HttpResponse:
|
|||
name = f"user-{count}"
|
||||
email = f"{name}@zulip.com"
|
||||
realm_name = f"realm-{count}"
|
||||
realm_type = Realm.ORG_TYPES["business"]["id"]
|
||||
prereg = create_preregistration_user(
|
||||
email, request, realm_creation=True, password_required=False
|
||||
)
|
||||
|
@ -58,6 +59,7 @@ def register_development_realm(request: HttpRequest) -> HttpResponse:
|
|||
request,
|
||||
key=key,
|
||||
realm_name=realm_name,
|
||||
realm_type=realm_type,
|
||||
full_name=name,
|
||||
password="test",
|
||||
realm_subdomain=realm_name,
|
||||
|
|
|
@ -308,7 +308,8 @@ def accounts_register(request: HttpRequest) -> HttpResponse:
|
|||
if realm_creation:
|
||||
string_id = form.cleaned_data["realm_subdomain"]
|
||||
realm_name = form.cleaned_data["realm_name"]
|
||||
realm = do_create_realm(string_id, realm_name)
|
||||
realm_type = form.cleaned_data["realm_type"]
|
||||
realm = do_create_realm(string_id, realm_name, org_type=realm_type)
|
||||
setup_realm_internal_bots(realm)
|
||||
assert realm is not None
|
||||
|
||||
|
@ -484,6 +485,9 @@ def accounts_register(request: HttpRequest) -> HttpResponse:
|
|||
"MAX_NAME_LENGTH": str(UserProfile.MAX_NAME_LENGTH),
|
||||
"MAX_PASSWORD_LENGTH": str(form.MAX_PASSWORD_LENGTH),
|
||||
"MAX_REALM_SUBDOMAIN_LENGTH": str(Realm.MAX_REALM_SUBDOMAIN_LENGTH),
|
||||
"sorted_realm_types": sorted(
|
||||
Realm.ORG_TYPES.values(), key=lambda d: d["display_order"]
|
||||
),
|
||||
},
|
||||
)
|
||||
|
||||
|
|
|
@ -312,7 +312,7 @@ class Command(BaseCommand):
|
|||
" It's great for testing!",
|
||||
invite_required=False,
|
||||
plan_type=Realm.SELF_HOSTED,
|
||||
org_type=Realm.CORPORATE,
|
||||
org_type=Realm.ORG_TYPES["business"]["id"],
|
||||
)
|
||||
RealmDomain.objects.create(realm=zulip_realm, domain="zulip.com")
|
||||
assert zulip_realm.notifications_stream is not None
|
||||
|
@ -327,7 +327,7 @@ class Command(BaseCommand):
|
|||
emails_restricted_to_domains=True,
|
||||
invite_required=False,
|
||||
plan_type=Realm.SELF_HOSTED,
|
||||
org_type=Realm.CORPORATE,
|
||||
org_type=Realm.ORG_TYPES["business"]["id"],
|
||||
)
|
||||
RealmDomain.objects.create(realm=mit_realm, domain="mit.edu")
|
||||
|
||||
|
@ -337,7 +337,7 @@ class Command(BaseCommand):
|
|||
emails_restricted_to_domains=False,
|
||||
invite_required=False,
|
||||
plan_type=Realm.SELF_HOSTED,
|
||||
org_type=Realm.CORPORATE,
|
||||
org_type=Realm.ORG_TYPES["business"]["id"],
|
||||
)
|
||||
|
||||
# Default to allowing all members to send mentions in
|
||||
|
|
Loading…
Reference in New Issue