This commit is contained in:
Ahmed Nagi 2025-01-16 17:21:53 +00:00
parent e6052baf45
commit 4e1b8b9a02
5 changed files with 103 additions and 41 deletions

View file

@ -75,6 +75,7 @@ THIRD_PARTY_APPS = [
"crispy_forms", "crispy_forms",
"crispy_bootstrap5", "crispy_bootstrap5",
"allauth", "allauth",
'allauth.headless',
"allauth.account", "allauth.account",
"allauth.mfa", "allauth.mfa",
"allauth.socialaccount", "allauth.socialaccount",
@ -233,7 +234,7 @@ EMAIL_TIMEOUT = 5
# Django Admin URL. # Django Admin URL.
ADMIN_URL = "admin/" ADMIN_URL = "admin/"
# https://docs.djangoproject.com/en/dev/ref/settings/#admins # https://docs.djangoproject.com/en/dev/ref/settings/#admins
ADMINS = [("""Ahmed Nagi""", "ahmed10nagi@gmail.com")] ADMINS = [("""ص""", "e@gmail.com")]
# https://docs.djangoproject.com/en/dev/ref/settings/#managers # https://docs.djangoproject.com/en/dev/ref/settings/#managers
MANAGERS = ADMINS MANAGERS = ADMINS
# https://cookiecutter-django.readthedocs.io/en/latest/settings.html#other-environment-settings # https://cookiecutter-django.readthedocs.io/en/latest/settings.html#other-environment-settings
@ -330,8 +331,22 @@ ACCOUNT_EMAIL_CONFIRMATION_AUTHENTICATED_REDIRECT_URL = None
# ACCOUNT_RATE_LIMITS = { # ACCOUNT_RATE_LIMITS = {
# "confirm_email": "1/4m", # 1 confirmation email every 4 minutes # "confirm_email": "1/4m", # 1 confirmation email every 4 minutes
# } # }
HEADLESS_FRONTEND_URLS = {
"account_confirm_email": "http://127.0.0.1:3000/account/email-confirmation/{key}/",
# Key placeholders are automatically populated. You are free to adjust this
# to your own needs, e.g.
#
# "https://app.project.org/account/email/verify-email?token={key}",
"account_reset_password": "https://app.project.org/account/password/reset",
"account_reset_password_from_key": "https://app.project.org/account/password/reset/key/{key}",
# "account_signup": "https://app.project.org/account/signup",
# Fallback in case the state containing the `next` URL is lost and the handshake
# with the third-party provider fails.
# "socialaccount_login_error": "https://app.project.org/account/provider/callback",
}
HEADLESS_ONLY = True
# https://docs.allauth.org/en/latest/account/configuration.html # https://docs.allauth.org/en/latest/account/configuration.html
ACCOUNT_ADAPTER = "lms.accounts.adapters.CustomAccountAdapter" # ACCOUNT_ADAPTER = "lms.accounts.adapters.CustomAccountAdapter"
# https://docs.allauth.org/en/latest/account/forms.html # https://docs.allauth.org/en/latest/account/forms.html
# ACCOUNT_FORMS = {"signup": "lms.users.forms.UserSignupForm"} # ACCOUNT_FORMS = {"signup": "lms.users.forms.UserSignupForm"}
# https://docs.allauth.org/en/latest/socialaccount/configuration.html # https://docs.allauth.org/en/latest/socialaccount/configuration.html
@ -353,6 +368,7 @@ REST_FRAMEWORK = {
'dj_rest_auth.jwt_auth.JWTCookieAuthentication', 'dj_rest_auth.jwt_auth.JWTCookieAuthentication',
), ),
"DEFAULT_PERMISSION_CLASSES": ( "DEFAULT_PERMISSION_CLASSES": (
'rest_framework.permissions.AllowAny',
"rest_framework.permissions.IsAuthenticated", "rest_framework.permissions.IsAuthenticated",
), ),
"DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema", "DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema",
@ -384,8 +400,17 @@ SPECTACULAR_SETTINGS = {
"TITLE": "Learning Management System API", "TITLE": "Learning Management System API",
"DESCRIPTION": "Documentation of API endpoints of Learning Management System", "DESCRIPTION": "Documentation of API endpoints of Learning Management System",
"VERSION": "1.0.0", "VERSION": "1.0.0",
"SERVE_PERMISSIONS": ["rest_framework.permissions.IsAdminUser"], # "SERVE_PERMISSIONS": ["rest_framework.permissions.IsAdminUser"],
"SCHEMA_PATH_PREFIX": "/api/", "SCHEMA_PATH_PREFIX": "/api/",
'SERVE_INCLUDE_SCHEMA': False,
} }
# Your stuff... # Your stuff...
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# CSRF_COOKIE_SECURE = False # لأنك لا تستخدم HTTPS محليًا
# CSRF_COOKIE_SAMESITE = 'None' # للسماح بالطلبات عبر النطاقات
# CSRF_COOKIE_HTTPONLY = False # للسماح للـ JavaScript بالوصول إذا لزم الأمر
# SESSION_COOKIE_SECURE = False
# SESSION_COOKIE_SAMESITE = 'None'
# SESSION_COOKIE_HTTPONLY = True

View file

@ -12,13 +12,52 @@ from drf_spectacular.views import SpectacularSwaggerView
from rest_framework.authtoken.views import obtain_auth_token from rest_framework.authtoken.views import obtain_auth_token
from lms.accounts.views import * from lms.accounts.views import *
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import AllowAny
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import AllowAny
class SetCookieExampleView(APIView):
permission_classes = [AllowAny]
def post(self, request, *args, **kwargs):
# الحصول على قيمة 'target' من البيانات المرسلة مع الطلب
target = request.META.get('HTTP_ORIGIN', 'No origin provided') # افتراض قيمة افتراضية
# طباعة 'target' في وحدة التحكم
print(f"Target received: {target}")
# إعداد الاستجابة
response = Response({
"message": "Cookie set successfully!",
"target": target, # إضافة 'target' إلى الاستجابة كإخراج اختباري
})
# إعداد الكوكي بدون أمان (HTTP فقط)
response.set_cookie(
key='my_cookie_name', # اسم الكوكي
value='my_cookie_value', # قيمة الكوكي
max_age=3600, # وقت انتهاء الصلاحية بالثواني
httponly=False, # يمكن الوصول للكوكي من JavaScript
samesite=None, # السماح باستخدام الكوكي عبر المواقع (Cross-Site)
)
return response
urlpatterns = [ urlpatterns = [
path("", TemplateView.as_view(template_name="pages/home.html"), name="home"), path("", TemplateView.as_view(template_name="pages/home.html"), name="home"),
# Django Admin, use {% url 'admin:index' %} # Django Admin, use {% url 'admin:index' %}
path(settings.ADMIN_URL, admin.site.urls), path(settings.ADMIN_URL, admin.site.urls),
# User management # User management
path("ex/", SetCookieExampleView.as_view(), name="ex"),
# path("users/", include("lms.users.urls", namespace="users")),
path("accounts/", include("allauth.urls")), path("accounts/", include("allauth.urls")),
path("auth/", include("allauth.headless.urls")),
# Your stuff: custom urls includes go here # Your stuff: custom urls includes go here
# ... # ...
# Media files # Media files
@ -31,11 +70,11 @@ if settings.DEBUG:
# API URLS # API URLS
urlpatterns += [ urlpatterns += [
path('authw/', include('dj_rest_auth.urls')), # path('authw/', include('dj_rest_auth.urls')),
path('api-auth/', include('rest_framework.urls', namespace='rest_framework')), # path('api-auth/', include('rest_framework.urls', namespace='rest_framework')),
path('auth/', include('lms.accounts.urls')), # path('auth/', include('lms.accounts.urls')),
path('app/', include('lms.app.urls')), # path('app/', include('lms.app.urls')),
# API base url # API base url

View file

@ -8,6 +8,6 @@ router.register(r'modules', ModuleViewSet, basename='modules')
router.register(r'lessons', LessonViewSet, basename='lessons') router.register(r'lessons', LessonViewSet, basename='lessons')
router.register(r'enrollment', EnrollmentViewSet, basename='enrollment') router.register(r'enrollment', EnrollmentViewSet, basename='enrollment')
router.register(r'quiz', QuizViewSet, basename='quiz') router.register(r'quiz', QuizViewSet, basename='quiz')
router.register(r'certificate', CertificateViewSet, basename='certificate') # router.register(r'certificate', CertificateViewSet, basename='certificate')
urlpatterns = router.urls urlpatterns = router.urls

View file

@ -259,8 +259,6 @@ class QuizViewSet(ModelViewSet):
if module.course.owner != request.user: if module.course.owner != request.user:
return Response({"detail": "You can only create quizzes for your own courses"}, status=status.HTTP_403_FORBIDDEN) return Response({"detail": "You can only create quizzes for your own courses"}, status=status.HTTP_403_FORBIDDEN)
# Create a new quiz # Create a new quiz
# data = request.data.copy() # نسخ البيانات لتجنب التعديل على الأصل
# data.pop('module', None) # إزالة المفتاح module إذا كان موجودًا
quiz = Quiz.objects.create(module=module) quiz = Quiz.objects.create(module=module)
serializer = self.get_serializer(quiz) serializer = self.get_serializer(quiz)
return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.data, status=status.HTTP_201_CREATED)
@ -295,40 +293,40 @@ class QuizViewSet(ModelViewSet):
return Response({"detail": "Quiz deleted successfully"}, status=status.HTTP_204_NO_CONTENT) return Response({"detail": "Quiz deleted successfully"}, status=status.HTTP_204_NO_CONTENT)
class CertificateViewSet(ModelViewSet): # class CertificateViewSet(ModelViewSet):
queryset = Certificate.objects.all() # queryset = Certificate.objects.all()
serializer_class = CertificateSerializer # serializer_class = CertificateSerializer
permission_classes = [] # permission_classes = []
def get_permissions(self): # def get_permissions(self):
if self.action == 'create': # if self.action == 'create':
# permission_classes = [Isowner] # # permission_classes = [Isowner]
pass # pass
elif self.action in ['update', 'destroy']: # elif self.action in ['update', 'destroy']:
permission_classes = [IsAdmin] # permission_classes = [IsAdmin]
else: # # else:
permission_classes = [] # # permission_classes = []
return [permission() for permission in permission_classes] # # return [permission() for permission in permission_classes]
def create(self, request, *args, **kwargs): # def create(self, request, *args, **kwargs):
# Get course data from the request # # Get course data from the request
courseId = request.data.get('course') # courseId = request.data.get('course')
student_id = request.data.get('student') # student_id = request.data.get('student')
# Check if the course exists # # Check if the course exists
try: # try:
course = Course.objects.get(id=courseId) # course = Course.objects.get(id=courseId)
student = User.objects.get(id=student_id, role='student') # student = User.objects.get(id=student_id, role='student')
except User.DoesNotExist: # except User.DoesNotExist:
return Response({"detail": "Student not found"}, status=status.HTTP_404_NOT_FOUND) # return Response({"detail": "Student not found"}, status=status.HTTP_404_NOT_FOUND)
except Course.DoesNotExist: # except Course.DoesNotExist:
return Response({"detail": "Course not found"}, status=status.HTTP_404_NOT_FOUND) # return Response({"detail": "Course not found"}, status=status.HTTP_404_NOT_FOUND)
# Ensure the current owner is the course owner # # Ensure the current owner is the course owner
if course.owner != request.user: # if course.owner != request.user:
return Response({"detail": "You can only create certificate for your own courses"}, status=status.HTTP_403_FORBIDDEN) # return Response({"detail": "You can only create certificate for your own courses"}, status=status.HTTP_403_FORBIDDEN)
certificate = Certificate.objects.create(course=course, student=student) # certificate = Certificate.objects.create(course=course, student=student)
serializer = self.get_serializer(certificate) # serializer = self.get_serializer(certificate)
return Response(serializer.data, status=status.HTTP_201_CREATED) # return Response(serializer.data, status=status.HTTP_201_CREATED)