fix: misc permission issues

This commit is contained in:
Jannat Patel
2025-12-04 17:15:14 +05:30
parent 0367c1db72
commit 836a6d1203
13 changed files with 1518 additions and 79 deletions

View File

@@ -675,7 +675,7 @@ export const getMetaInfo = (type, route, meta) => {
export const updateMetaInfo = (type, route, meta) => {
call('lms.lms.api.update_meta_info', {
type: type,
meta_type: type,
route: route,
meta_tags: [
{ key: 'description', value: meta.description },

View File

@@ -813,7 +813,6 @@ 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)
@@ -1453,11 +1452,11 @@ def get_meta_info(type, route):
@frappe.whitelist()
def update_meta_info(type, route, meta_tags):
parent_name = f"{type}/{route}"
if not isinstance(meta_tags, list):
frappe.throw(_("Meta tags should be a list."))
def update_meta_info(meta_type, route, meta_tags):
validate_meta_data_permissions()
validate_meta_tags(meta_tags)
parent_name = f"{meta_type}/{route}"
for tag in meta_tags:
existing_tag = frappe.db.exists(
"Website Meta Tag",
@@ -1484,18 +1483,43 @@ def update_meta_info(type, route, meta_tags):
parent_exists = frappe.db.exists("Website Route Meta", parent_name)
if not parent_exists:
route_meta = frappe.new_doc("Website Route Meta")
route_meta.update(
{
"__newname": parent_name,
}
)
route_meta.append("meta_tags", tag_properties)
route_meta.insert()
create_meta(parent_name, tag_properties)
else:
new_tag = frappe.new_doc("Website Meta Tag")
new_tag.update(tag_properties)
new_tag.insert()
create_meta_tag(tag_properties)
def validate_meta_tags(meta_tags):
if not isinstance(meta_tags, list):
frappe.throw(_("Meta tags should be a list."))
def create_meta(parent_name, tag_properties):
route_meta = frappe.new_doc("Website Route Meta")
route_meta.update(
{
"__newname": parent_name,
}
)
route_meta.append("meta_tags", tag_properties)
route_meta.insert()
def create_meta_tag(tag_properties):
new_tag = frappe.new_doc("Website Meta Tag")
new_tag.update(tag_properties)
new_tag.insert()
def validate_meta_data_permissions(meta_type):
roles = frappe.get_roles()
if meta_type == "courses":
if not ("Course Creator" in roles or "Moderator" in roles):
frappe.throw(_("You do not have permission to update meta tags."))
elif meta_type == "batches":
if not ("Batch Evaluator" in roles or "Moderator" in roles):
frappe.throw(_("You do not have permission to update meta tags."))
@frappe.whitelist()

View File

@@ -30,9 +30,7 @@ frappe.ui.form.on("LMS Badge", {
const user_fields = fields
.filter(
(df) =>
(df.fieldtype === "Link" && df.options === "User") ||
df.fieldtype === "Data"
(df) => df.fieldtype === "Link" && df.options === "User"
)
.map(map_for_options)
.concat([

View File

@@ -84,7 +84,7 @@
"grid_page_length": 50,
"index_web_pages_for_search": 1,
"links": [],
"modified": "2025-11-10 11:39:42.233779",
"modified": "2025-12-04 17:06:26.090276",
"modified_by": "sayali@frappe.io",
"module": "LMS",
"name": "LMS Badge Assignment",
@@ -116,25 +116,13 @@
},
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "LMS Student",
"share": 1,
"write": 1
"role": "LMS Student"
},
{
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "LMS Student",
"share": 1
"role": "LMS Student"
},
{
"create": 1,

View File

@@ -1,9 +1,64 @@
# Copyright (c) 2024, Frappe and contributors
# For license information, please see license.txt
# import frappe
import frappe
from frappe import _
from frappe.model.document import Document
from lms.lms.doctype.lms_badge.lms_badge import eval_condition
class LMSBadgeAssignment(Document):
pass
def validate(self):
self.validate_owner()
self.validate_duplicate_badge_assignment()
self.validate_badge_criteria()
def validate_owner(self):
if self.owner == self.member:
return
roles = frappe.get_roles(self.owner)
if "Moderator" not in roles:
frappe.throw(_("You must be a Moderator to assign badges to users."))
def validate_duplicate_badge_assignment(self):
grant_only_once = frappe.db.get_value("LMS Badge", self.badge, "grant_only_once")
if not grant_only_once:
return
if frappe.db.exists(
"LMS Badge Assignment",
{"badge": self.badge, "member": self.member, "name": ["!=", self.name]},
):
frappe.throw(
_("Badge {0} has already been assigned to this {1}.").format(self.badge, self.member)
)
def validate_badge_criteria(self):
badge_details = frappe.db.get_value(
"LMS Badge", self.badge, ["reference_doctype", "user_field", "condition", "enabled"], as_dict=True
)
if badge_details:
if badge_details.reference_doctype and badge_details.user_field and badge_details.condition:
user_fieldname = frappe.db.get_value(
"DocField",
{"parent": badge_details.reference_doctype, "fieldname": badge_details.user_field},
"fieldname",
)
documents = frappe.get_all(
badge_details.reference_doctype,
{user_fieldname: self.member},
)
for document in documents:
reference_value = eval_condition(
frappe.get_doc(badge_details.reference_doctype, document.name),
badge_details.condition,
)
if reference_value:
return
frappe.throw(_("Member does not meet the criteria for the badge {0}.").format(self.badge))

View File

@@ -379,7 +379,7 @@
"link_fieldname": "batch_name"
}
],
"modified": "2025-05-26 15:30:55.083507",
"modified": "2025-12-04 12:54:11.190967",
"modified_by": "sayali@frappe.io",
"module": "LMS",
"name": "LMS Batch",
@@ -422,13 +422,8 @@
"write": 1
},
{
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "LMS Student",
"share": 1
"role": "LMS Student"
}
],
"row_format": "Dynamic",

View File

@@ -73,8 +73,8 @@
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2025-02-11 10:39:57.259526",
"modified_by": "Administrator",
"modified": "2025-12-04 12:53:38.246250",
"modified_by": "sayali@frappe.io",
"module": "LMS",
"name": "LMS Batch Enrollment",
"owner": "Administrator",
@@ -105,18 +105,14 @@
},
{
"create": 1,
"email": 1,
"export": 1,
"if_owner": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "LMS Student",
"share": 1
"role": "LMS Student"
}
],
"row_format": "Dynamic",
"sort_field": "creation",
"sort_order": "DESC",
"states": [],
"title_field": "member_name"
}
}

View File

@@ -15,10 +15,19 @@ class LMSBatchEnrollment(Document):
self.add_member_to_live_class()
def validate(self):
self.validate_owner()
self.validate_duplicate_members()
self.validate_seat_availability()
self.validate_course_enrollment()
def validate_owner(self):
if self.owner == self.member:
return
roles = frappe.get_roles(self.owner)
if not ("Moderator" in roles or "Batch Evaluator" in roles):
frappe.throw(_("You must be a Moderator or Batch Evaluator to enroll users in a batch."))
def validate_duplicate_members(self):
if frappe.db.exists(
"LMS Batch Enrollment",

View File

@@ -115,29 +115,14 @@ def has_website_permission(doc, ptype, user, verbose=False):
@frappe.whitelist()
def create_certificate(course):
certificate = is_certified(course)
if certificate:
if is_certified(course):
return frappe.db.get_value(
"LMS Certificate", certificate, ["name", "course", "template"], as_dict=True
)
else:
default_certificate_template = frappe.db.get_value(
"Property Setter",
{
"doc_type": "LMS Certificate",
"property": "default_print_format",
},
"value",
)
if not default_certificate_template:
default_certificate_template = frappe.db.get_value(
"Print Format",
{
"doc_type": "LMS Certificate",
},
)
validate_certification_eligibility(course)
default_certificate_template = get_default_certificate_template()
certificate = frappe.get_doc(
{
"doctype": "LMS Certificate",
@@ -149,3 +134,37 @@ def create_certificate(course):
)
certificate.save(ignore_permissions=True)
return certificate
def get_default_certificate_template():
default_certificate_template = frappe.db.get_value(
"Property Setter",
{
"doc_type": "LMS Certificate",
"property": "default_print_format",
},
"value",
)
if not default_certificate_template:
default_certificate_template = frappe.db.get_value(
"Print Format",
{
"doc_type": "LMS Certificate",
},
)
return default_certificate_template
def validate_certification_eligibility(course):
if not frappe.db.exists("LMS Enrollment", {"course": course, "member": frappe.session.user}):
frappe.throw(_("You are not enrolled in this course."))
if not frappe.db.get_value("LMS Course", course, "enable_certification"):
frappe.throw(_("Certification is not enabled for this course."))
progress = frappe.db.get_value(
"LMS Enrollment", {"course": course, "member": frappe.session.user}, "progress"
)
if progress < 100:
frappe.throw(_("You have not completed the course yet."))

View File

@@ -92,7 +92,7 @@
"grid_page_length": 50,
"index_web_pages_for_search": 1,
"links": [],
"modified": "2025-08-20 12:28:57.238902",
"modified": "2025-12-04 12:56:14.249363",
"modified_by": "sayali@frappe.io",
"module": "LMS",
"name": "LMS Program",
@@ -136,13 +136,8 @@
"write": 1
},
{
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "LMS Student",
"share": 1
"role": "LMS Student"
}
],
"row_format": "Dynamic",

View File

@@ -2206,6 +2206,11 @@ def get_program_details(program_name):
def enroll_in_program(program):
if frappe.session.user == "Guest":
frappe.throw(_("Please login to enroll in the program."))
published = frappe.db.get_value("LMS Program", program, "published")
if not published:
frappe.throw(_("You cannot enroll in an unpublished program."))
if not frappe.db.exists("LMS Program Member", {"parent": program, "member": frappe.session.user}):
program_member = frappe.new_doc("LMS Program Member")
program_member.update(

View File

@@ -25,7 +25,7 @@
},
"homepage": "https://github.com/frappe/lms#readme",
"devDependencies": {
"cypress": "^14.5.2",
"cypress": "^15.7.1",
"cypress-file-upload": "^5.0.8",
"cypress-real-events": "^1.14.0"
},

1355
yarn.lock Normal file

File diff suppressed because it is too large Load Diff