fix: validate course and batch before a reply is added

This commit is contained in:
Jannat Patel
2025-12-04 09:25:07 +05:30
parent 5f17802ab8
commit 0367c1db72
10 changed files with 75 additions and 26 deletions
+4 -1
View File
@@ -101,7 +101,10 @@ doc_events = {
"lms.lms.doctype.lms_badge.lms_badge.process_badges",
]
},
"Discussion Reply": {"after_insert": "lms.lms.utils.handle_notifications"},
"Discussion Reply": {
"after_insert": "lms.lms.utils.handle_notifications",
"validate": "lms.lms.utils.validate_discussion_reply",
},
"Notification Log": {"on_change": "lms.lms.utils.publish_notifications"},
"User": {
"validate": "lms.lms.user.validate_username_duplicates",
+3 -1
View File
@@ -520,7 +520,7 @@ def get_sidebar_settings():
web_pages = frappe.get_all(
"LMS Sidebar Item",
{"parenttype": "LMS Settings", "parentfield": "sidebar_items"},
["web_page", "route", "title as label", "icon"],
["web_page", "route", "title as label", "icon", "name"],
)
for page in web_pages:
page.to = page.route
@@ -813,6 +813,7 @@ def save_certificate_details(
def delete_documents(doctype, documents):
frappe.only_for("Moderator")
for doc in documents:
print(f"Deleting {doctype} {doc}")
frappe.delete_doc(doctype, doc)
@@ -1014,6 +1015,7 @@ def give_discussions_permission():
"write": 1,
"create": 1,
"delete": 1,
"if_owner": 0 if role == "Moderator" else 1,
}
).save(ignore_permissions=True)
@@ -4,7 +4,7 @@
import frappe
from frappe.model.document import Document
from lms.lms.utils import has_course_instructor_role, has_course_moderator_role
from lms.lms.utils import has_course_instructor_role, has_moderator_role
class LMSAssignment(Document):
@@ -13,7 +13,7 @@ class LMSAssignment(Document):
@frappe.whitelist()
def save_assignment(assignment, title, type, question):
if not has_course_moderator_role() or not has_course_instructor_role():
if not has_moderator_role() or not has_course_instructor_role():
return
if assignment:
@@ -6,7 +6,7 @@ from frappe import _
from frappe.model.document import Document
from frappe.model.mapper import get_mapped_doc
from lms.lms.utils import has_course_moderator_role
from lms.lms.utils import has_moderator_role
class LMSCertificateEvaluation(Document):
@@ -19,7 +19,7 @@ class LMSCertificateEvaluation(Document):
def has_website_permission(doc, ptype, user, verbose=False):
if has_course_moderator_role() or doc.member == frappe.session.user:
if has_moderator_role() or doc.member == frappe.session.user:
return True
return False
+2 -2
View File
@@ -5,7 +5,7 @@ import frappe
from frappe import _
from frappe.model.document import Document
from lms.lms.utils import has_course_instructor_role, has_course_moderator_role
from lms.lms.utils import has_course_instructor_role, has_moderator_role
class LMSQuestion(Document):
@@ -95,7 +95,7 @@ def get_correct_options(question):
@frappe.whitelist()
def get_question_details(question):
if not has_course_instructor_role() or not has_course_moderator_role():
if not has_course_instructor_role() or not has_moderator_role():
return
fields = ["question", "type", "name"]
+54 -9
View File
@@ -492,7 +492,7 @@ def can_create_courses(course, member=None):
if frappe.session.user == "Guest":
return False
if has_course_moderator_role(member):
if has_moderator_role(member):
return True
if has_course_instructor_role(member) and member in instructors:
@@ -508,14 +508,14 @@ def can_create_batches(member=None):
if not member:
member = frappe.session.user
if has_course_moderator_role(member):
if has_moderator_role(member):
return True
if has_course_evaluator_role(member):
if has_evaluator_role(member):
return True
return False
def has_course_moderator_role(member=None):
def has_moderator_role(member=None):
return frappe.db.get_value(
"Has Role",
{"parent": member or frappe.session.user, "role": "Moderator"},
@@ -523,7 +523,7 @@ def has_course_moderator_role(member=None):
)
def has_course_evaluator_role(member=None):
def has_evaluator_role(member=None):
return frappe.db.get_value(
"Has Role",
{"parent": member or frappe.session.user, "role": "Batch Evaluator"},
@@ -823,7 +823,7 @@ def get_telemetry_boot_info():
@frappe.whitelist()
def is_onboarding_complete():
if not has_course_moderator_role():
if not has_moderator_role():
return {"is_onboarded": True}
course_created = frappe.db.a_row_exists("LMS Course")
@@ -1266,7 +1266,7 @@ def get_lesson(course, chapter, lesson):
if (
not lesson_details.include_in_preview
and not membership
and not has_course_moderator_role()
and not has_moderator_role()
and not is_instructor(course)
):
return {
@@ -1959,9 +1959,9 @@ def get_lesson_creation_details(course, chapter, lesson):
def get_roles(name):
frappe.only_for("Moderator")
return {
"moderator": has_course_moderator_role(name),
"moderator": has_moderator_role(name),
"course_creator": has_course_instructor_role(name),
"batch_evaluator": has_course_evaluator_role(name),
"batch_evaluator": has_evaluator_role(name),
"lms_student": has_student_role(name),
}
@@ -2683,3 +2683,48 @@ def get_streak_info():
"current_streak": current_streak,
"longest_streak": longest_streak,
}
def validate_discussion_reply(doc, method):
topic = frappe.db.get_value(
"Discussion Topic", doc.topic, ["reference_doctype", "reference_docname"], as_dict=True
)
if topic.reference_doctype == "Course Lesson":
validate_course_access(topic.reference_docname)
elif topic.reference_doctype == "LMS Batch":
validate_batch_access(topic.reference_docname)
def validate_course_access(lesson):
if not frappe.db.exists("Course Lesson", lesson):
frappe.throw(_("The lesson does not exist."))
if has_moderator_role():
return
if has_course_instructor_role():
return
course = frappe.db.get_value("Course Lesson", lesson, "course")
enrollment_exists = frappe.db.exists("LMS Enrollment", {"member": frappe.session.user, "course": course})
if not enrollment_exists:
frappe.throw(_("You do not have access to this course."))
def validate_batch_access(batch):
if not frappe.db.exists("LMS Batch", batch):
frappe.throw(_("The batch does not exist."))
if has_moderator_role():
return
if has_evaluator_role():
return
enrollment_exists = frappe.db.exists(
"LMS Batch Enrollment", {"member": frappe.session.user, "batch": batch}
)
if not enrollment_exists:
frappe.throw(_("You do not have access to this batch."))
+1 -1
View File
@@ -1,6 +1,6 @@
{% set onboarding_status = is_onboarding_complete() %}
{% if has_course_moderator_role() and not onboarding_status.is_onboarded %}
{% if has_moderator_role() and not onboarding_status.is_onboarded %}
<div class="onboarding-parent">
<div class="container">
<div class="onboarding-skip">{{ _("Skip") }}</div>