Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion api/common/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,12 @@ def is_phone(val: str):
Validates a phone number
"""
if not val.isnumeric() or len(val) != 10:
raise ValidationError(f'"{val}" is not a valid number')
raise ValidationError(f'"Phone: {val}" is not a valid number')


def is_national_id(val: str):
"""
Validates an egyptian national id
"""
if not val.isnumeric() or len(val) != 14:
raise ValidationError(f'"ID: {val}" is not a valid national id')
2 changes: 1 addition & 1 deletion api/users/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class UserAdmin(auth_admin.UserAdmin):
add_form = UserAdminCreationForm
fieldsets = (
(None, {"fields": ("username", "password")}),
(_("Personal info"), {"fields": ("name", "email", "location")}),
(_("Personal info"), {"fields": ("name", "email", "location", "national_id")}),
(
_("Permissions"),
{
Expand Down
24 changes: 21 additions & 3 deletions api/users/apis.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
from django.shortcuts import get_object_or_404
from rest_framework import permissions, serializers, status
from rest_framework.response import Response
from rest_framework.views import APIView

from api.common.permissions import IsVerified
from api.common.utils import get_object, inline_serializer
from api.common.utils import inline_serializer
from api.users.models import User
from api.users.services import create_user, update_user
from api.users.services import create_user, set_national_id, update_user


class CreateUserApi(APIView):
Expand Down Expand Up @@ -47,7 +48,7 @@ class OutputSerializer(serializers.Serializer):
)

def get(self, request, user_id):
user = get_object(User, id=user_id)
user = get_object_or_404(User, id=user_id)
serializer = self.OutputSerializer(user)
return Response(serializer.data)

Expand Down Expand Up @@ -80,3 +81,20 @@ def post(self, request, user_id):
data=serializer.validated_data,
)
return Response(status=status.HTTP_200_OK)


class SetNationalIdApi(APIView):
class InputSerializer(serializers.Serializer):
national_id = serializers.CharField()

def post(self, request, user_id):
serializer = self.InputSerializer(data=request.data)
serializer.is_valid(raise_exception=True)

user = get_object_or_404(User, pk=user_id)
set_national_id(
user=user,
data=serializer.validated_data,
)

return Response(status=status.HTTP_200_OK)
8 changes: 4 additions & 4 deletions api/users/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Generated by Django 3.2.13 on 2022-04-19 22:39
# Generated by Django 3.2.13 on 2022-05-10 19:09

import api.common.validators
import django.contrib.auth.models
Expand All @@ -12,7 +12,7 @@ class Migration(migrations.Migration):
initial = True

dependencies = [
('locations', '0001_initial'),
('locations', '0003_alter_location_address'),
('auth', '0012_alter_user_first_name_max_length'),
]

Expand All @@ -24,14 +24,14 @@ class Migration(migrations.Migration):
('password', models.CharField(max_length=128, verbose_name='password')),
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')),
('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
('name', models.CharField(max_length=256)),
('email', models.EmailField(blank=True, max_length=254, null=True)),
('username', models.CharField(max_length=10, unique=True, validators=[api.common.validators.is_phone])),
('id_exp_date', models.DateTimeField(blank=True, null=True)),
('id_photo_url', models.ImageField(blank=True, upload_to='id-photos/')),
('national_id', models.CharField(blank=True, max_length=14, null=True, unique=True, validators=[api.common.validators.is_national_id])),
('firebase_token', models.CharField(blank=True, max_length=256, unique=True)),
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')),
('location', models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='user', to='locations.location')),
Expand Down
17 changes: 0 additions & 17 deletions api/users/migrations/0002_remove_user_id_photo_url.py

This file was deleted.

18 changes: 0 additions & 18 deletions api/users/migrations/0003_alter_user_email.py

This file was deleted.

9 changes: 8 additions & 1 deletion api/users/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from django.urls import reverse
from django.utils import timezone

from api.common.validators import is_phone
from api.common.validators import is_national_id, is_phone
from api.locations.models import Location


Expand All @@ -15,6 +15,13 @@ class User(AbstractUser):
username = models.CharField(max_length=10, unique=True, validators=[is_phone])

id_exp_date = models.DateTimeField(null=True, blank=True)
national_id = models.CharField(
max_length=14,
unique=True,
null=True,
blank=True,
validators=[is_national_id],
)

firebase_token = models.CharField(max_length=256, unique=True, blank=True)

Expand Down
16 changes: 11 additions & 5 deletions api/users/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,7 @@ def create_user(


@transaction.atomic
def update_user(
*,
user: User,
data: Dict,
) -> User:
def update_user(*, user: User, data: Dict) -> User:
non_side_effect_fields = ["name", "firebase_token"]

user, _ = model_update(
Expand All @@ -64,3 +60,13 @@ def update_user(
update_location(location=user.location, data=location_data)

return user


def set_national_id(*, user: User, data: Dict) -> None:
national_id = data.get("national_id")
user.national_id = national_id

user.full_clean()
user.save()

return None
3 changes: 2 additions & 1 deletion api/users/urls.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from django.urls import path

from api.users.apis import CreateUserApi, DetailUserApi, UpdateUserApi
from api.users.apis import CreateUserApi, DetailUserApi, SetNationalIdApi, UpdateUserApi

app_name = "users"
urlpatterns = [
path("create/", CreateUserApi.as_view(), name="create_user"),
path("<int:user_id>/", DetailUserApi.as_view(), name="get_user"),
path("<int:user_id>/update/", UpdateUserApi.as_view(), name="update_user"),
path("<int:user_id>/set/id/", SetNationalIdApi.as_view(), name="set_id"),
]