diff --git a/api/authentication/apis.py b/api/authentication/apis.py index 455ddec..93ec1de 100644 --- a/api/authentication/apis.py +++ b/api/authentication/apis.py @@ -1,11 +1,31 @@ from rest_framework import permissions, serializers, status from rest_framework.response import Response from rest_framework.views import APIView +from rest_framework_simplejwt.serializers import TokenObtainPairSerializer +from rest_framework_simplejwt.views import TokenObtainPairView from api.authentication.selectors import validate_phone from api.common.validators import is_phone +class MyTokenObtainPairView(TokenObtainPairView): + class TokenSerializer(TokenObtainPairSerializer): + @classmethod + def get_token(cls, user): + token = super().get_token(user) + + # Users Claims + token["name"] = user.name + token["phone"] = user.username + token["national_id"] = user.national_id + token["firebase_token"] = user.firebase_token + token["gov"] = user.location.gov.name_ar + token["city"] = user.location.city.name_ar + return token + + serializer_class = TokenSerializer + + class ValidatePhoneAPI(APIView): permission_classes = [permissions.AllowAny] diff --git a/api/authentication/urls.py b/api/authentication/urls.py index e0005a9..f5dac51 100644 --- a/api/authentication/urls.py +++ b/api/authentication/urls.py @@ -1,15 +1,11 @@ from django.urls import path -from rest_framework_simplejwt.views import ( - TokenObtainPairView, - TokenRefreshView, - TokenVerifyView, -) +from rest_framework_simplejwt.views import TokenRefreshView, TokenVerifyView -from api.authentication.apis import ValidatePhoneAPI +from api.authentication.apis import MyTokenObtainPairView, ValidatePhoneAPI app_name = "auth" urlpatterns = [ - path("token/", TokenObtainPairView.as_view(), name="obtain_token"), + path("token/", MyTokenObtainPairView.as_view(), name="obtain_token"), path("token/refresh/", TokenRefreshView.as_view(), name="refresh_token"), path("token/verify/", TokenVerifyView.as_view(), name="verify_token"), path("phone/validate/", ValidatePhoneAPI.as_view(), name="validate_phone"), diff --git a/api/cases/services.py b/api/cases/services.py index 42a3199..9c284ed 100644 --- a/api/cases/services.py +++ b/api/cases/services.py @@ -170,6 +170,9 @@ def publish_case(*, case: Case, performed_by: User): if not case.is_active: raise ValidationError("Cannot publish inactive case") + if case.posted_at: + raise ValidationError("Case already published") + case.publish() case.save() diff --git a/api/notifications/services.py b/api/notifications/services.py index d2ead96..5d37617 100644 --- a/api/notifications/services.py +++ b/api/notifications/services.py @@ -29,14 +29,14 @@ def create_notification( def create_fcm_device( *, user: User, - fcm_token: str, + firebase_token: str, device_type: Optional[str] = "android", ) -> FCMDevice: device = FCMDevice( user=user, type=device_type, - registration_id=fcm_token, + registration_id=firebase_token, ) device.full_clean() device.save() diff --git a/api/users/apis.py b/api/users/apis.py index 4223b75..eb7421a 100644 --- a/api/users/apis.py +++ b/api/users/apis.py @@ -16,7 +16,6 @@ class InputSerializer(serializers.Serializer): username = serializers.CharField() password = serializers.CharField() name = serializers.CharField() - fcm_token = serializers.CharField() firebase_token = serializers.CharField() location = inline_serializer( fields={ @@ -55,7 +54,6 @@ class UpdateUserApi(APIView): class InputSerializer(serializers.Serializer): name = serializers.CharField(required=False) firebase_token = serializers.CharField(required=False) - fcm_token = serializers.CharField(required=False) location = inline_serializer( fields={ "gov": serializers.IntegerField(), @@ -91,7 +89,7 @@ class OutputSerializer(serializers.Serializer): type = serializers.CharField() state = serializers.CharField(source="get_state_display") name = serializers.CharField(source="details.name") - thumbnail = serializers.URLField() + thumbnail = serializers.URLField(source="thumbnail.url") last_seen = serializers.DateField(source="details.last_seen") posted_at = serializers.DateTimeField() location = inline_serializer( diff --git a/api/users/services.py b/api/users/services.py index 0e8847e..d8f5fec 100644 --- a/api/users/services.py +++ b/api/users/services.py @@ -20,7 +20,6 @@ def create_user( password: str, firebase_token: str, location: Dict, - fcm_token: str, ) -> User: # Creating user's related entities @@ -41,7 +40,7 @@ def create_user( # Saving user to the database user.save() - create_fcm_device(user=user, fcm_token=fcm_token) + create_fcm_device(user=user, firebase_token=firebase_token) return user diff --git a/api/users/tests/test_models.py b/api/users/tests/test_models.py index 51cdd84..d70bee6 100644 --- a/api/users/tests/test_models.py +++ b/api/users/tests/test_models.py @@ -15,7 +15,6 @@ def setUpTestData(cls): # Called once at the beginning of the test run password="hardpassword", firebase_token="token", location={"gov": 1, "city": "4"}, - fcm_token="fcm_token", ) def test_name_max_lenght(self): diff --git a/config/urls.py b/config/urls.py index 2f1b07a..8de07ed 100644 --- a/config/urls.py +++ b/config/urls.py @@ -2,22 +2,25 @@ from django.conf.urls.static import static from django.contrib import admin from django.contrib.staticfiles.urls import staticfiles_urlpatterns +from django.http import HttpResponseNotFound from django.urls import include, path from django.views import defaults as default_views -from django.views.generic import TemplateView -from drf_spectacular.views import SpectacularAPIView, SpectacularSwaggerView -from rest_framework.authtoken.views import obtain_auth_token + +# from django.views.generic import TemplateView +# from drf_spectacular.views import SpectacularAPIView, SpectacularSwaggerView +# from rest_framework.authtoken.views import obtain_auth_token urlpatterns = [ - path("", TemplateView.as_view(template_name="pages/home.html"), name="home"), - path( - "about/", TemplateView.as_view(template_name="pages/about.html"), name="about" - ), + path("", HttpResponseNotFound), + # path("", TemplateView.as_view(template_name="pages/home.html"), name="home"), + # path( + # "about/", TemplateView.as_view(template_name="pages/about.html"), name="about" + # ), # Django Admin, use {% url 'admin:index' %} path(settings.ADMIN_URL, admin.site.urls), # User management - path("app-users/", include("api.users.app_urls", namespace="app_users")), - path("accounts/", include("allauth.urls")), + # path("app-users/", include("api.users.app_urls", namespace="app_users")), + # path("accounts/", include("allauth.urls")), # Your stuff: custom urls includes go here path("api/", include("api.apis.urls", namespace="apis")), ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) @@ -26,17 +29,17 @@ urlpatterns += staticfiles_urlpatterns() # API URLS -urlpatterns += [ - # DRF auth token - path("auth-token/", obtain_auth_token), - # Docs - path("api/schema/", SpectacularAPIView.as_view(), name="api-schema"), - path( - "api/docs/", - SpectacularSwaggerView.as_view(url_name="api-schema"), - name="api-docs", - ), -] +# urlpatterns += [ +# # DRF auth token +# path("auth-token/", obtain_auth_token), +# # Docs +# path("api/schema/", SpectacularAPIView.as_view(), name="api-schema"), +# path( +# "api/docs/", +# SpectacularSwaggerView.as_view(url_name="api-schema"), +# name="api-docs", +# ), +# ] if settings.DEBUG: # This allows the error pages to be debugged during development, just visit