irongit

added the session auth

huncholanehuncholaneauthored
parent 439cb37commit 39a2ddd839ebd1f8c1ac202f8ec1dc97913a6064Browse files

8 files changed, +129 -5

+0-0.vscode/settings.json → .vscode.template/settings.json

No content changes (mode or rename only).

+0-0rango/backend/api/auth/__init__.py

No content changes (mode or rename only).

+41-0rango/backend/api/auth/serializers.py
@@ -0,0 +1,41 @@
1+from rest_framework import serializers
2+from django.contrib.auth.models import User
3+from rest_framework.exceptions import ValidationError, NotFound, AuthenticationFailed
4+from django.contrib.auth import login, logout, authenticate
5+
6+
7+class LoginSerializer(serializers.ModelSerializer):
8+ username = serializers.CharField(required=False)
9+ email = serializers.EmailField(required=False)
10+ password = serializers.CharField(write_only=True)
11+ class Meta:
12+ model = User
13+ fields = ['username', 'email', 'password']
14+
15+ def create(self, validated_data):
16+ request = self.context['request']
17+ logout(request)
18+ username = validated_data.get('username')
19+ email = validated_data.get('email')
20+ password = validated_data.get('password')
21+ if not username and not email:
22+ raise ValidationError('Requires username or email.')
23+ if username:
24+ user = authenticate(username=username, password=password)
25+ else:
26+ query = User.objects.filter(email=email)
27+ if not query:
28+ raise NotFound(f'{email} has no account.')
29+ username = query.first().username
30+ user = authenticate(username, password)
31+ if not user:
32+ raise AuthenticationFailed('Incorrect username or password.')
33+ login(self.context['request'], user)
34+ return user
35+
36+
37+class LogoutSerializer(serializers.Serializer):
38+ detail = serializers.CharField(read_only=True, default="Success")
39+
40+class LoggedInSerializer(serializers.Serializer):
41+ detail = serializers.BooleanField(read_only=True, default=False)
+11-0rango/backend/api/auth/urls.py
@@ -0,0 +1,11 @@
1+from django.urls import path
2+from .views import LoginView, AuthRoot, LogoutView, LoggedInView
3+
4+
5+urlpatterns = [
6+ path('login', LoginView.as_view(), name='api-login'),
7+ path('', AuthRoot.as_view(), name='api-auth-root'),
8+ path('logout', LogoutView.as_view(), name='api-logout'),
9+ path('logged-in', LoggedInView.as_view(), name='api-logged-in')
10+]
11+
+66-0rango/backend/api/auth/views.py
@@ -0,0 +1,66 @@
1+from rest_framework.generics import CreateAPIView, GenericAPIView, RetrieveAPIView
2+from rest_framework.views import APIView
3+from rest_framework.routers import APIRootView
4+from rest_framework.reverse import reverse
5+from rest_framework.response import Response
6+from rest_framework.permissions import IsAuthenticated
7+from rest_framework.schemas.openapi import AutoSchema
8+from rest_framework.permissions import AllowAny
9+from .serializers import LoginSerializer, LogoutSerializer, LoggedInSerializer
10+from django.contrib.auth.models import User
11+from django.contrib.auth import logout
12+
13+
14+class AuthRoot(APIRootView):
15+
16+ def get(self, request, *args, **kwargs):
17+ return Response({
18+ 'login': reverse('api-login', request=request),
19+ 'logout': reverse('api-logout', request=request),
20+ 'logged-in': reverse('api-logged-in', request=request)
21+ })
22+
23+
24+class LoginView(CreateAPIView):
25+ schema = AutoSchema(
26+ tags=['Auth'],
27+ component_name='login',
28+ operation_id_base='Login'
29+ )
30+ serializer_class = LoginSerializer
31+ queryset = User.objects.all()
32+ permission_classes = [AllowAny]
33+
34+
35+class LoggedInView(RetrieveAPIView):
36+ schema = AutoSchema(
37+ tags=['Auth'],
38+ component_name='logged-in',
39+ operation_id_base='LoggedIn'
40+ )
41+ serializer_class = LoggedInSerializer
42+
43+ def retrieve(self, request, *args, **kwargs):
44+ if request.user.is_authenticated:
45+ return Response({
46+ 'detail': True
47+ })
48+ return Response({'detail': False})
49+
50+
51+class LogoutView(RetrieveAPIView):
52+ schema = AutoSchema(
53+ tags=['Auth'],
54+ component_name='logout',
55+ operation_id_base='Logout'
56+ )
57+ serializer_class = LogoutSerializer
58+ permission_classes = [IsAuthenticated]
59+
60+ def retrieve(self, request):
61+ user = request.user
62+ logout(request)
63+ return Response({
64+ 'details': f'Successfully logged out {user}.'
65+ })
66+
+3-3rango/backend/api/management/commands/createapi.py
@@ -9,13 +9,13 @@ class Command(BaseCommand):
99 help = "Creates a new API. Usage: python manage.py createapi api_name [root_dir]"
1010
1111 def add_arguments(self, parser: CommandParser) -> None:
12- parser.add_argument('api_name', type=str, help='The name of the API model')
12+ parser.add_argument('model_name', type=str, help='The name of the API model')
1313 parser.add_argument('root_dir', type=str, nargs='?', default='api', help='The root directory for the API model. Defaults to "api"')
1414
1515 def handle(self, *args, **options):
1616 # Get the api name from the first argument
17- api_name = options['api_name'].lower()
18- model_name = api_name.capitalize()
17+ model_name = options['model_name']
18+ api_name = model_name.lower()
1919 # Get the root directory
2020 root_dir = options['root_dir'].lower()
2121 # Create context for the templates
+4-1rango/backend/api/urls.py
@@ -3,9 +3,12 @@ from .views import ApiRoot, schema_view, swagger_view
33
44
55 urlpatterns = [
6+ # Auto-generated: a keyword used by the createapi command to know where to add new urls
67 re_path('$', ApiRoot.as_view(), name='api-root'),
78 re_path('', include('api.user.urls')),
89 re_path('openapi', schema_view, name='openapi-schema'),
910 re_path('swagger-ui', swagger_view, name='swagger-ui'),
10- # Auto-generated: a keyword used by the createapi command to know where to add new urls
11+ re_path('openapi', schema_view, name='openapi-schema'),
12+ re_path('swagger-ui', swagger_view, name='swagger-ui'),
13+ re_path('auth/', include('api.auth.urls')),
1114 ]
+4-1rango/backend/api/views.py
@@ -13,6 +13,9 @@ class ApiRoot(APIRootView):
1313
1414 def get(self, request, *args, **kwargs):
1515 return Response({
16- 'user': reverse('user-list', request=request),
1716 # Auto-generated: a keyword used by the createapi command to know where to add new urls
17+ 'user': reverse('user-list', request=request),
18+ 'openapi': reverse('openapi-schema', request=request),
19+ 'swagger-ui': reverse('swagger-ui', request=request),
20+ 'auth': reverse('api-auth-root', request=request),
1821 })