fix: sanitize html of all description fields
This commit is contained in:
@@ -66,7 +66,7 @@
|
||||
<script setup lang="ts">
|
||||
import { Button, Dialog, FormControl, TextEditor, toast } from 'frappe-ui'
|
||||
import { computed, reactive, watch } from 'vue'
|
||||
import { escapeHTML } from '@/utils'
|
||||
import { escapeHTML, sanitizeHTML } from '@/utils'
|
||||
|
||||
const show = defineModel()
|
||||
const assignments = defineModel<Assignments>('assignments')
|
||||
@@ -122,12 +122,13 @@ watch(show, (newVal) => {
|
||||
}
|
||||
})
|
||||
|
||||
const validateTitle = () => {
|
||||
const validateFields = () => {
|
||||
assignment.title = escapeHTML(assignment.title.trim())
|
||||
assignment.question = sanitizeHTML(assignment.question)
|
||||
}
|
||||
|
||||
const saveAssignment = () => {
|
||||
validateTitle()
|
||||
validateFields()
|
||||
if (props.assignmentID == 'new') {
|
||||
createAssignment()
|
||||
} else {
|
||||
|
||||
@@ -104,9 +104,8 @@ import {
|
||||
} from 'frappe-ui'
|
||||
import { ref, reactive, watch } from 'vue'
|
||||
import { X } from 'lucide-vue-next'
|
||||
import { getFileSize, decodeEntities } from '@/utils'
|
||||
import { getFileSize, sanitizeHTML } from '@/utils'
|
||||
import Link from '@/components/Controls/Link.vue'
|
||||
import DOMPurify from 'dompurify'
|
||||
|
||||
const reloadProfile = defineModel('reloadProfile')
|
||||
const hasLanguageChanged = ref(false)
|
||||
@@ -157,22 +156,7 @@ const updateProfile = createResource({
|
||||
})
|
||||
|
||||
const saveProfile = (close) => {
|
||||
profile.bio = DOMPurify.sanitize(decodeEntities(profile.bio), {
|
||||
ALLOWED_TAGS: [
|
||||
'b',
|
||||
'i',
|
||||
'em',
|
||||
'strong',
|
||||
'a',
|
||||
'p',
|
||||
'br',
|
||||
'ul',
|
||||
'ol',
|
||||
'li',
|
||||
'img',
|
||||
],
|
||||
ALLOWED_ATTR: ['href', 'target', 'src'],
|
||||
})
|
||||
profile.bio = sanitizeHTML(profile.bio)
|
||||
updateProfile.submit(
|
||||
{},
|
||||
{
|
||||
|
||||
@@ -340,11 +340,12 @@ import { sessionStore } from '../stores/session'
|
||||
import MultiSelect from '@/components/Controls/MultiSelect.vue'
|
||||
import Link from '@/components/Controls/Link.vue'
|
||||
import {
|
||||
openSettings,
|
||||
escapeHTML,
|
||||
getMetaInfo,
|
||||
openSettings,
|
||||
sanitizeHTML,
|
||||
updateMetaInfo,
|
||||
validateFile,
|
||||
escapeHTML,
|
||||
} from '@/utils'
|
||||
|
||||
const router = useRouter()
|
||||
@@ -502,6 +503,9 @@ const imageResource = createResource({
|
||||
})
|
||||
|
||||
const validateFields = () => {
|
||||
batch.description = sanitizeHTML(batch.description)
|
||||
batch.batch_details = sanitizeHTML(batch.batch_details)
|
||||
|
||||
Object.keys(batch).forEach((key) => {
|
||||
if (
|
||||
!['description', 'batch_details'].includes(key) &&
|
||||
|
||||
@@ -353,11 +353,12 @@ import { capture, startRecording, stopRecording } from '@/telemetry'
|
||||
import { useOnboarding } from 'frappe-ui/frappe'
|
||||
import { sessionStore } from '../stores/session'
|
||||
import {
|
||||
openSettings,
|
||||
escapeHTML,
|
||||
getMetaInfo,
|
||||
openSettings,
|
||||
sanitizeHTML,
|
||||
updateMetaInfo,
|
||||
validateFile,
|
||||
escapeHTML,
|
||||
} from '@/utils'
|
||||
import Link from '@/components/Controls/Link.vue'
|
||||
import CourseOutline from '@/components/CourseOutline.vue'
|
||||
@@ -539,6 +540,8 @@ const imageResource = createResource({
|
||||
})
|
||||
|
||||
const validateFields = () => {
|
||||
course.description = sanitizeHTML(course.description)
|
||||
|
||||
Object.keys(course).forEach((key) => {
|
||||
if (key != 'description' && typeof course[key] === 'string') {
|
||||
course[key] = escapeHTML(course[key])
|
||||
|
||||
@@ -158,7 +158,7 @@ import { computed, onMounted, reactive, inject } from 'vue'
|
||||
import { FileText, X } from 'lucide-vue-next'
|
||||
import { sessionStore } from '@/stores/session'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { escapeHTML, getFileSize, validateFile } from '@/utils'
|
||||
import { escapeHTML, getFileSize, sanitizeHTML, validateFile } from '@/utils'
|
||||
|
||||
const user = inject('$user')
|
||||
const router = useRouter()
|
||||
@@ -314,6 +314,7 @@ const editJobDetails = () => {
|
||||
}
|
||||
|
||||
const validateJobFields = () => {
|
||||
job.description = sanitizeHTML(job.description)
|
||||
Object.keys(job).forEach((key) => {
|
||||
if (key != 'description' && typeof job[key] === 'string') {
|
||||
job[key] = escapeHTML(job[key])
|
||||
|
||||
@@ -19,6 +19,7 @@ import SimpleImage from '@editorjs/simple-image'
|
||||
import Table from '@editorjs/table'
|
||||
import Plyr from 'plyr'
|
||||
import 'plyr/dist/plyr.css'
|
||||
import DOMPurify from 'dompurify'
|
||||
|
||||
const readOnlyMode = window.read_only_mode
|
||||
|
||||
@@ -540,6 +541,26 @@ export const escapeHTML = (text) => {
|
||||
)
|
||||
}
|
||||
|
||||
export const sanitizeHTML = (text) => {
|
||||
text = DOMPurify.sanitize(decodeEntities(text), {
|
||||
ALLOWED_TAGS: [
|
||||
'b',
|
||||
'i',
|
||||
'em',
|
||||
'strong',
|
||||
'a',
|
||||
'p',
|
||||
'br',
|
||||
'ul',
|
||||
'ol',
|
||||
'li',
|
||||
'img',
|
||||
],
|
||||
ALLOWED_ATTR: ['href', 'target', 'src'],
|
||||
})
|
||||
return text
|
||||
}
|
||||
|
||||
export const canCreateCourse = () => {
|
||||
const { userResource } = usersStore()
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user