-
Notifications
You must be signed in to change notification settings - Fork 47
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
1104 add useraffiliation to the base user model #1126
Merged
Merged
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
affc746
add profile model
jchate6 a8d6142
add signals to update and create profiles when users are saved.
jchate6 5f7cf90
fix naming issue
jchate6 f046f4e
create profile if none exists when trying to save User
jchate6 6bd8604
display verbose name for profile fields
jchate6 021f9e8
remove general signals registration.
jchate6 d7fa21a
add formset stuff to tests for user creation
jchate6 f6f7941
add test for verbose name exception
jchate6 1c7c670
be more specific
jchate6 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
from django.contrib import admin | ||
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin | ||
from django.contrib.auth.models import User | ||
|
||
from tom_common.models import Profile | ||
|
||
|
||
# Define an inline admin descriptor for the TomUser model | ||
# which acts a bit like a singleton | ||
class TomUserInline(admin.StackedInline): | ||
model = Profile | ||
can_delete = False | ||
verbose_name_plural = "profiles" | ||
|
||
|
||
# Define a new User admin | ||
class UserAdmin(BaseUserAdmin): | ||
inlines = [TomUserInline] | ||
|
||
|
||
# Re-register UserAdmin | ||
admin.site.unregister(User) | ||
admin.site.register(User, UserAdmin) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# Generated by Django 4.2.16 on 2024-11-22 22:08 | ||
|
||
from django.conf import settings | ||
from django.db import migrations, models | ||
import django.db.models.deletion | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
initial = True | ||
|
||
dependencies = [ | ||
migrations.swappable_dependency(settings.AUTH_USER_MODEL), | ||
] | ||
|
||
operations = [ | ||
migrations.CreateModel( | ||
name='Profile', | ||
fields=[ | ||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | ||
('affiliation', models.CharField(blank=True, max_length=100, null=True)), | ||
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), | ||
], | ||
), | ||
] |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,21 @@ | ||
from django.conf import settings | ||
from django.db.models.signals import post_save | ||
from django.db import models | ||
from django.dispatch import receiver | ||
from django.contrib.auth.models import User | ||
from rest_framework.authtoken.models import Token | ||
|
||
|
||
@receiver(post_save, sender=settings.AUTH_USER_MODEL) | ||
def create_auth_token(sender, instance=None, created=False, **kwargs): | ||
if created: | ||
Token.objects.create(user=instance) | ||
|
||
|
||
class Profile(models.Model): | ||
"""Profile model for a TOMToolkit User""" | ||
user = models.OneToOneField(User, on_delete=models.CASCADE) | ||
affiliation = models.CharField(max_length=100, null=True, blank=True) | ||
|
||
def __str__(self): | ||
return f'{self.user.username} Profile' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
from django.db.models.signals import post_save | ||
from django.contrib.auth.models import User | ||
from django.dispatch import receiver | ||
from tom_common.models import Profile | ||
|
||
|
||
@receiver(post_save, sender=User) | ||
def create_profile(sender, instance, created, **kwargs): | ||
"""When a new user is created, create a profile for them.""" | ||
if created: | ||
Profile.objects.create(user=instance) | ||
|
||
|
||
@receiver(post_save, sender=User) | ||
def save_profile(sender, instance, **kwargs): | ||
"""When a user is saved, save their profile.""" | ||
# Take advantage of the fact that logging in updates a user's last_login field | ||
# to create a profile for users that don't have one. | ||
try: | ||
instance.profile.save() | ||
except User.profile.RelatedObjectDoesNotExist: | ||
Profile.objects.create(user=instance) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,6 +9,7 @@ | |
from django_comments.models import Comment | ||
|
||
from tom_targets.tests.factories import SiderealTargetFactory | ||
from tom_common.templatetags.tom_common_extras import verbose_name | ||
|
||
|
||
class TestCommonViews(TestCase): | ||
|
@@ -26,6 +27,17 @@ def test_index(self): | |
self.assertEqual(response.status_code, 200) | ||
|
||
|
||
class TestCommonExtras(TestCase): | ||
def setUp(self): | ||
pass | ||
|
||
def test_verbose_name(self): | ||
# Check that the verbose name for a model field is returned correctly | ||
self.assertEqual(verbose_name(User, 'email'), 'Email Address') | ||
# Check that the verbose name for a non-existent field is returned correctly | ||
self.assertEqual(verbose_name(User, 'definitely_not_a_field'), 'Definitely_Not_A_Field') | ||
|
||
|
||
class TestUserManagement(TestCase): | ||
def setUp(self): | ||
self.admin = User.objects.create_superuser(username='admin', password='admin', email='[email protected]') | ||
|
@@ -38,6 +50,8 @@ def test_user_list(self): | |
|
||
def test_user_create(self): | ||
user_data = { | ||
'profile-TOTAL_FORMS': '1', | ||
'profile-INITIAL_FORMS': '0', | ||
'username': 'testuser', | ||
'first_name': 'first', | ||
'last_name': 'last', | ||
|
@@ -83,6 +97,8 @@ def test_user_can_update_self(self): | |
user = User.objects.create(username='luke', password='forc3') | ||
self.client.force_login(user) | ||
user_data = { | ||
'profile-TOTAL_FORMS': '1', | ||
'profile-INITIAL_FORMS': '0', | ||
'username': 'luke', | ||
'first_name': 'Luke', | ||
'last_name': 'Skywalker', | ||
|
@@ -99,6 +115,8 @@ def test_user_cannot_update_other(self): | |
user = User.objects.create(username='luke', password='forc3') | ||
self.client.force_login(user) | ||
user_data = { | ||
'profile-TOTAL_FORMS': '1', | ||
'profile-INITIAL_FORMS': '0', | ||
'username': 'luke', | ||
'first_name': 'Luke', | ||
'last_name': 'Skywalker', | ||
|
@@ -111,6 +129,37 @@ def test_user_cannot_update_other(self): | |
self.assertRedirects(response, reverse('user-update', kwargs={'pk': user.id})) | ||
self.assertNotEqual(self.admin.username, user_data['username']) | ||
|
||
def test_user_can_delete_self(self): | ||
user = User.objects.create(username='luke', password='forc3') | ||
self.client.force_login(user) | ||
self.assertTrue(User.objects.filter(username='luke').exists()) | ||
response = self.client.post(reverse('user-delete', kwargs={'pk': user.id}), follow=True) | ||
self.assertEqual(response.status_code, 200) | ||
self.assertFalse(User.objects.filter(username='luke').exists()) | ||
|
||
|
||
class TestUserProfile(TestCase): | ||
def setUp(self): | ||
self.admin = User.objects.create_superuser(username='admin', password='admin', email='[email protected]') | ||
self.client.force_login(self.admin) | ||
|
||
def test_user_profile(self): | ||
user_data = { | ||
'profile-TOTAL_FORMS': '1', | ||
'profile-INITIAL_FORMS': '0', | ||
'username': 'testuser', | ||
'first_name': 'first', | ||
'last_name': 'last', | ||
'email': '[email protected]', | ||
'password1': 'suchsecure543', | ||
'password2': 'suchsecure543', | ||
'profile-0-affiliation': 'Test University', | ||
} | ||
response = self.client.post(reverse('user-create'), data=user_data, follow=True) | ||
self.assertEqual(response.status_code, 200) | ||
user = User.objects.get(username='testuser') | ||
self.assertEqual(user.profile.affiliation, 'Test University') | ||
|
||
|
||
class TestAuthScheme(TestCase): | ||
@override_settings(AUTH_STRATEGY='LOCKED') | ||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We changed the user creation form to a formset, so we need to include the profile ManagementForm data here or it will get angry.