Send user-modified only to webhooks of relevant OAuth apps #93585
@ -49,6 +49,7 @@ class WebhookAdmin(ModelAdmin):
|
|||||||
list_display = (
|
list_display = (
|
||||||
"name",
|
"name",
|
||||||
"hook_type",
|
"hook_type",
|
||||||
|
"app",
|
||||||
"url",
|
"url",
|
||||||
"enabled",
|
"enabled",
|
||||||
)
|
)
|
||||||
|
21
bid_api/migrations/0010_alter_webhook_app.py
Normal file
21
bid_api/migrations/0010_alter_webhook_app.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# Generated by Django 3.2.9 on 2024-06-17 06:57
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.OAUTH2_PROVIDER_APPLICATION_MODEL),
|
||||||
|
('bid_api', '0009_remove_webhook_last_flush_attempt'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='webhook',
|
||||||
|
name='app',
|
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='webhooks', to='bid_main.oauth2application'),
|
||||||
|
),
|
||||||
|
]
|
@ -36,8 +36,6 @@ class Webhook(models.Model):
|
|||||||
)
|
)
|
||||||
app = models.ForeignKey(
|
app = models.ForeignKey(
|
||||||
'bid_main.OAuth2Application',
|
'bid_main.OAuth2Application',
|
||||||
null=True,
|
|
||||||
blank=True,
|
|
||||||
related_name="webhooks",
|
related_name="webhooks",
|
||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
)
|
)
|
||||||
|
@ -100,9 +100,10 @@ def inspect_modified_user(sender, user: UserModel, **kwargs):
|
|||||||
|
|
||||||
@receiver(post_save)
|
@receiver(post_save)
|
||||||
@filter_user_save_hook
|
@filter_user_save_hook
|
||||||
def modified_user_to_webhooks(sender, user: UserModel, **kwargs):
|
def handle_modifications(sender, user: UserModel, **kwargs):
|
||||||
"""Forwards modified user information to webhooks.
|
"""Act on various account modifications.
|
||||||
|
|
||||||
|
Clean up orphaned avatars, notify about email change and call webhooks.
|
||||||
The payload is POSTed, and a HMAC-SHA256 checksum is sent using the
|
The payload is POSTed, and a HMAC-SHA256 checksum is sent using the
|
||||||
X-Webhook-HMAC HTTP header.
|
X-Webhook-HMAC HTTP header.
|
||||||
|
|
||||||
@ -116,9 +117,6 @@ def modified_user_to_webhooks(sender, user: UserModel, **kwargs):
|
|||||||
# log.debug('Skipping save of %s', user.email)
|
# log.debug('Skipping save of %s', user.email)
|
||||||
return
|
return
|
||||||
|
|
||||||
hooks = models.Webhook.objects.filter(enabled=True)
|
|
||||||
log.debug("Sending modification of %s to %d webhooks", user.email, len(hooks))
|
|
||||||
|
|
||||||
# Get the old email address so that the webhook receiver can match by
|
# Get the old email address so that the webhook receiver can match by
|
||||||
# either database ID or email address.
|
# either database ID or email address.
|
||||||
webhook_pre_save = getattr(user, "webhook_pre_save", {})
|
webhook_pre_save = getattr(user, "webhook_pre_save", {})
|
||||||
@ -145,6 +143,19 @@ def modified_user_to_webhooks(sender, user: UserModel, **kwargs):
|
|||||||
log.debug("User changed email from %s to %s", old_email, user.email)
|
log.debug("User changed email from %s to %s", old_email, user.email)
|
||||||
user_email_changed.send(sender, user=user, old_email=old_email)
|
user_email_changed.send(sender, user=user, old_email=old_email)
|
||||||
|
|
||||||
|
hooks = list(
|
||||||
|
models.Webhook.objects.filter(enabled=True).filter(
|
||||||
|
app__in=user.bid_main_oauth2accesstoken.distinct().values_list('application', flat=True)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
hooks_count = len(hooks)
|
||||||
|
if hooks_count == 0:
|
||||||
|
log.info('Not sending modification of pk=%d to any webhooks', user.pk)
|
||||||
|
return
|
||||||
|
|
||||||
|
log.info("Sending modification of pk=%d to %d webhooks", user.pk, hooks_count)
|
||||||
|
|
||||||
# Do our own JSON encoding so that we can compute the HMAC using the hook's secret.
|
# Do our own JSON encoding so that we can compute the HMAC using the hook's secret.
|
||||||
payload = {
|
payload = {
|
||||||
"id": user.id,
|
"id": user.id,
|
||||||
|
@ -11,7 +11,7 @@ from freezegun import freeze_time
|
|||||||
import responses
|
import responses
|
||||||
|
|
||||||
from .abstract import UserModel
|
from .abstract import UserModel
|
||||||
from bid_main.models import Role
|
from bid_main.models import Role, OAuth2Application
|
||||||
from bid_api import models
|
from bid_api import models
|
||||||
import bid_api.tasks as tasks
|
import bid_api.tasks as tasks
|
||||||
|
|
||||||
@ -48,19 +48,24 @@ def _call_task_directly(*args, **kwargs):
|
|||||||
new=_call_task_directly,
|
new=_call_task_directly,
|
||||||
)
|
)
|
||||||
class WebhookTest(TestCase):
|
class WebhookTest(TestCase):
|
||||||
HOOK_URL = "http://www.unit.test/api/webhook"
|
HOOK_URLS = [
|
||||||
|
"http://www.unit.test/api/webhook/",
|
||||||
|
"http://www.yet-another-unit.test/api/webhook/",
|
||||||
|
]
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.hook = models.Webhook(
|
self.oauth_app = OAuth2Application.objects.create()
|
||||||
|
self.hook = models.Webhook.objects.create(
|
||||||
|
app=self.oauth_app,
|
||||||
name="Unit test webhook",
|
name="Unit test webhook",
|
||||||
enabled=True,
|
enabled=True,
|
||||||
hook_type="USER_MODIFIED",
|
hook_type="USER_MODIFIED",
|
||||||
url=self.HOOK_URL,
|
url=self.HOOK_URLS[0],
|
||||||
secret="ieBithiGhahh4hee5mac8zu0xiu8kae0",
|
secret="ieBithiGhahh4hee5mac8zu0xiu8kae0",
|
||||||
)
|
)
|
||||||
self.hook.save()
|
|
||||||
responses.start()
|
responses.start()
|
||||||
responses.add(responses.POST, self.HOOK_URL, json={"status": "success"}, status=200)
|
responses.add(responses.POST, self.HOOK_URLS[0], json={"status": "success"}, status=200)
|
||||||
|
responses.add(responses.POST, self.HOOK_URLS[1], json={"status": "success"}, status=200)
|
||||||
super().setUp()
|
super().setUp()
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
@ -69,6 +74,10 @@ class WebhookTest(TestCase):
|
|||||||
|
|
||||||
def test_modify_user_email_only(self):
|
def test_modify_user_email_only(self):
|
||||||
user = UserModel.objects.create_user("test@user.com", "123456")
|
user = UserModel.objects.create_user("test@user.com", "123456")
|
||||||
|
user.bid_main_oauth2accesstoken.create(
|
||||||
|
application=self.oauth_app, expires='2024-01-01 01:01:01'
|
||||||
|
)
|
||||||
|
|
||||||
user.email = "new@user.com"
|
user.email = "new@user.com"
|
||||||
user.save(update_fields={"email"})
|
user.save(update_fields={"email"})
|
||||||
self.assertEqual(user.public_roles_as_string, "")
|
self.assertEqual(user.public_roles_as_string, "")
|
||||||
@ -77,7 +86,7 @@ class WebhookTest(TestCase):
|
|||||||
|
|
||||||
self.assertEqual(1, len(responses.calls))
|
self.assertEqual(1, len(responses.calls))
|
||||||
call = responses.calls[0]
|
call = responses.calls[0]
|
||||||
self.assertEqual(self.HOOK_URL, call.request.url)
|
self.assertEqual(self.HOOK_URLS[0], call.request.url)
|
||||||
|
|
||||||
payload = json.loads(call.request.body)
|
payload = json.loads(call.request.body)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
@ -106,8 +115,81 @@ class WebhookTest(TestCase):
|
|||||||
self.assertEqual(hexdigest, call.request.headers["X-Webhook-HMAC"])
|
self.assertEqual(hexdigest, call.request.headers["X-Webhook-HMAC"])
|
||||||
self.assertEqual("application/json", call.request.headers["Content-Type"])
|
self.assertEqual("application/json", call.request.headers["Content-Type"])
|
||||||
|
|
||||||
|
def test_modify_user_email_and_full_name_not_sent_because_no_oauth_apps_linked_to_user(self):
|
||||||
|
user = UserModel.objects.create_user("test@user.com", "123456")
|
||||||
|
|
||||||
|
user.email = "new@user.com"
|
||||||
|
user.full_name = "ဖန်စီဘောင်းဘီ"
|
||||||
|
user.save()
|
||||||
|
|
||||||
|
self.assertTrue(user.webhook_user_modified)
|
||||||
|
|
||||||
|
self.assertEqual(0, len(responses.calls))
|
||||||
|
|
||||||
|
def test_modify_user_email_and_full_name_only_sent_to_hooks_linked_to_oauth_app(self):
|
||||||
|
another_oauth_app1 = OAuth2Application.objects.create()
|
||||||
|
models.Webhook.objects.create(
|
||||||
|
app=another_oauth_app1,
|
||||||
|
name="Another webhook linked to a different OAuth app",
|
||||||
|
enabled=True,
|
||||||
|
hook_type="USER_MODIFIED",
|
||||||
|
url="http://www.another-unit.test/api/another-webhook/",
|
||||||
|
secret="asdfasdfasdfasfdasdfasdfas",
|
||||||
|
)
|
||||||
|
another_oauth_app2 = OAuth2Application.objects.create()
|
||||||
|
models.Webhook.objects.create(
|
||||||
|
app=another_oauth_app2,
|
||||||
|
name="Yet another webhook linked to a different OAuth app",
|
||||||
|
enabled=True,
|
||||||
|
hook_type="USER_MODIFIED",
|
||||||
|
url=self.HOOK_URLS[1],
|
||||||
|
secret="asdfasdfasdfasfdasdfasdfas",
|
||||||
|
)
|
||||||
|
models.Webhook.objects.create(
|
||||||
|
app=self.oauth_app,
|
||||||
|
name="Disabled webhook of the same OAuth app",
|
||||||
|
enabled=False,
|
||||||
|
hook_type="USER_MODIFIED",
|
||||||
|
url='http://example.com/disabled-webhook/',
|
||||||
|
secret="asdfasdfasasd12asdfasdfas",
|
||||||
|
)
|
||||||
|
user = UserModel.objects.create_user("test@user.com", "123456")
|
||||||
|
user.bid_main_oauth2accesstoken.create(
|
||||||
|
application=self.oauth_app, expires='2024-01-01 01:01:01', token='foobar1'
|
||||||
|
)
|
||||||
|
user.bid_main_oauth2accesstoken.create(
|
||||||
|
application=another_oauth_app2, expires='2024-01-01 01:01:01', token='fooobar2'
|
||||||
|
)
|
||||||
|
|
||||||
|
user.email = "new@user.com"
|
||||||
|
user.full_name = "ဖန်စီဘောင်းဘီ"
|
||||||
|
user.save()
|
||||||
|
|
||||||
|
self.assertTrue(user.webhook_user_modified)
|
||||||
|
|
||||||
|
self.assertEqual(2, len(responses.calls))
|
||||||
|
expected_payload = {
|
||||||
|
"id": user.id,
|
||||||
|
"old_email": "test@user.com",
|
||||||
|
"full_name": "ဖန်စီဘောင်းဘီ",
|
||||||
|
"email": "new@user.com",
|
||||||
|
"roles": [],
|
||||||
|
"avatar_changed": False,
|
||||||
|
"avatar_url": None,
|
||||||
|
"date_deletion_requested": None,
|
||||||
|
"confirmed_email_at": None,
|
||||||
|
"nickname": "",
|
||||||
|
"old_nickname": "",
|
||||||
|
}
|
||||||
|
self.assertEqual(expected_payload, json.loads(responses.calls[0].request.body))
|
||||||
|
self.assertEqual(expected_payload, json.loads(responses.calls[1].request.body))
|
||||||
|
|
||||||
def test_modify_user_email_and_full_name(self):
|
def test_modify_user_email_and_full_name(self):
|
||||||
user = UserModel.objects.create_user("test@user.com", "123456")
|
user = UserModel.objects.create_user("test@user.com", "123456")
|
||||||
|
user.bid_main_oauth2accesstoken.create(
|
||||||
|
application=self.oauth_app, expires='2024-01-01 01:01:01'
|
||||||
|
)
|
||||||
|
|
||||||
user.email = "new@user.com"
|
user.email = "new@user.com"
|
||||||
user.full_name = "ဖန်စီဘောင်းဘီ"
|
user.full_name = "ဖန်စီဘောင်းဘီ"
|
||||||
user.save()
|
user.save()
|
||||||
@ -135,6 +217,10 @@ class WebhookTest(TestCase):
|
|||||||
|
|
||||||
def test_modify_user_nickname(self):
|
def test_modify_user_nickname(self):
|
||||||
user = UserModel.objects.create_user("test@user.com", "123456")
|
user = UserModel.objects.create_user("test@user.com", "123456")
|
||||||
|
user.bid_main_oauth2accesstoken.create(
|
||||||
|
application=self.oauth_app, expires='2024-01-01 01:01:01'
|
||||||
|
)
|
||||||
|
|
||||||
user.nickname = "propellorolleporp"
|
user.nickname = "propellorolleporp"
|
||||||
user.save()
|
user.save()
|
||||||
|
|
||||||
@ -184,6 +270,10 @@ class WebhookTest(TestCase):
|
|||||||
my_dir = pathlib.Path(__file__).absolute().parent
|
my_dir = pathlib.Path(__file__).absolute().parent
|
||||||
with self.settings(MEDIA_ROOT=my_dir / "media"):
|
with self.settings(MEDIA_ROOT=my_dir / "media"):
|
||||||
user = UserModel.objects.create_user("test@user.com", "123456")
|
user = UserModel.objects.create_user("test@user.com", "123456")
|
||||||
|
user.bid_main_oauth2accesstoken.create(
|
||||||
|
application=self.oauth_app, expires='2024-01-01 01:01:01'
|
||||||
|
)
|
||||||
|
|
||||||
user.avatar = "images/t-rex.png"
|
user.avatar = "images/t-rex.png"
|
||||||
user.save()
|
user.save()
|
||||||
|
|
||||||
@ -210,6 +300,10 @@ class WebhookTest(TestCase):
|
|||||||
|
|
||||||
def test_modify_user_add_role(self):
|
def test_modify_user_add_role(self):
|
||||||
user = UserModel.objects.create_user("test@user.com", "123456", full_name="ဖန်စီဘောင်းဘီ")
|
user = UserModel.objects.create_user("test@user.com", "123456", full_name="ဖန်စီဘောင်းဘီ")
|
||||||
|
user.bid_main_oauth2accesstoken.create(
|
||||||
|
application=self.oauth_app, expires='2024-01-01 01:01:01'
|
||||||
|
)
|
||||||
|
|
||||||
role1 = Role(name="cloud_subscriber", is_public=True, is_badge=True, is_active=True)
|
role1 = Role(name="cloud_subscriber", is_public=True, is_badge=True, is_active=True)
|
||||||
role1.save()
|
role1.save()
|
||||||
role2 = Role(name="admin", is_public=False, is_badge=False, is_active=True)
|
role2 = Role(name="admin", is_public=False, is_badge=False, is_active=True)
|
||||||
@ -271,6 +365,10 @@ class WebhookTest(TestCase):
|
|||||||
@freeze_time('2021-01-01T01:02:03+02:00')
|
@freeze_time('2021-01-01T01:02:03+02:00')
|
||||||
def test_modify_date_deletion_requested(self):
|
def test_modify_date_deletion_requested(self):
|
||||||
user = UserModel.objects.create_user("test@user.com", "123456")
|
user = UserModel.objects.create_user("test@user.com", "123456")
|
||||||
|
user.bid_main_oauth2accesstoken.create(
|
||||||
|
application=self.oauth_app, expires='2024-01-01 01:01:01'
|
||||||
|
)
|
||||||
|
|
||||||
user.date_deletion_requested = timezone.now()
|
user.date_deletion_requested = timezone.now()
|
||||||
user.save(update_fields={"date_deletion_requested"})
|
user.save(update_fields={"date_deletion_requested"})
|
||||||
|
|
||||||
@ -278,7 +376,7 @@ class WebhookTest(TestCase):
|
|||||||
|
|
||||||
self.assertEqual(1, len(responses.calls))
|
self.assertEqual(1, len(responses.calls))
|
||||||
call = responses.calls[0]
|
call = responses.calls[0]
|
||||||
self.assertEqual(self.HOOK_URL, call.request.url)
|
self.assertEqual(self.HOOK_URLS[0], call.request.url)
|
||||||
|
|
||||||
payload = json.loads(call.request.body)
|
payload = json.loads(call.request.body)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
@ -301,6 +399,10 @@ class WebhookTest(TestCase):
|
|||||||
@freeze_time('2021-01-01T04:05:06+02:00')
|
@freeze_time('2021-01-01T04:05:06+02:00')
|
||||||
def test_modify_confirmed_email_at(self):
|
def test_modify_confirmed_email_at(self):
|
||||||
user = UserModel.objects.create_user("test@user.com", "123456")
|
user = UserModel.objects.create_user("test@user.com", "123456")
|
||||||
|
user.bid_main_oauth2accesstoken.create(
|
||||||
|
application=self.oauth_app, expires='2024-01-01 01:01:01'
|
||||||
|
)
|
||||||
|
|
||||||
user.confirmed_email_at = timezone.now()
|
user.confirmed_email_at = timezone.now()
|
||||||
user.save(update_fields={"confirmed_email_at"})
|
user.save(update_fields={"confirmed_email_at"})
|
||||||
|
|
||||||
@ -308,7 +410,7 @@ class WebhookTest(TestCase):
|
|||||||
|
|
||||||
self.assertEqual(1, len(responses.calls))
|
self.assertEqual(1, len(responses.calls))
|
||||||
call = responses.calls[0]
|
call = responses.calls[0]
|
||||||
self.assertEqual(self.HOOK_URL, call.request.url)
|
self.assertEqual(self.HOOK_URLS[0], call.request.url)
|
||||||
|
|
||||||
payload = json.loads(call.request.body)
|
payload = json.loads(call.request.body)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
@ -375,19 +477,24 @@ class WebhookQueuedAsTaskTest(TestCase):
|
|||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.maxDiff = None
|
self.maxDiff = None
|
||||||
self.hook = models.Webhook(
|
self.oauth_app = OAuth2Application.objects.create()
|
||||||
|
self.hook = models.Webhook.objects.create(
|
||||||
|
app=self.oauth_app,
|
||||||
name="Unit test webhook",
|
name="Unit test webhook",
|
||||||
enabled=True,
|
enabled=True,
|
||||||
hook_type="USER_MODIFIED",
|
hook_type="USER_MODIFIED",
|
||||||
url=self.HOOK_URL,
|
url=self.HOOK_URL,
|
||||||
secret="ieBithiGhahh4hee5mac8zu0xiu8kae0",
|
secret="ieBithiGhahh4hee5mac8zu0xiu8kae0",
|
||||||
)
|
)
|
||||||
self.hook.save()
|
|
||||||
super().setUp()
|
super().setUp()
|
||||||
self.assertEqual(Task.objects.count(), 0)
|
self.assertEqual(Task.objects.count(), 0)
|
||||||
|
|
||||||
def test_modify_user_email_only(self):
|
def test_modify_user_email_only(self):
|
||||||
user = UserModel.objects.create_user("test@user.com", "123456")
|
user = UserModel.objects.create_user("test@user.com", "123456")
|
||||||
|
user.bid_main_oauth2accesstoken.create(
|
||||||
|
application=self.oauth_app, expires='2024-01-01 01:01:01'
|
||||||
|
)
|
||||||
|
|
||||||
user.email = "new@user.com"
|
user.email = "new@user.com"
|
||||||
user.save(update_fields={"email"})
|
user.save(update_fields={"email"})
|
||||||
self.assertEqual(user.public_roles_as_string, "")
|
self.assertEqual(user.public_roles_as_string, "")
|
||||||
@ -417,8 +524,77 @@ class WebhookQueuedAsTaskTest(TestCase):
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_modify_user_email_and_full_name_not_sent_because_no_oauth_apps_linked_to_user(self):
|
||||||
|
user = UserModel.objects.create_user("test@user.com", "123456")
|
||||||
|
|
||||||
|
user.email = "new@user.com"
|
||||||
|
user.full_name = "ဖန်စီဘောင်းဘီ"
|
||||||
|
user.save()
|
||||||
|
|
||||||
|
self.assertTrue(user.webhook_user_modified)
|
||||||
|
|
||||||
|
self.assertEqual(Task.objects.count(), 0)
|
||||||
|
|
||||||
|
def test_modify_user_email_and_full_name_only_sent_to_hook_linked_to_oauth_app(self):
|
||||||
|
another_oauth_app = OAuth2Application.objects.create()
|
||||||
|
models.Webhook.objects.create(
|
||||||
|
app=another_oauth_app,
|
||||||
|
name="Unit test webhook linked to a different OAuth app",
|
||||||
|
enabled=True,
|
||||||
|
hook_type="USER_MODIFIED",
|
||||||
|
url="http://www.some-other-unit.test/api/another-webhook/",
|
||||||
|
secret="asdfasdfasdfasfdasdfasdfas",
|
||||||
|
)
|
||||||
|
models.Webhook.objects.create(
|
||||||
|
app=self.oauth_app,
|
||||||
|
name="Disabled webhook of the same OAuth app",
|
||||||
|
enabled=False,
|
||||||
|
hook_type="USER_MODIFIED",
|
||||||
|
url=self.HOOK_URL,
|
||||||
|
secret="asdfasdfasasd12asdfasdfas",
|
||||||
|
)
|
||||||
|
user = UserModel.objects.create_user("test@user.com", "123456")
|
||||||
|
user.bid_main_oauth2accesstoken.create(
|
||||||
|
application=self.oauth_app, expires='2024-01-01 01:01:01'
|
||||||
|
)
|
||||||
|
|
||||||
|
user.email = "new@user.com"
|
||||||
|
user.full_name = "ဖန်စီဘောင်းဘီ"
|
||||||
|
user.save()
|
||||||
|
|
||||||
|
self.assertTrue(user.webhook_user_modified)
|
||||||
|
|
||||||
|
self.assertEqual(Task.objects.count(), 1)
|
||||||
|
task = Task.objects.first()
|
||||||
|
self.assertEqual(
|
||||||
|
json.loads(task.task_params),
|
||||||
|
[
|
||||||
|
[
|
||||||
|
self.hook.pk,
|
||||||
|
{
|
||||||
|
"id": user.id,
|
||||||
|
"old_email": "test@user.com",
|
||||||
|
"full_name": "ဖန်စီဘောင်းဘီ",
|
||||||
|
"email": "new@user.com",
|
||||||
|
"roles": [],
|
||||||
|
"avatar_changed": False,
|
||||||
|
"avatar_url": None,
|
||||||
|
"date_deletion_requested": None,
|
||||||
|
"confirmed_email_at": None,
|
||||||
|
"nickname": "",
|
||||||
|
"old_nickname": "",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
{},
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
def test_modify_user_email_and_full_name(self):
|
def test_modify_user_email_and_full_name(self):
|
||||||
user = UserModel.objects.create_user("test@user.com", "123456")
|
user = UserModel.objects.create_user("test@user.com", "123456")
|
||||||
|
user.bid_main_oauth2accesstoken.create(
|
||||||
|
application=self.oauth_app, expires='2024-01-01 01:01:01'
|
||||||
|
)
|
||||||
|
|
||||||
user.email = "new@user.com"
|
user.email = "new@user.com"
|
||||||
user.full_name = "ဖန်စီဘောင်းဘီ"
|
user.full_name = "ဖန်စီဘောင်းဘီ"
|
||||||
user.save()
|
user.save()
|
||||||
@ -450,6 +626,10 @@ class WebhookQueuedAsTaskTest(TestCase):
|
|||||||
|
|
||||||
def test_modify_user_nickname(self):
|
def test_modify_user_nickname(self):
|
||||||
user = UserModel.objects.create_user("test@user.com", "123456")
|
user = UserModel.objects.create_user("test@user.com", "123456")
|
||||||
|
user.bid_main_oauth2accesstoken.create(
|
||||||
|
application=self.oauth_app, expires='2024-01-01 01:01:01'
|
||||||
|
)
|
||||||
|
|
||||||
user.nickname = "propellorolleporp"
|
user.nickname = "propellorolleporp"
|
||||||
user.save()
|
user.save()
|
||||||
|
|
||||||
@ -509,6 +689,10 @@ class WebhookQueuedAsTaskTest(TestCase):
|
|||||||
my_dir = pathlib.Path(__file__).absolute().parent
|
my_dir = pathlib.Path(__file__).absolute().parent
|
||||||
with self.settings(MEDIA_ROOT=my_dir / "media"):
|
with self.settings(MEDIA_ROOT=my_dir / "media"):
|
||||||
user = UserModel.objects.create_user("test@user.com", "123456")
|
user = UserModel.objects.create_user("test@user.com", "123456")
|
||||||
|
user.bid_main_oauth2accesstoken.create(
|
||||||
|
application=self.oauth_app, expires='2024-01-01 01:01:01'
|
||||||
|
)
|
||||||
|
|
||||||
user.avatar = "images/t-rex.png"
|
user.avatar = "images/t-rex.png"
|
||||||
user.save()
|
user.save()
|
||||||
|
|
||||||
@ -538,6 +722,10 @@ class WebhookQueuedAsTaskTest(TestCase):
|
|||||||
|
|
||||||
def test_modify_user_add_role(self):
|
def test_modify_user_add_role(self):
|
||||||
user = UserModel.objects.create_user("test@user.com", "123456", full_name="ဖန်စီဘောင်းဘီ")
|
user = UserModel.objects.create_user("test@user.com", "123456", full_name="ဖန်စီဘောင်းဘီ")
|
||||||
|
user.bid_main_oauth2accesstoken.create(
|
||||||
|
application=self.oauth_app, expires='2024-01-01 01:01:01'
|
||||||
|
)
|
||||||
|
|
||||||
role1 = Role(name="cloud_subscriber", is_public=True, is_badge=True, is_active=True)
|
role1 = Role(name="cloud_subscriber", is_public=True, is_badge=True, is_active=True)
|
||||||
role1.save()
|
role1.save()
|
||||||
role2 = Role(name="admin", is_public=False, is_badge=False, is_active=True)
|
role2 = Role(name="admin", is_public=False, is_badge=False, is_active=True)
|
||||||
@ -611,6 +799,10 @@ class WebhookQueuedAsTaskTest(TestCase):
|
|||||||
@freeze_time('2021-01-01T01:02:03+02:00')
|
@freeze_time('2021-01-01T01:02:03+02:00')
|
||||||
def test_modify_date_deletion_requested(self):
|
def test_modify_date_deletion_requested(self):
|
||||||
user = UserModel.objects.create_user("test@user.com", "123456")
|
user = UserModel.objects.create_user("test@user.com", "123456")
|
||||||
|
user.bid_main_oauth2accesstoken.create(
|
||||||
|
application=self.oauth_app, expires='2024-01-01 01:01:01'
|
||||||
|
)
|
||||||
|
|
||||||
user.date_deletion_requested = timezone.now()
|
user.date_deletion_requested = timezone.now()
|
||||||
user.save(update_fields={"date_deletion_requested"})
|
user.save(update_fields={"date_deletion_requested"})
|
||||||
|
|
||||||
@ -642,6 +834,10 @@ class WebhookQueuedAsTaskTest(TestCase):
|
|||||||
@freeze_time('2021-01-01T04:05:06+02:00')
|
@freeze_time('2021-01-01T04:05:06+02:00')
|
||||||
def test_modify_confirmed_email_at(self):
|
def test_modify_confirmed_email_at(self):
|
||||||
user = UserModel.objects.create_user("test@user.com", "123456")
|
user = UserModel.objects.create_user("test@user.com", "123456")
|
||||||
|
user.bid_main_oauth2accesstoken.create(
|
||||||
|
application=self.oauth_app, expires='2024-01-01 01:01:01'
|
||||||
|
)
|
||||||
|
|
||||||
user.confirmed_email_at = timezone.now()
|
user.confirmed_email_at = timezone.now()
|
||||||
user.save(update_fields={"confirmed_email_at"})
|
user.save(update_fields={"confirmed_email_at"})
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
"model": "bid_api.webhook",
|
"model": "bid_api.webhook",
|
||||||
"pk": 8111,
|
"pk": 8111,
|
||||||
"fields": {
|
"fields": {
|
||||||
|
"app_id": 8111,
|
||||||
"description": "Webhook of Blender Extensions Development server; installed from a Django .json fixture",
|
"description": "Webhook of Blender Extensions Development server; installed from a Django .json fixture",
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"hook_type": "USER_MODIFIED",
|
"hook_type": "USER_MODIFIED",
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
"model": "bid_api.webhook",
|
"model": "bid_api.webhook",
|
||||||
"pk": 1,
|
"pk": 1,
|
||||||
"fields": {
|
"fields": {
|
||||||
|
"app_id": 1,
|
||||||
"description": "Webhook of Blender Studio Development server; installed from a Django .json fixture",
|
"description": "Webhook of Blender Studio Development server; installed from a Django .json fixture",
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"hook_type": "USER_MODIFIED",
|
"hook_type": "USER_MODIFIED",
|
||||||
|
@ -22,7 +22,7 @@ class ProcessDeletionRequestsCommandTest(TestCase):
|
|||||||
mock_anonymize.assert_not_called()
|
mock_anonymize.assert_not_called()
|
||||||
|
|
||||||
@patch('bid_main.models.User.delete')
|
@patch('bid_main.models.User.delete')
|
||||||
@patch('bid_api.signals.modified_user_to_webhooks')
|
@patch('bid_api.signals.handle_modifications')
|
||||||
def test_anonymises_users(self, mock_webhook, mock_delete):
|
def test_anonymises_users(self, mock_webhook, mock_delete):
|
||||||
now = timezone.now()
|
now = timezone.now()
|
||||||
# create some users
|
# create some users
|
||||||
@ -65,7 +65,7 @@ class ProcessDeletionRequestsCommandTest(TestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
@patch('bid_main.models.User.delete')
|
@patch('bid_main.models.User.delete')
|
||||||
@patch('bid_api.signals.modified_user_to_webhooks')
|
@patch('bid_api.signals.handle_modifications')
|
||||||
def test_missing_avatar(self, mock_webhook, mock_delete):
|
def test_missing_avatar(self, mock_webhook, mock_delete):
|
||||||
now = timezone.now()
|
now = timezone.now()
|
||||||
# a user who requested deletion long enough ago, with a missing avatar
|
# a user who requested deletion long enough ago, with a missing avatar
|
||||||
|
Loading…
Reference in New Issue
Block a user