fix: permission issues when adding new members

This commit is contained in:
Jannat Patel
2026-02-16 18:05:53 +05:30
parent 9f6f717585
commit eba1815390
12 changed files with 739 additions and 674 deletions
@@ -16,7 +16,12 @@
<button
class="flex w-full items-center justify-between focus:outline-none"
:class="inputClasses"
@click="() => togglePopover()"
@click="
() => {
showOptions = !showOptions
togglePopover()
}
"
:disabled="attrs.readonly"
>
<div class="flex items-center w-[90%]">
@@ -93,7 +93,7 @@
<div class="space-y-4">
<div
class="font-medium text-ink-gray-9"
:class="{ 'mt-8': course.data.membership && !readOnlyMode }"
:class="{ 'mt-8': !readOnlyMode }"
>
{{ __('This course has:') }}
</div>
+31 -28
View File
@@ -117,7 +117,15 @@
</Dialog>
</template>
<script setup lang="ts">
import { Avatar, Button, createResource, Dialog, FormControl } from 'frappe-ui'
import {
Avatar,
Button,
call,
createResource,
Dialog,
FormControl,
toast,
} from 'frappe-ui'
import { useRouter } from 'vue-router'
import { ref, watch, reactive, inject } from 'vue'
import { RefreshCw, Plus, Search, Shield } from 'lucide-vue-next'
@@ -184,34 +192,29 @@ const openProfile = (username: string) => {
})
}
const newMember = createResource({
url: 'frappe.client.insert',
makeParams() {
return {
doc: {
doctype: 'User',
first_name: member.first_name,
email: member.email,
},
}
},
auto: false,
onSuccess(data: Member) {
show.value = false
if (user?.data?.is_system_manager) updateOnboardingStep('invite_students')
router.push({
name: 'ProfileRoles',
params: {
username: data.username,
},
})
},
})
const addMember = (close: () => void) => {
newMember.reload()
close()
call('frappe.client.insert', {
doc: {
doctype: 'User',
first_name: member.first_name,
email: member.email,
},
})
.then((data: Member) => {
if (user?.data?.is_system_manager) updateOnboardingStep('invite_students')
show.value = false
router.push({
name: 'ProfileRoles',
params: {
username: data.username,
},
})
close()
})
.catch((err: any) => {
console.error(err)
toast.error(__(err.messages?.[0] || err))
})
}
watch(search, () => {
@@ -20,7 +20,7 @@
<NumberChartGraph :title="__('Lessons')" :value="course.data?.lessons" />
</div>
<div class="grid grid-cols-[2fr_1fr] gap-5 items-start">
<div v-if="course.data?.enrollments" class="border rounded-lg py-3 px-4">
<div class="border rounded-lg py-3 px-4">
<div class="flex items-center justify-between mb-3">
<div class="text-lg text-ink-gray-9 font-semibold">
{{ __('Students') }}
@@ -244,6 +244,7 @@
v-if="showEnrollmentModal"
v-model="showEnrollmentModal"
:course="course"
:students="progressList"
/>
<StudentCourseProgress
v-if="showProgressModal"
@@ -58,6 +58,7 @@ import Link from '@/components/Controls/Link.vue'
const show = defineModel<boolean>({ required: true, default: false })
const student = ref<string | null>(null)
const students = defineModel<any[]>('students')
const payment = ref<string | null>(null)
const purchasedCertificate = ref<boolean>(false)
@@ -79,6 +80,7 @@ const enrollStudent = (close: () => void) => {
},
})
.then(() => {
students.value?.reload()
toast.success(__('Student enrolled successfully'))
close()
})
+626 -633
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -47,6 +47,7 @@ ALLOWED_PATHS = [
"/api/method/frappe.core.doctype.user.user.reset_password",
"/api/method/frappe.desk.doctype.notification_log.notification_log.mark_as_read",
"/api/method/frappe.desk.doctype.notification_log.notification_log.mark_all_as_read",
"/api/method/frappe.sessions.clear",
]
+34 -7
View File
@@ -7,6 +7,7 @@ from lms.lms.api import give_discussions_permission
def after_install():
create_batch_source()
give_discussions_permission()
give_user_list_permission()
def after_sync():
@@ -27,13 +28,6 @@ def create_lms_roles():
create_lms_student_role()
def delete_lms_roles():
roles = ["Course Creator", "Moderator"]
for role in roles:
if frappe.db.exists("Role", role):
frappe.db.delete("Role", role)
def create_course_creator_role():
if frappe.db.exists("Role", "Course Creator"):
frappe.db.set_value("Role", "Course Creator", "desk_access", 0)
@@ -185,3 +179,36 @@ def give_lms_roles_to_admin():
doc.parentfield = "roles"
doc.role = role
doc.save()
def give_user_list_permission():
doctype = "User"
roles = ["Course Creator", "Moderator", "Batch Evaluator"]
for role in roles:
permlevel = 0
create_role(doctype, role, permlevel)
create_role(doctype, "System Manager", 1)
def create_role(doctype, role, permlevel):
if not frappe.db.exists("Custom DocPerm", {"parent": doctype, "role": role, "permlevel": permlevel}):
doc = frappe.new_doc("Custom DocPerm")
doc.update(
{
"doctype": "Custom DocPerm",
"parent": doctype,
"role": role,
"read": 1,
"write": 1 if role in ["Moderator", "System Manager"] else 0,
"create": 1 if role == "Moderator" else 0,
"permlevel": permlevel,
}
)
doc.save()
def delete_lms_roles():
roles = ["Course Creator", "Moderator", "Batch Evaluator", "LMS Student"]
for role in roles:
if frappe.db.exists("Role", role):
frappe.db.delete("Role", role)
@@ -8,9 +8,15 @@ from frappe.utils import ceil
class LMSEnrollment(Document):
def before_insert(self):
def validate(self):
self.validate_duplicate_enrollment()
self.validate_course_enrollment_eligibility()
self.validate_owner()
def validate_owner(self):
"""Makes the member as the owner of the document so that users can update their progress"""
if self.owner != self.member:
self.owner = self.member
def on_update(self):
update_program_progress(self.member)
@@ -45,7 +51,7 @@ class LMSEnrollment(Document):
if self.enrollment_from_batch:
return
if not course_details.published:
if not course_details.published and not is_admin():
frappe.throw(_("You cannot enroll in an unpublished course."))
if course_details.paid_course:
+3 -1
View File
@@ -115,4 +115,6 @@ lms.patches.v2_0.fix_scorm_lesson_reference_idx #02-09-2025
lms.patches.v2_0.certified_members_to_certifications #05-10-2025
lms.patches.v2_0.fix_job_application_resume_urls
lms.patches.v2_0.open_to_opportunities
lms.patches.v2_0.open_to_work
lms.patches.v2_0.open_to_work
lms.patches.v2_0.share_enrollment
lms.patches.v2_0.give_user_list_permission #11-02-2026
@@ -0,0 +1,5 @@
from lms.install import give_user_list_permission
def execute():
give_user_list_permission()
+20
View File
@@ -0,0 +1,20 @@
import frappe
def execute():
enrollments = frappe.get_all("LMS Enrollment", ["name", "member", "owner"])
for enrollment in enrollments:
if enrollment.owner == enrollment.member:
continue
filters = {
"user": enrollment.member,
"share_doctype": "LMS Enrollment",
"share_name": enrollment.name,
}
is_shared = frappe.db.exists("DocShare", filters)
if not is_shared:
share = frappe.new_doc("DocShare")
filters.update({"read": 1, "notify_by_email": 0})
share.update(filters)
share.save()