diff --git a/api/custom_auth/serializers.py b/api/custom_auth/serializers.py
index 11bd80828a6b..aabf01eff74a 100644
--- a/api/custom_auth/serializers.py
+++ b/api/custom_auth/serializers.py
@@ -52,8 +52,9 @@ class Meta(UserCreateSerializer.Meta):
"is_active",
"marketing_consent_given",
"key",
+ "uuid",
)
- read_only_fields = ("is_active",)
+ read_only_fields = ("is_active", "uuid")
write_only_fields = ("sign_up_type",)
extra_kwargs = {
"email": {
diff --git a/api/sales_dashboard/templates/sales_dashboard/organisation.html b/api/sales_dashboard/templates/sales_dashboard/organisation.html
index cfe0610039a1..f0e7563a973f 100644
--- a/api/sales_dashboard/templates/sales_dashboard/organisation.html
+++ b/api/sales_dashboard/templates/sales_dashboard/organisation.html
@@ -156,6 +156,7 @@
{{user.email}}
{{ user.date_joined }} |
{{ user.last_login }} |
+ {{ user.uuid }} |
{% endfor %}
diff --git a/api/tests/unit/custom_auth/test_unit_custom_auth_views.py b/api/tests/unit/custom_auth/test_unit_custom_auth_views.py
new file mode 100644
index 000000000000..09b6d45de632
--- /dev/null
+++ b/api/tests/unit/custom_auth/test_unit_custom_auth_views.py
@@ -0,0 +1,22 @@
+from django.urls import reverse
+from rest_framework import status
+from rest_framework.test import APIClient
+
+from users.models import FFAdminUser
+
+
+def test_get_current_user(staff_user: FFAdminUser, staff_client: APIClient) -> None:
+ # Given
+ url = reverse("api-v1:custom_auth:ffadminuser-me")
+
+ # When
+ response = staff_client.get(url)
+
+ # Then
+ assert response.status_code == status.HTTP_200_OK
+
+ response_json = response.json()
+ assert response_json["email"] == staff_user.email
+ assert response_json["first_name"] == staff_user.first_name
+ assert response_json["last_name"] == staff_user.last_name
+ assert response_json["uuid"] == str(staff_user.uuid)
diff --git a/api/tests/unit/features/test_unit_features_views.py b/api/tests/unit/features/test_unit_features_views.py
index 0226d4b1a615..07defe5e8766 100644
--- a/api/tests/unit/features/test_unit_features_views.py
+++ b/api/tests/unit/features/test_unit_features_views.py
@@ -140,6 +140,7 @@ def test_remove_owners_only_remove_specified_owners(
"first_name": user_3.first_name,
"last_name": user_3.last_name,
"last_login": None,
+ "uuid": mock.ANY,
}
@@ -1565,6 +1566,7 @@ def test_add_owners_adds_owner(
"first_name": staff_user.first_name,
"last_name": staff_user.last_name,
"last_login": None,
+ "uuid": mock.ANY,
}
assert json_response["owners"][1] == {
"id": admin_user.id,
@@ -1572,6 +1574,7 @@ def test_add_owners_adds_owner(
"first_name": admin_user.first_name,
"last_name": admin_user.last_name,
"last_login": None,
+ "uuid": mock.ANY,
}
diff --git a/api/users/admin.py b/api/users/admin.py
index 85663231e8fd..4ce68597736a 100644
--- a/api/users/admin.py
+++ b/api/users/admin.py
@@ -44,6 +44,7 @@ class CustomUserAdmin(UserAdmin):
"is_staff",
"is_active",
"date_joined",
+ "uuid",
)
list_filter = (
@@ -57,6 +58,7 @@ class CustomUserAdmin(UserAdmin):
"username",
"first_name",
"last_name",
+ "uuid",
)
inlines = [UserOrganisationInline]
diff --git a/api/users/migrations/0037_add_uuid_field_to_user_model.py b/api/users/migrations/0037_add_uuid_field_to_user_model.py
new file mode 100644
index 000000000000..f5eb30f549e8
--- /dev/null
+++ b/api/users/migrations/0037_add_uuid_field_to_user_model.py
@@ -0,0 +1,37 @@
+# Generated by Django 3.2.25 on 2024-08-12 14:21
+from django.apps.registry import Apps
+from django.db import migrations, models
+import uuid
+
+from django.db.backends.base.schema import BaseDatabaseSchemaEditor
+
+
+def set_default_uuids(apps: Apps, schema_editor: BaseDatabaseSchemaEditor) -> None:
+ user_model = apps.get_model("users", "FFAdminUser")
+
+ users = list(user_model.objects.all())
+ for user in users:
+ user.uuid = uuid.uuid4()
+
+ user_model.objects.bulk_update(users, fields=["uuid"])
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('users', '0036_create_hubspot_lead'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='ffadminuser',
+ name='uuid',
+ field=models.UUIDField(default=uuid.uuid4),
+ ),
+ migrations.RunPython(set_default_uuids, reverse_code=migrations.RunPython.noop),
+ migrations.AlterField(
+ model_name='ffadminuser',
+ name='uuid',
+ field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True),
+ ),
+ ]
diff --git a/api/users/models.py b/api/users/models.py
index e2e272c3ba3a..3c458e3b0e94 100644
--- a/api/users/models.py
+++ b/api/users/models.py
@@ -1,5 +1,6 @@
import logging
import typing
+import uuid
from datetime import timedelta
from django.conf import settings
@@ -112,6 +113,8 @@ class FFAdminUser(LifecycleModel, AbstractUser):
choices=SignUpType.choices, max_length=100, blank=True, null=True
)
+ uuid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
+
USERNAME_FIELD = "email"
REQUIRED_FIELDS = ["first_name", "last_name", "sign_up_type"]
diff --git a/api/users/serializers.py b/api/users/serializers.py
index d7fef9200201..858ae491a2ba 100644
--- a/api/users/serializers.py
+++ b/api/users/serializers.py
@@ -44,7 +44,7 @@ class UserFullSerializer(serializers.ModelSerializer):
class Meta:
model = FFAdminUser
- fields = ("id", "email", "first_name", "last_name", "organisations")
+ fields = ("id", "email", "first_name", "last_name", "organisations", "uuid")
class UserLoginSerializer(serializers.ModelSerializer):
@@ -57,7 +57,7 @@ class UserListSerializer(serializers.ModelSerializer):
role = serializers.SerializerMethodField(read_only=True)
join_date = serializers.SerializerMethodField(read_only=True)
- default_fields = ("id", "email", "first_name", "last_name", "last_login")
+ default_fields = ("id", "email", "first_name", "last_name", "last_login", "uuid")
organisation_users_fields = (
"role",
"date_joined",
@@ -134,12 +134,14 @@ class UserPermissionGroupSerializerDetail(UserPermissionGroupSerializer):
class CustomCurrentUserSerializer(DjoserUserSerializer):
auth_type = serializers.CharField(read_only=True)
is_superuser = serializers.BooleanField(read_only=True)
+ uuid = serializers.UUIDField(read_only=True)
class Meta(DjoserUserSerializer.Meta):
fields = DjoserUserSerializer.Meta.fields + (
"auth_type",
"is_superuser",
"date_joined",
+ "uuid",
)