-
-
Notifications
You must be signed in to change notification settings - Fork 156
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: Change User
class in backend/models.py
to use email as uniqu…
#368
Conversation
Hi @James-Makela, just wondering if this will be worked on further at any point? |
Hi Trey, unfortunately I am flat out for the next couple of weeks. I could continue after that. However if you or anyone else wants to take over that is cool too. |
Update:
Next Steps:
Questions:
|
Hey @James-Makela, what you said sounds good. As for the user class, we have a custom one already in models.py so you can override parts of that if that's what you mean? Let me know if you have any more questions, great work though :) |
Ah yes, that appears to be what I am doing. I have gone through some testing today, Setting up from scratch after moving to test the branch for this fix. Tests Involved:
|
Hi @James-Makela, sorry I missed the PR update. Anything you need me to do at this point? I appreciate your patience |
Hi Trey, I made a little progress on this. I have extended the Alternatively I have tried to change the GlobalUserModel = apps.get_model(
self.model._meta.app_label, self.model._meta.object_name
)
username = GlobalUserModel.normalize_username(username) Here is my current state of the extended class CustomUserManager(BaseUserManager):
def _create_user(self, email, password, **extra_fields):
if not email:
raise ValueError("The given email must be set")
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self, email, password=None, **extra_fields):
extra_fields.setdefault("is_staff", False)
extra_fields.setdefault('is_superuser', False)
return self._create_user(email, password, **extra_fields)
def create_superuser(self, email, password=None, **extra_fields):
extra_fields.setdefault("is_staff", True)
extra_fields.setdefault("is_superuser", True)
if extra_fields.get("is_staff") is not True:
raise ValueError("Superuser must have is_staff=True.")
if extra_fields.get("is_superuser") is not True:
raise ValueError("Superuser must have is_superuser=True.")
return self._create_user(email, password, **extra_fields)
def get_queryset(self):
return (
super()
.get_queryset()
.select_related("user_profile", "logged_in_as_team")
.annotate(notification_count=(Count("user_notifications")))
) I feel like its almost there but I will need advice on whether you want to go in the direction of no usernames at all, or enforced unique usernames, as well as unique emails, and whether I am hopefully on the right track here. |
I'm wondering if in models.py class User you could just add username and email fields manually and add unique=True and Django might do the rest |
Trying that, with the whole user class as: class User(AbstractUser):
objects = CustomUserManager() # type: ignore
email = models.EmailField(max_length=150, unique=True)
username = models.CharField(max_length=150, unique=True)
USERNAME_FIELD = "email"
REQUIRED_FIELDS = ["username"]
logged_in_as_team = models.ForeignKey("Team", on_delete=models.SET_NULL, null=True, blank=True)
awaiting_email_verification = models.BooleanField(default=True)
class Role(models.TextChoices):
# NAME DJANGO ADMIN NAME
DEV = "DEV", "Developer"
STAFF = "STAFF", "Staff"
USER = "USER", "User"
TESTER = "TESTER", "Tester"
role = models.CharField(max_length=10, choices=Role.choices, default=Role.USER) Strangely this results in allowing the user to enter a non-unique username without error, then crashes while trying to store the data in the database:
|
Ah yeah, that's cause we don't do validation in the create account view. We'd have to just add User.objects.filter and check if one exists |
Line 71 backend/views/core/auth/create_account.py should handle it... hmm |
I notice backend/views/core/auth/create_account.py at line 81 sets the username to be the email.
def _create_user(self, email, password, **extra_fields):
if not email:
raise ValueError("The given email must be set")
email = self.normalize_email(email)
user = self.model(email=email, username=email, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user |
…e field.
Description
Here I have made changes to the
User
Model inbackend/models.py
. The changes make the email field unique, and required, rather than the username. At this stage, some other things will still need working out. All local tests have passed so far. I am open to creating some new tests to test the structure and behavior of the user model, but not sure how to go about that yet.To Do
Logged in as
no longer displaying anythingChecklist
djLint-er on any new code
(checks
will
fail without)
changes
What type of PR is this?
Helpful Info Found Along the Way
Added/updated tests?
Related PRs, Issues etc