mirror of
https://github.com/zulip/zulip.git
synced 2025-11-10 00:46:03 +00:00
[manual] Add User fields to the UserProfile model.
And keep the fields updated, by copying on UserProfile creation and updating the UserProfile object whenever we're updating the User object, and add management commands to (1) initially ensure that they match and (2) check that they still match (aka that the updating code is working). The copy_user_to_userprofile migration needs to be run after this is deployed to prod. (imported from commit 0a598d2e10b1a7a2f5c67dd5140ea4bb8e1ec0b8)
This commit is contained in:
@@ -75,6 +75,10 @@ def user_sessions(user):
|
|||||||
return [s for s in Session.objects.all() if s.get_decoded().get('_auth_user_id') == user.id]
|
return [s for s in Session.objects.all() if s.get_decoded().get('_auth_user_id') == user.id]
|
||||||
|
|
||||||
def do_deactivate(user_profile):
|
def do_deactivate(user_profile):
|
||||||
|
user_profile.is_active = False;
|
||||||
|
user_profile.set_unusable_password()
|
||||||
|
user_profile.save(update_fields=["is_active", "password"])
|
||||||
|
|
||||||
user_profile.user.set_unusable_password()
|
user_profile.user.set_unusable_password()
|
||||||
user_profile.user.is_active = False
|
user_profile.user.is_active = False
|
||||||
user_profile.user.save(update_fields=["is_active", "password"])
|
user_profile.user.save(update_fields=["is_active", "password"])
|
||||||
@@ -98,6 +102,10 @@ def do_deactivate(user_profile):
|
|||||||
|
|
||||||
def do_change_user_email(user_profile, new_email):
|
def do_change_user_email(user_profile, new_email):
|
||||||
old_email = user_profile.user.email
|
old_email = user_profile.user.email
|
||||||
|
|
||||||
|
user_profile.email = new_email
|
||||||
|
user_profile.save(update_fields=["email"])
|
||||||
|
|
||||||
user_profile.user.email = new_email
|
user_profile.user.email = new_email
|
||||||
user_profile.user.save(update_fields=["email"])
|
user_profile.user.save(update_fields=["email"])
|
||||||
|
|
||||||
@@ -469,6 +477,12 @@ def log_subscription_property_change(user_email, property, property_dict):
|
|||||||
|
|
||||||
def do_activate_user(user_profile, log=True, join_date=timezone.now()):
|
def do_activate_user(user_profile, log=True, join_date=timezone.now()):
|
||||||
user = user_profile.user
|
user = user_profile.user
|
||||||
|
|
||||||
|
user_profile.is_active = True
|
||||||
|
user_profile.set_password(initial_password(user_profile.email))
|
||||||
|
user_profile.date_joined = join_date
|
||||||
|
user_profile.save(update_fields=["is_active", "date_joined", "password"])
|
||||||
|
|
||||||
user.is_active = True
|
user.is_active = True
|
||||||
user.set_password(initial_password(user.email))
|
user.set_password(initial_password(user.email))
|
||||||
user.date_joined = join_date
|
user.date_joined = join_date
|
||||||
@@ -486,10 +500,13 @@ def do_change_password(user_profile, password, log=True, commit=True,
|
|||||||
if hashed_password:
|
if hashed_password:
|
||||||
# This is a hashed password, not the password itself.
|
# This is a hashed password, not the password itself.
|
||||||
user.password = password
|
user.password = password
|
||||||
|
user_profile.set_password(password)
|
||||||
else:
|
else:
|
||||||
user.set_password(password)
|
user.set_password(password)
|
||||||
|
user_profile.set_password(password)
|
||||||
if commit:
|
if commit:
|
||||||
user.save(update_fields=["password"])
|
user.save(update_fields=["password"])
|
||||||
|
user_profile.save(update_fields=["password"])
|
||||||
if log:
|
if log:
|
||||||
log_event({'type': 'user_change_password',
|
log_event({'type': 'user_change_password',
|
||||||
'user': user.email,
|
'user': user.email,
|
||||||
|
|||||||
@@ -42,8 +42,14 @@ def bulk_create_users(realms, users_raw):
|
|||||||
# Now create user_profiles
|
# Now create user_profiles
|
||||||
profiles_to_create = []
|
profiles_to_create = []
|
||||||
for (email, full_name, short_name, active) in users:
|
for (email, full_name, short_name, active) in users:
|
||||||
|
user = users_by_email[email]
|
||||||
domain = email.split('@')[1]
|
domain = email.split('@')[1]
|
||||||
profile = UserProfile(user=users_by_email[email], pointer=-1,
|
profile = UserProfile(user=user, pointer=-1,
|
||||||
|
is_active=user.is_active,
|
||||||
|
is_staff=user.is_staff,
|
||||||
|
date_joined=user.date_joined,
|
||||||
|
email=user.email,
|
||||||
|
password=user.password,
|
||||||
realm=realms[domain],
|
realm=realms[domain],
|
||||||
full_name=full_name, short_name=short_name)
|
full_name=full_name, short_name=short_name)
|
||||||
profile.api_key = initial_api_key(email)
|
profile.api_key = initial_api_key(email)
|
||||||
|
|||||||
18
zephyr/management/commands/copy_user_to_userprofile.py
Normal file
18
zephyr/management/commands/copy_user_to_userprofile.py
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
from optparse import make_option
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
from zephyr.models import UserProfile, User
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
option_list = BaseCommand.option_list
|
||||||
|
help = "Copy all the shared fields from User to UserProfile."
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
for user_profile in UserProfile.objects.all():
|
||||||
|
user = user_profile.user
|
||||||
|
user_profile.email = user.email
|
||||||
|
user_profile.is_active = user.is_active
|
||||||
|
user_profile.is_staff = user.is_staff
|
||||||
|
user_profile.date_joined = user.date_joined
|
||||||
|
user_profile.password = user.password
|
||||||
|
user_profile.save(update_fields=["email", "is_active", "is_staff", "date_joined", "password"])
|
||||||
|
|
||||||
19
zephyr/management/commands/diff_user_to_userprofile.py
Normal file
19
zephyr/management/commands/diff_user_to_userprofile.py
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
from optparse import make_option
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
from zephyr.models import UserProfile, User
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
option_list = BaseCommand.option_list
|
||||||
|
help = "Diff all the shared fields between User to UserProfile."
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
for user_profile in UserProfile.objects.all():
|
||||||
|
user = user_profile.user
|
||||||
|
def diff_fields(user_version, user_profile_version):
|
||||||
|
if user_version != user_profile_version:
|
||||||
|
print "Some values differ for %s!" % (user_profile.user.email,)
|
||||||
|
diff_fields(user.email, user_profile.email)
|
||||||
|
diff_fields(user.is_active, user_profile.is_active)
|
||||||
|
diff_fields(user.is_staff, user_profile.is_staff)
|
||||||
|
diff_fields(user.date_joined, user_profile.date_joined)
|
||||||
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User, AbstractBaseUser, UserManager
|
||||||
from zephyr.lib.cache import cache_with_key, update_user_profile_cache, \
|
from zephyr.lib.cache import cache_with_key, update_user_profile_cache, \
|
||||||
update_user_cache, user_profile_by_id_cache_key, \
|
update_user_cache, user_profile_by_id_cache_key, \
|
||||||
user_profile_by_email_cache_key
|
user_profile_by_email_cache_key
|
||||||
@@ -52,8 +52,21 @@ class Realm(models.Model):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.__repr__()
|
return self.__repr__()
|
||||||
|
|
||||||
class UserProfile(models.Model):
|
class UserProfile(AbstractBaseUser):
|
||||||
|
# Fields from models.AbstractUser minus last_name and first_name, which we don't use
|
||||||
|
email = models.EmailField(blank=True)
|
||||||
|
is_staff = models.BooleanField(default=False)
|
||||||
|
is_active = models.BooleanField(default=True)
|
||||||
|
date_joined = models.DateTimeField(default=timezone.now)
|
||||||
|
USERNAME_FIELD = 'email'
|
||||||
|
|
||||||
|
# User Legacy code: the object that goes with this UserProfile.
|
||||||
|
# Plan is to for a short time maintain them both in sync, then
|
||||||
|
# later we'll dump the old User field, and perhaps later than
|
||||||
|
# that, rename the surviving field to just User.
|
||||||
user = models.OneToOneField(User)
|
user = models.OneToOneField(User)
|
||||||
|
|
||||||
|
# Our custom site-specific fields
|
||||||
full_name = models.CharField(max_length=100)
|
full_name = models.CharField(max_length=100)
|
||||||
short_name = models.CharField(max_length=100)
|
short_name = models.CharField(max_length=100)
|
||||||
pointer = models.IntegerField()
|
pointer = models.IntegerField()
|
||||||
@@ -63,16 +76,20 @@ class UserProfile(models.Model):
|
|||||||
enable_desktop_notifications = models.BooleanField(default=True)
|
enable_desktop_notifications = models.BooleanField(default=True)
|
||||||
enter_sends = models.NullBooleanField(default=False)
|
enter_sends = models.NullBooleanField(default=False)
|
||||||
|
|
||||||
def __repr__(self):
|
objects = UserManager()
|
||||||
return (u"<UserProfile: %s %s>" % (self.user.email, self.realm)).encode("utf-8")
|
|
||||||
def __str__(self):
|
|
||||||
return self.__repr__()
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create(cls, user, realm, full_name, short_name):
|
def create(cls, user, realm, full_name, short_name):
|
||||||
"""When creating a new user, make a profile for him or her."""
|
"""When creating a new user, make a profile for him or her."""
|
||||||
if not cls.objects.filter(user=user):
|
if not cls.objects.filter(user=user):
|
||||||
profile = cls(user=user, pointer=-1, realm=realm,
|
profile = cls(user=user, pointer=-1, realm=realm,
|
||||||
|
# User Legacy code:
|
||||||
|
is_active=user.is_active,
|
||||||
|
is_staff=user.is_staff,
|
||||||
|
date_joined=user.date_joined,
|
||||||
|
email=user.email,
|
||||||
|
password=user.password,
|
||||||
|
# end User Legacy code
|
||||||
full_name=full_name, short_name=short_name)
|
full_name=full_name, short_name=short_name)
|
||||||
profile.api_key = initial_api_key(user.email)
|
profile.api_key = initial_api_key(user.email)
|
||||||
profile.save()
|
profile.save()
|
||||||
@@ -81,6 +98,11 @@ class UserProfile(models.Model):
|
|||||||
Subscription.objects.create(user_profile=profile, recipient=recipient)
|
Subscription.objects.create(user_profile=profile, recipient=recipient)
|
||||||
return profile
|
return profile
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return (u"<UserProfile: %s %s>" % (self.user.email, self.realm)).encode("utf-8")
|
||||||
|
def __str__(self):
|
||||||
|
return self.__repr__()
|
||||||
|
|
||||||
# Make sure we flush the UserProfile object from our memcached
|
# Make sure we flush the UserProfile object from our memcached
|
||||||
# whenever we save it.
|
# whenever we save it.
|
||||||
post_save.connect(update_user_profile_cache, sender=UserProfile)
|
post_save.connect(update_user_profile_cache, sender=UserProfile)
|
||||||
|
|||||||
Reference in New Issue
Block a user