mirror of
https://github.com/frappe/lms.git
synced 2026-05-02 13:39:31 +03:00
fix(lesson): sanitize lesson client side
This commit is contained in:
@@ -57,7 +57,7 @@
|
||||
>
|
||||
</iframe>
|
||||
</div>
|
||||
<div v-else v-html="markdown.render(block)"></div>
|
||||
<div v-else v-html="renderSafe(block)"></div>
|
||||
</div>
|
||||
<div v-if="quizId">
|
||||
<Quiz :quiz="quizId" />
|
||||
@@ -66,6 +66,7 @@
|
||||
<script setup>
|
||||
import Quiz from '@/components/QuizBlock.vue'
|
||||
import MarkdownIt from 'markdown-it'
|
||||
import DOMPurify from 'dompurify'
|
||||
import { useScreenSize } from '@/utils/composables'
|
||||
|
||||
const screenSize = useScreenSize()
|
||||
@@ -75,6 +76,8 @@ const markdown = new MarkdownIt({
|
||||
linkify: true,
|
||||
})
|
||||
|
||||
const renderSafe = (block) => DOMPurify.sanitize(markdown.render(block))
|
||||
|
||||
const props = defineProps({
|
||||
content: {
|
||||
type: String,
|
||||
|
||||
@@ -365,7 +365,12 @@ import {
|
||||
MessageCircleQuestion,
|
||||
TrendingUp,
|
||||
} from 'lucide-vue-next'
|
||||
import { getEditorTools, enablePlyr, highlightText } from '@/utils'
|
||||
import {
|
||||
getEditorTools,
|
||||
enablePlyr,
|
||||
highlightText,
|
||||
sanitizeEditorJs,
|
||||
} from '@/utils'
|
||||
import { sessionStore } from '@/stores/session'
|
||||
import { useSidebar } from '@/stores/sidebar'
|
||||
import EditorJS from '@editorjs/editorjs'
|
||||
@@ -511,7 +516,7 @@ const renderEditor = (holder, content) => {
|
||||
return new EditorJS({
|
||||
holder: holder,
|
||||
tools: getEditorTools(),
|
||||
data: JSON.parse(content),
|
||||
data: sanitizeEditorJs(JSON.parse(content)),
|
||||
readOnly: true,
|
||||
defaultBlock: 'embed',
|
||||
i18n: {
|
||||
|
||||
@@ -104,7 +104,7 @@ import { sessionStore } from '../stores/session'
|
||||
import EditorJS from '@editorjs/editorjs'
|
||||
import LessonHelp from '@/components/LessonHelp.vue'
|
||||
import { ChevronRight } from 'lucide-vue-next'
|
||||
import { getEditorTools, enablePlyr } from '@/utils'
|
||||
import { getEditorTools, enablePlyr, sanitizeEditorJs } from '@/utils'
|
||||
import { useOnboarding, useTelemetry } from 'frappe-ui/frappe'
|
||||
|
||||
const { brand } = sessionStore()
|
||||
@@ -191,7 +191,7 @@ const lessonDetails = createResource({
|
||||
const addLessonContent = (data) => {
|
||||
editor.value.isReady.then(() => {
|
||||
if (data.lesson.content) {
|
||||
editor.value.render(JSON.parse(data.lesson.content))
|
||||
editor.value.render(sanitizeEditorJs(JSON.parse(data.lesson.content)))
|
||||
} else if (data.lesson.body) {
|
||||
let blocks = convertToJSON(data.lesson)
|
||||
editor.value.render({
|
||||
@@ -204,7 +204,9 @@ const addLessonContent = (data) => {
|
||||
const addInstructorNotes = (data) => {
|
||||
instructorEditor.value.isReady.then(() => {
|
||||
if (data.lesson.instructor_content) {
|
||||
instructorEditor.value.render(JSON.parse(data.lesson.instructor_content))
|
||||
instructorEditor.value.render(
|
||||
sanitizeEditorJs(JSON.parse(data.lesson.instructor_content))
|
||||
)
|
||||
} else if (data.lesson.instructor_notes) {
|
||||
let blocks = convertToJSON(data.lesson)
|
||||
instructorEditor.value.render({
|
||||
|
||||
@@ -706,6 +706,34 @@ export const escapeHTML = (text) => {
|
||||
)
|
||||
}
|
||||
|
||||
const sanitizeJSON = (node) => {
|
||||
if (Array.isArray(node)) return node.map(sanitizeJSON)
|
||||
if (node && typeof node === 'object') {
|
||||
const temp = {}
|
||||
for (const n in node) {
|
||||
temp[n] = sanitizeJSON(node[n])
|
||||
}
|
||||
return temp
|
||||
}
|
||||
if (
|
||||
typeof node === 'string' &&
|
||||
(node.includes('<') || node.includes('>'))
|
||||
) {
|
||||
return DOMPurify.sanitize(node)
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
export const sanitizeEditorJs = (data) => {
|
||||
if (!data || !Array.isArray(data.blocks)) return data
|
||||
for (const node of data.blocks) {
|
||||
if (node && node.type !== 'code') {
|
||||
node.data = sanitizeJSON(node.data)
|
||||
}
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
export const sanitizeHTML = (text) => {
|
||||
text = DOMPurify.sanitize(decodeEntities(text), {
|
||||
ALLOWED_TAGS: [
|
||||
|
||||
Reference in New Issue
Block a user