Skip to content

Commit a61aad6

Browse files
committed
User advertiser member check and constraint
I hit this extremely minor bug in production. If you try to add the same user again as an authorized user on an advertiser, you hit a DB constraint (500 error). That's because the constraint added here exists in production but not in the model. That is because at first the UserAdvertiserMember model was just an automatic table and then we added a new column to the table via migration. This adds a secondary check to ensure we don't try to add the same user again and adds the constraint in development. Hopefully there isn't an issue adding that constraint again in prod or we could fake the migration if desired since the constraint already exists.
1 parent 2fabb1b commit a61aad6

File tree

4 files changed

+31
-7
lines changed

4 files changed

+31
-7
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Generated by Django 5.2.7 on 2025-11-01 16:57
2+
3+
from django.db import migrations
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('adserver', '0104_auto_renew_payment_method'),
10+
('adserver_auth', '0010_data_all_emails_verified'),
11+
]
12+
13+
operations = [
14+
migrations.AlterUniqueTogether(
15+
name='useradvertisermember',
16+
unique_together={('user', 'advertiser')},
17+
),
18+
]

adserver/auth/models.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,8 @@ class Meta:
255255
# To do that, we needed to start with the same table
256256
db_table = "adserver_auth_user_advertisers"
257257

258+
unique_together = ("user", "advertiser")
259+
258260

259261
class UserPublisherMember(models.Model):
260262
"""User-Publisher 'through' model."""

adserver/tests/test_advertiser_dashboard.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1252,6 +1252,7 @@ def test_authorized_users_invite_existing(self):
12521252
self.assertContains(response, "Successfully invited")
12531253
self.assertEqual(User.objects.filter(email=email).count(), 1)
12541254
self.assertEqual(User.objects.filter(name=name).count(), 1)
1255+
self.assertEqual(UserAdvertiserMember.objects.filter(advertiser=self.advertiser, user__email=email).count(), 1)
12551256

12561257
# The 2nd request didn't create a user or update the user's name
12571258
self.assertEqual(User.objects.filter(name="Yet Another User").count(), 0)

adserver/views.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1857,13 +1857,16 @@ def dispatch(self, request, *args, **kwargs):
18571857
def form_valid(self, form):
18581858
result = super().form_valid(form)
18591859

1860-
# Add m2m and role
1861-
role = form.cleaned_data["role"]
1862-
UserAdvertiserMember.objects.create(
1863-
advertiser=self.advertiser,
1864-
user=self.object,
1865-
role=role,
1866-
)
1860+
if not UserAdvertiserMember.objects.filter(
1861+
advertiser=self.advertiser, user=self.object
1862+
).exists():
1863+
# Add m2m and role
1864+
role = form.cleaned_data["role"]
1865+
UserAdvertiserMember.objects.create(
1866+
advertiser=self.advertiser,
1867+
user=self.object,
1868+
role=role,
1869+
)
18671870

18681871
messages.success(
18691872
self.request,

0 commit comments

Comments
 (0)