fix: roles, permission and access on profile page

This commit is contained in:
Jannat Patel
2025-11-06 12:21:12 +05:30
parent 27d2297e2b
commit 28be3891d2
8 changed files with 90 additions and 30 deletions
+37 -6
View File
@@ -66,7 +66,11 @@
</template> </template>
{{ __('View Certificate') }} {{ __('View Certificate') }}
</Button> </Button>
<Button v-else @click="openCallLink(event.venue)" class="w-full"> <Button
v-else-if="userIsEvaluator()"
@click="openCallLink(event.venue)"
class="w-full"
>
<template #prefix> <template #prefix>
<Video class="h-4 w-4 stroke-1.5" /> <Video class="h-4 w-4 stroke-1.5" />
</template> </template>
@@ -83,21 +87,31 @@
class="flex flex-col space-y-4 p-5" class="flex flex-col space-y-4 p-5"
> >
<div class="flex items-center justify-between"> <div class="flex items-center justify-between">
<Rating v-model="evaluation.rating" :label="__('Rating')" /> <Rating
v-model="evaluation.rating"
:label="__('Rating')"
:disabled="!userIsEvaluator()"
/>
<FormControl <FormControl
type="select" type="select"
:options="statusOptions" :options="statusOptions"
v-model="evaluation.status" v-model="evaluation.status"
:label="__('Status')" :label="__('Status')"
class="w-1/2" class="w-1/2"
:disabled="!userIsEvaluator()"
/> />
</div> </div>
<Textarea <Textarea
v-model="evaluation.summary" v-model="evaluation.summary"
:label="__('Summary')" :label="__('Summary')"
:rows="7" :rows="7"
:disabled="!userIsEvaluator()"
/> />
<Button variant="solid" @click="saveEvaluation()"> <Button
v-if="userIsEvaluator()"
variant="solid"
@click="saveEvaluation()"
>
{{ __('Save') }} {{ __('Save') }}
</Button> </Button>
</div> </div>
@@ -106,11 +120,13 @@
type="checkbox" type="checkbox"
v-model="certificate.published" v-model="certificate.published"
:label="__('Published')" :label="__('Published')"
:disabled="!userIsEvaluator()"
/> />
<Link <Link
v-model="certificate.template" v-model="certificate.template"
:label="__('Template')" :label="__('Template')"
doctype="Print Format" doctype="Print Format"
:disabled="!userIsEvaluator()"
:filters="{ :filters="{
doc_type: 'LMS Certificate', doc_type: 'LMS Certificate',
}" }"
@@ -118,14 +134,20 @@
<FormControl <FormControl
type="date" type="date"
v-model="certificate.issue_date" v-model="certificate.issue_date"
:disabled="!userIsEvaluator()"
:label="__('Issue Date')" :label="__('Issue Date')"
/> />
<FormControl <FormControl
type="date" type="date"
v-model="certificate.expiry_date" v-model="certificate.expiry_date"
:disabled="!userIsEvaluator()"
:label="__('Expiry Date')" :label="__('Expiry Date')"
/> />
<Button variant="solid" @click="saveCertificate()"> <Button
v-if="userIsEvaluator()"
variant="solid"
@click="saveCertificate()"
>
{{ __('Save') }} {{ __('Save') }}
</Button> </Button>
</div> </div>
@@ -163,6 +185,7 @@ import Rating from '@/components/Controls/Rating.vue'
import Link from '@/components/Controls/Link.vue' import Link from '@/components/Controls/Link.vue'
const show = defineModel() const show = defineModel()
const user = inject('$user')
const dayjs = inject('$dayjs') const dayjs = inject('$dayjs')
const tabIndex = ref(0) const tabIndex = ref(0)
const showCertification = ref(false) const showCertification = ref(false)
@@ -175,9 +198,18 @@ const props = defineProps({
}) })
const evaluation = reactive({}) const evaluation = reactive({})
const certificate = reactive({}) const certificate = reactive({})
watch(user, () => {
if (userIsEvaluator()) {
defaultTemplate.reload()
}
})
const userIsEvaluator = () => {
return user.data && user.data.name == props.event.evaluator
}
const defaultTemplate = createResource({ const defaultTemplate = createResource({
url: 'frappe.client.get_value', url: 'frappe.client.get_value',
makeParams(values) { makeParams(values) {
@@ -190,7 +222,6 @@ const defaultTemplate = createResource({
}, },
} }
}, },
auto: true,
onSuccess(data) { onSuccess(data) {
certificate.template = data.value certificate.template = data.value
}, },
+6 -10
View File
@@ -124,19 +124,13 @@ const props = defineProps({
onMounted(() => { onMounted(() => {
if ($user.data) profile.reload() if ($user.data) profile.reload()
setActiveTab() setActiveTab()
}) })
const profile = createResource({ const profile = createResource({
url: 'frappe.client.get', url: 'lms.lms.api.get_profile_details',
makeParams(values) { params: {
return { username: props.username,
doctype: 'User',
filters: {
username: props.username,
},
}
}, },
}) })
@@ -183,6 +177,7 @@ watch(
() => props.username, () => props.username,
() => { () => {
profile.reload() profile.reload()
getProfileRoles()
} }
) )
@@ -199,6 +194,7 @@ const hasHigherAccess = () => {
} }
const isEvaluatorOrModerator = () => { const isEvaluatorOrModerator = () => {
console.log(profile.data)
return ( return (
profile.data?.roles.filter( profile.data?.roles.filter(
(row) => row.role === 'Moderator' || row.role === 'Evaluator' (row) => row.role === 'Moderator' || row.role === 'Evaluator'
@@ -210,7 +206,7 @@ const getTabButtons = () => {
let buttons = [{ label: 'About' }, { label: 'Certificates' }] let buttons = [{ label: 'About' }, { label: 'Certificates' }]
if ($user.data?.is_moderator) buttons.push({ label: 'Roles' }) if ($user.data?.is_moderator) buttons.push({ label: 'Roles' })
if (hasHigherAccess() && isEvaluatorOrModerator()) { if (hasHigherAccess()) {
buttons.push({ label: 'Slots' }) buttons.push({ label: 'Slots' })
buttons.push({ label: 'Schedule' }) buttons.push({ label: 'Schedule' })
} }
@@ -36,7 +36,7 @@
</Calendar> </Calendar>
</div> </div>
</div> </div>
<Event v-model="showEvent" :event="currentEvent" /> <Event v-if="showEvent" v-model="showEvent" :event="currentEvent" />
</template> </template>
<script setup> <script setup>
import { Calendar, createListResource, Button } from 'frappe-ui' import { Calendar, createListResource, Button } from 'frappe-ui'
@@ -153,6 +153,7 @@ import { Play, X, Check, Settings } from 'lucide-vue-next'
import { sessionStore } from '@/stores/session' import { sessionStore } from '@/stores/session'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { openSettings } from '@/utils' import { openSettings } from '@/utils'
import { useSettings } from '@/stores/settings'
const user = inject<any>('$user') const user = inject<any>('$user')
const code = ref<string | null>('') const code = ref<string | null>('')
@@ -162,7 +163,8 @@ const errorMessage = ref<string | null>(null)
const testCaseSection = ref<HTMLElement | null>(null) const testCaseSection = ref<HTMLElement | null>(null)
const testCases = ref<TestCase[]>([]) const testCases = ref<TestCase[]>([])
const boilerplate = ref<string>('') const boilerplate = ref<string>('')
const { brand, livecodeURL } = sessionStore() const { brand } = sessionStore()
const { livecodeURL } = useSettings()
const router = useRouter() const router = useRouter()
const fromLesson = ref(false) const fromLesson = ref(false)
const falconURL = ref<string>('https://falcon.frappe.io/') const falconURL = ref<string>('https://falcon.frappe.io/')
-11
View File
@@ -54,16 +54,6 @@ export const sessionStore = defineStore('lms-session', () => {
}, },
}) })
const livecodeURL = createResource({
url: 'frappe.client.get_single_value',
params: {
doctype: 'LMS Settings',
field: 'livecode_url',
},
cache: 'livecodeURL',
auto: user.value ? true : false,
})
return { return {
user, user,
isLoggedIn, isLoggedIn,
@@ -71,6 +61,5 @@ export const sessionStore = defineStore('lms-session', () => {
logout, logout,
brand, brand,
branding, branding,
livecodeURL,
} }
}) })
+7
View File
@@ -41,6 +41,13 @@ export const useSettings = defineStore('settings', () => {
auto: false, auto: false,
}) })
const livecodeURL = createResource({
url: 'lms.lms.api.get_lms_setting',
params: { field: 'livecode_url' },
auto: true,
cache: ['livecodeURL'],
})
return { return {
isSettingsOpen, isSettingsOpen,
activeTab, activeTab,
+11
View File
@@ -1672,3 +1672,14 @@ def get_pwa_manifest():
} }
return Response(json.dumps(manifest), status=200, content_type="application/manifest+json") return Response(json.dumps(manifest), status=200, content_type="application/manifest+json")
@frappe.whitelist()
def get_profile_details(username):
print(username)
return frappe.db.get_value(
"User",
{"username": username},
["full_name", "name", "username", "user_image", "bio", "headline", "cover_image"],
as_dict=True,
)
@@ -84,7 +84,7 @@
"grid_page_length": 50, "grid_page_length": 50,
"index_web_pages_for_search": 1, "index_web_pages_for_search": 1,
"links": [], "links": [],
"modified": "2025-07-07 20:37:22.449149", "modified": "2025-11-06 11:38:35.903520",
"modified_by": "sayali@frappe.io", "modified_by": "sayali@frappe.io",
"module": "LMS", "module": "LMS",
"name": "LMS Badge Assignment", "name": "LMS Badge Assignment",
@@ -135,6 +135,30 @@
"report": 1, "report": 1,
"role": "LMS Student", "role": "LMS Student",
"share": 1 "share": 1
},
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Batch Evaluator",
"share": 1,
"write": 1
},
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Course Creator",
"share": 1,
"write": 1
} }
], ],
"row_format": "Dynamic", "row_format": "Dynamic",