diff --git a/requirements.txt b/requirements.txt
index 360a414..1926c0e 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,4 +1,5 @@
Django==5.0.6
djangorestframework
django-cors-headers
+djangorestframework-simplejwt
sabatron-tryton-rpc-client==7.4.0
diff --git a/tienda_ilusion/don_confiao/tests/Mixins.py b/tienda_ilusion/don_confiao/tests/Mixins.py
index 7957827..37176d9 100644
--- a/tienda_ilusion/don_confiao/tests/Mixins.py
+++ b/tienda_ilusion/don_confiao/tests/Mixins.py
@@ -1,10 +1,19 @@
from django.contrib.auth.models import User
+from rest_framework_simplejwt.tokens import RefreshToken
+from rest_framework.test import APIClient
class LoginMixin:
def login(self):
- username = 'nombre_usuario'
- password = 'contraseña'
- email = 'correo@example.com'
- self.user = User.objects.create_user(username, email, password)
- self.client.login(username=username, password=password)
+ self.user = User.objects.create_superuser(
+ username='admin',
+ email='admin@example.com',
+ password='adminpass'
+ )
+
+ refresh = RefreshToken.for_user(self.user)
+ self.access_token = str(refresh.access_token)
+
+ self.client = APIClient()
+ self.client.credentials(
+ HTTP_AUTHORIZATION=f'Bearer {self.access_token}')
diff --git a/tienda_ilusion/requirements.txt b/tienda_ilusion/requirements.txt
new file mode 100644
index 0000000..1926c0e
--- /dev/null
+++ b/tienda_ilusion/requirements.txt
@@ -0,0 +1,5 @@
+Django==5.0.6
+djangorestframework
+django-cors-headers
+djangorestframework-simplejwt
+sabatron-tryton-rpc-client==7.4.0
diff --git a/tienda_ilusion/tienda_ilusion/settings.py b/tienda_ilusion/tienda_ilusion/settings.py
index df1a981..6678e0b 100644
--- a/tienda_ilusion/tienda_ilusion/settings.py
+++ b/tienda_ilusion/tienda_ilusion/settings.py
@@ -11,6 +11,7 @@ https://docs.djangoproject.com/en/5.0/ref/settings/
"""
import os
+from datetime import timedelta
from pathlib import Path
# Build paths inside the project like this: BASE_DIR / 'subdir'.
@@ -44,7 +45,9 @@ INSTALLED_APPS = [
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
+ 'rest_framework.authtoken',
'corsheaders',
+ 'users',
# 'don_confiao'
]
@@ -57,7 +60,6 @@ MIDDLEWARE = [
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'corsheaders.middleware.CorsMiddleware',
- 'django.middleware.common.CommonMiddleware',
]
ROOT_URLCONF = 'tienda_ilusion.urls'
@@ -137,11 +139,19 @@ FIXTURE_DIRS = ['don_confiao/tests/Fixtures']
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
- 'rest_framework.authentication.SessionAuthentication',
+ "rest_framework_simplejwt.authentication.JWTAuthentication",
],
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
}
-LOGOUT_REDIRECT_URL = '/start/'
+SIMPLE_JWT = {
+ "ACCESS_TOKEN_LIFETIME": timedelta(minutes=30),
+ "REFRESH_TOKEN_LIFETIME": timedelta(days=1),
+ "AUTH_HEADER_TYPES": ("Bearer",),
+}
+
+# CORS_ALLOWED_ORIGINS = [
+# "http://localhost:5173",
+# ]
diff --git a/tienda_ilusion/tienda_ilusion/templates/registration/login.html b/tienda_ilusion/tienda_ilusion/templates/registration/login.html
deleted file mode 100644
index 0ec0e16..0000000
--- a/tienda_ilusion/tienda_ilusion/templates/registration/login.html
+++ /dev/null
@@ -1,5 +0,0 @@
-
diff --git a/tienda_ilusion/tienda_ilusion/templates/registration/profile.html b/tienda_ilusion/tienda_ilusion/templates/registration/profile.html
deleted file mode 100644
index e70c7fe..0000000
--- a/tienda_ilusion/tienda_ilusion/templates/registration/profile.html
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-
- Perfil de usuario
-
-
-
-
-
-
-
-
Perfil de usuario
-
Nombre de usuario: {{ user.username }}
-
Email: {{ user.email }}
-
-
-
-
-
-
diff --git a/tienda_ilusion/tienda_ilusion/templates/start.html b/tienda_ilusion/tienda_ilusion/templates/start.html
deleted file mode 100644
index 4ebf3bd..0000000
--- a/tienda_ilusion/tienda_ilusion/templates/start.html
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
- Bienvenido a la tienda la ilusión
-
-
-
-
-
-
-
Bienvenido a la tienda la ilusion
-
-
Login
-
-
-
-
-
diff --git a/tienda_ilusion/tienda_ilusion/urls.py b/tienda_ilusion/tienda_ilusion/urls.py
index 213403f..602cc8b 100644
--- a/tienda_ilusion/tienda_ilusion/urls.py
+++ b/tienda_ilusion/tienda_ilusion/urls.py
@@ -16,15 +16,19 @@ Including another URLconf
"""
from django.contrib import admin
from django.urls import include, path
-from . import views
-
+from rest_framework_simplejwt.views import (
+ TokenObtainPairView,
+ TokenRefreshView,
+)
app_name = "don_confiao"
urlpatterns = [
path("don_confiao/", include("don_confiao.urls")),
- path("accounts/", include("django.contrib.auth.urls")),
- path('accounts/profile/', views.ProfileView.as_view(), name='profile'),
- path('start/', views.StartView.as_view(), name='start'),
path('admin/', admin.site.urls),
+ path('api/token/', TokenObtainPairView.as_view(),
+ name='token_obtain_pair'),
+ path('api/token/refresh/', TokenRefreshView.as_view(),
+ name='token_refresh'),
+ path('api/users/', include('users.urls')),
]
diff --git a/tienda_ilusion/tienda_ilusion/views.py b/tienda_ilusion/tienda_ilusion/views.py
deleted file mode 100644
index ade2409..0000000
--- a/tienda_ilusion/tienda_ilusion/views.py
+++ /dev/null
@@ -1,15 +0,0 @@
-from django.views.generic import TemplateView
-from django.contrib.auth.mixins import LoginRequiredMixin
-
-
-class ProfileView(LoginRequiredMixin, TemplateView):
- template_name = 'registration/profile.html'
-
- def get_context_data(self, **kwargs):
- context = super().get_context_data(**kwargs)
- context['user'] = self.request.user
- return context
-
-
-class StartView(TemplateView):
- template_name = 'start.html'
diff --git a/tienda_ilusion/users/__init__.py b/tienda_ilusion/users/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tienda_ilusion/users/admin.py b/tienda_ilusion/users/admin.py
new file mode 100644
index 0000000..8c38f3f
--- /dev/null
+++ b/tienda_ilusion/users/admin.py
@@ -0,0 +1,3 @@
+from django.contrib import admin
+
+# Register your models here.
diff --git a/tienda_ilusion/users/apps.py b/tienda_ilusion/users/apps.py
new file mode 100644
index 0000000..4ce1fab
--- /dev/null
+++ b/tienda_ilusion/users/apps.py
@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+
+class UsersConfig(AppConfig):
+ name = 'users'
diff --git a/tienda_ilusion/users/migrations/__init__.py b/tienda_ilusion/users/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tienda_ilusion/users/models.py b/tienda_ilusion/users/models.py
new file mode 100644
index 0000000..71a8362
--- /dev/null
+++ b/tienda_ilusion/users/models.py
@@ -0,0 +1,3 @@
+from django.db import models
+
+# Create your models here.
diff --git a/tienda_ilusion/users/serializers.py b/tienda_ilusion/users/serializers.py
new file mode 100644
index 0000000..cdc3387
--- /dev/null
+++ b/tienda_ilusion/users/serializers.py
@@ -0,0 +1,8 @@
+from django.contrib.auth.models import User
+from rest_framework import serializers
+
+
+class UserSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = User
+ fields = ('id', 'username', 'email', 'first_name', 'last_name')
diff --git a/tienda_ilusion/users/tests.py b/tienda_ilusion/users/tests.py
new file mode 100644
index 0000000..ad750ad
--- /dev/null
+++ b/tienda_ilusion/users/tests.py
@@ -0,0 +1,51 @@
+from django.test import TestCase
+from django.urls import reverse
+from django.contrib.auth.models import User
+from rest_framework.test import APIClient
+from rest_framework_simplejwt.tokens import RefreshToken
+
+
+class MeEndpointTests(TestCase):
+ def setUp(self):
+ self.user = User.objects.create_superuser(
+ username='admin',
+ email='admin@example.com',
+ password='adminpass'
+ )
+
+ refresh = RefreshToken.for_user(self.user)
+ self.access_token = str(refresh.access_token)
+
+ self.client = APIClient()
+ self.client.credentials(
+ HTTP_AUTHORIZATION=f'Bearer {self.access_token}')
+
+ def test_me_endpoint_returns_correct_user_data(self):
+ """
+ Verifica que GET /api/users/me/ devuelve los datos del usuario
+ autenticado.
+ """
+ url = reverse('current-user')
+ response = self.client.get(url)
+
+ self.assertEqual(response.status_code, 200)
+
+ expected_fields = {'id', 'username', 'email',
+ 'first_name', 'last_name'}
+ self.assertTrue(expected_fields.issubset(response.json().keys()))
+
+ data = response.json()
+ self.assertEqual(data['username'], self.user.username)
+ self.assertEqual(data['email'], self.user.email)
+ self.assertEqual(data['first_name'], self.user.first_name)
+ self.assertEqual(data['last_name'], self.user.last_name)
+
+ def test_me_endpoint_requires_authentication(self):
+ """
+ Sin token el endpoint debe devolver 401 Unauthorized.
+ """
+ client_no_auth = APIClient()
+ url = reverse('current-user')
+ response = client_no_auth.get(url)
+
+ self.assertEqual(response.status_code, 401)
diff --git a/tienda_ilusion/users/urls.py b/tienda_ilusion/users/urls.py
new file mode 100644
index 0000000..8d408f9
--- /dev/null
+++ b/tienda_ilusion/users/urls.py
@@ -0,0 +1,6 @@
+from django.urls import path
+from .views import CurrentUserView
+
+urlpatterns = [
+ path('me/', CurrentUserView.as_view(), name='current-user'),
+]
diff --git a/tienda_ilusion/users/views.py b/tienda_ilusion/users/views.py
new file mode 100644
index 0000000..68762b8
--- /dev/null
+++ b/tienda_ilusion/users/views.py
@@ -0,0 +1,12 @@
+from rest_framework.views import APIView
+from rest_framework.response import Response
+from rest_framework.permissions import IsAuthenticated
+from .serializers import UserSerializer
+
+
+class CurrentUserView(APIView):
+ permission_classes = [IsAuthenticated]
+
+ def get(self, request):
+ serializer = UserSerializer(request.user)
+ return Response(serializer.data)