feat: introduce public_id UUID field for user identification in URLs and APIs

This commit is contained in:
Your Name
2026-04-10 17:11:43 +05:30
parent 8c836fdac6
commit 083936d036
6 changed files with 47 additions and 3 deletions
@@ -0,0 +1,19 @@
# Generated by Django 6.0.4 on 2026-04-10 11:39
import uuid
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("users", "0002_user_kdf_salt_alter_user_is_active"),
]
operations = [
migrations.AddField(
model_name="user",
name="public_id",
field=models.UUIDField(default=uuid.uuid4, editable=False, null=True),
),
]
@@ -0,0 +1,19 @@
# Generated by Django 6.0.4 on 2026-04-10 11:39
import uuid
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("users", "0003_user_public_id"),
]
operations = [
migrations.AlterField(
model_name="user",
name="public_id",
field=models.UUIDField(db_index=True, default=uuid.uuid4, editable=False, unique=True),
),
]
+6
View File
@@ -1,3 +1,5 @@
import uuid
from django.contrib.auth.models import AbstractUser, BaseUserManager from django.contrib.auth.models import AbstractUser, BaseUserManager
from django.db import models from django.db import models
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
@@ -32,8 +34,12 @@ class CustomUserManager(BaseUserManager):
class User(AbstractUser): class User(AbstractUser):
""" """
Database table structure. Database table structure.
Note: We use the default integer ID internally for database performance (joins/indexes)
but expose a random 'public_id' (UUID) in URLs and APIs for real privacy.
""" """
public_id = models.UUIDField(default=uuid.uuid4, editable=False, unique=True, db_index=True)
# Reset default fields # Reset default fields
username = None username = None
first_name = None first_name = None
+1 -1
View File
@@ -9,7 +9,7 @@ class UserSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = User model = User
fields = ("id", "email", "full_name", "password") fields = ("public_id", "email", "full_name", "password")
def create(self, validated_data): def create(self, validated_data):
user = User.objects.create_user( user = User.objects.create_user(
+1 -1
View File
@@ -7,7 +7,7 @@ from django.utils.http import urlsafe_base64_encode
def send_activation_email(user): def send_activation_email(user):
token = default_token_generator.make_token(user) token = default_token_generator.make_token(user)
uid = urlsafe_base64_encode(force_bytes(user.pk)) uid = urlsafe_base64_encode(force_bytes(user.public_id))
activation_url = f"{settings.FRONTEND_URL}/activate/{uid}/{token}" activation_url = f"{settings.FRONTEND_URL}/activate/{uid}/{token}"
subject = "Activate Your Piku Account" subject = "Activate Your Piku Account"
message = f"""Hi {user.full_name}, message = f"""Hi {user.full_name},
+1 -1
View File
@@ -31,7 +31,7 @@ class ActivationView(generics.GenericAPIView):
def get(self, request, uidb64, token): def get(self, request, uidb64, token):
try: try:
uid = urlsafe_base64_decode(uidb64).decode() uid = urlsafe_base64_decode(uidb64).decode()
user = User.objects.get(pk=uid) user = User.objects.get(public_id=uid)
except (User.DoesNotExist, TypeError, ValueError): except (User.DoesNotExist, TypeError, ValueError):
return Response({"detail": "Invalid activation link: User Error"}, status=status.HTTP_400_BAD_REQUEST) return Response({"detail": "Invalid activation link: User Error"}, status=status.HTTP_400_BAD_REQUEST)
# validate token # validate token