models: Create delivery_email field in userprofile.

This commit creates a new field called delivery_email. For now, it is
exactly the same as email upon user profile creation and should stay
that way even when email is changed, and is used only for sending
outgoing email from Zulip.

The purpose of this field is to support an upcoming option where the
existing `email` field in Zulip becomes effectively the user's
"display email" address, as part of making it possible for users
actual email addresses (that can receive email, stored in the
delivery_email field) to not be available to other non-administrator
users in the organization.

Because the `email` field is used in numerous places in display code,
in the API, and in database queries, the shortest path to implementing
this "private email" feature is to keep "email" as-is in those parts
of the codebase, and just set the existing "email" ("display email")
model field to be something generated like
"username@zulip.example.com" for display purposes.

Eventually, we'll want to do further refactoring, either in the form
of having both `display_email` and `delivery_email` as fields, or
renaming "email" to "username".
This commit is contained in:
Joshua Pan
2018-07-05 11:08:30 -07:00
committed by Tim Abbott
parent 4b3fb746ea
commit 533eccd655
5 changed files with 38 additions and 3 deletions

View File

@@ -789,7 +789,8 @@ def do_change_user_email(user_profile: UserProfile, new_email: str) -> None:
delete_user_profile_caches([user_profile]) delete_user_profile_caches([user_profile])
user_profile.email = new_email user_profile.email = new_email
user_profile.save(update_fields=["email"]) user_profile.delivery_email = new_email
user_profile.save(update_fields=["email", "delivery_email"])
payload = dict(user_id=user_profile.id, payload = dict(user_id=user_profile.id,
new_email=new_email) new_email=new_email)

View File

@@ -65,7 +65,8 @@ def create_user_profile(realm: Realm, email: str, password: Optional[str],
enter_sends=enter_sends, enter_sends=enter_sends,
onboarding_steps=ujson.dumps([]), onboarding_steps=ujson.dumps([]),
default_language=realm.default_language, default_language=realm.default_language,
twenty_four_hour_time=realm.default_twenty_four_hour_time) twenty_four_hour_time=realm.default_twenty_four_hour_time,
delivery_email=email)
if bot_type or not active: if bot_type or not active:
password = None password = None

View File

@@ -43,7 +43,7 @@ def build_email(template_prefix: str, to_user_id: Optional[int]=None,
to_user = get_user_profile_by_id(to_user_id) to_user = get_user_profile_by_id(to_user_id)
# Change to formataddr((to_user.full_name, to_user.email)) once # Change to formataddr((to_user.full_name, to_user.email)) once
# https://github.com/zulip/zulip/issues/4676 is resolved # https://github.com/zulip/zulip/issues/4676 is resolved
to_email = to_user.email to_email = to_user.delivery_email
if context is None: if context is None:
context = {} context = {}

View File

@@ -0,0 +1,32 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.13 on 2018-07-05 17:57
from __future__ import unicode_literals
from django.db import migrations, models
from django.apps import apps
from django.db.models import F
from django.db.backends.postgresql_psycopg2.schema import DatabaseSchemaEditor
from django.db.migrations.state import StateApps
def copy_email_field(apps: StateApps, schema_editor: DatabaseSchemaEditor) -> None:
UserProfile = apps.get_model('zerver', 'UserProfile')
UserProfile.objects.all().update(delivery_email=F('email'))
class Migration(migrations.Migration):
dependencies = [
('zerver', '0173_support_seat_based_plans'),
]
operations = [
migrations.AddField(
model_name='userprofile',
name='delivery_email',
field=models.EmailField(db_index=True, default='', max_length=254),
preserve_default=False,
),
migrations.RunPython(copy_email_field,
reverse_code=migrations.RunPython.noop),
]

View File

@@ -602,6 +602,7 @@ class UserProfile(AbstractBaseUser, PermissionsMixin):
# Fields from models.AbstractUser minus last_name and first_name, # Fields from models.AbstractUser minus last_name and first_name,
# which we don't use; email is modified to make it indexed and unique. # which we don't use; email is modified to make it indexed and unique.
email = models.EmailField(blank=False, db_index=True) # type: str email = models.EmailField(blank=False, db_index=True) # type: str
delivery_email = models.EmailField(blank=False, db_index=True) # type: str
is_staff = models.BooleanField(default=False) # type: bool is_staff = models.BooleanField(default=False) # type: bool
is_active = models.BooleanField(default=True, db_index=True) # type: bool is_active = models.BooleanField(default=True, db_index=True) # type: bool
is_realm_admin = models.BooleanField(default=False, db_index=True) # type: bool is_realm_admin = models.BooleanField(default=False, db_index=True) # type: bool