fix: don't allow unnecessary attributes in profile bio
This commit is contained in:
@@ -30,6 +30,7 @@
|
|||||||
"chart.js": "^4.4.1",
|
"chart.js": "^4.4.1",
|
||||||
"codemirror": "^6.0.1",
|
"codemirror": "^6.0.1",
|
||||||
"dayjs": "^1.11.6",
|
"dayjs": "^1.11.6",
|
||||||
|
"dompurify": "^3.2.6",
|
||||||
"feather-icons": "^4.28.0",
|
"feather-icons": "^4.28.0",
|
||||||
"frappe-ui": "0.1.173",
|
"frappe-ui": "0.1.173",
|
||||||
"highlight.js": "^11.11.1",
|
"highlight.js": "^11.11.1",
|
||||||
|
|||||||
@@ -97,7 +97,8 @@ import {
|
|||||||
} from 'frappe-ui'
|
} from 'frappe-ui'
|
||||||
import { reactive, watch } from 'vue'
|
import { reactive, watch } from 'vue'
|
||||||
import { FileText, X } from 'lucide-vue-next'
|
import { FileText, X } from 'lucide-vue-next'
|
||||||
import { getFileSize } from '@/utils'
|
import { getFileSize, decodeEntities } from '@/utils'
|
||||||
|
import DOMPurify from 'dompurify'
|
||||||
|
|
||||||
const reloadProfile = defineModel('reloadProfile')
|
const reloadProfile = defineModel('reloadProfile')
|
||||||
|
|
||||||
@@ -147,6 +148,22 @@ const updateProfile = createResource({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const saveProfile = (close) => {
|
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'],
|
||||||
|
})
|
||||||
updateProfile.submit(
|
updateProfile.submit(
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,7 +5,24 @@
|
|||||||
</h2>
|
</h2>
|
||||||
<div
|
<div
|
||||||
v-if="profile.data.bio"
|
v-if="profile.data.bio"
|
||||||
v-html="profile.data.bio"
|
v-html="
|
||||||
|
DOMPurify.sanitize(decodeEntities(profile.data.bio), {
|
||||||
|
ALLOWED_TAGS: [
|
||||||
|
'b',
|
||||||
|
'i',
|
||||||
|
'em',
|
||||||
|
'strong',
|
||||||
|
'a',
|
||||||
|
'p',
|
||||||
|
'br',
|
||||||
|
'ul',
|
||||||
|
'ol',
|
||||||
|
'li',
|
||||||
|
'img',
|
||||||
|
],
|
||||||
|
ALLOWED_ATTR: ['href', 'target', 'rel', 'src'],
|
||||||
|
})
|
||||||
|
"
|
||||||
class="ProseMirror prose prose-table:table-fixed prose-td:p-2 prose-th:p-2 prose-td:border prose-th:border prose-td:border-outline-gray-2 prose-th:border-outline-gray-2 prose-td:relative prose-th:relative prose-th:bg-surface-gray-2 prose-sm max-w-none !whitespace-normal"
|
class="ProseMirror prose prose-table:table-fixed prose-td:p-2 prose-th:p-2 prose-td:border prose-th:border prose-td:border-outline-gray-2 prose-th:border-outline-gray-2 prose-td:relative prose-th:relative prose-th:bg-surface-gray-2 prose-sm max-w-none !whitespace-normal"
|
||||||
></div>
|
></div>
|
||||||
<div v-else class="text-ink-gray-7 text-sm italic">
|
<div v-else class="text-ink-gray-7 text-sm italic">
|
||||||
@@ -101,6 +118,8 @@ import { inject } from 'vue'
|
|||||||
import { createResource, Popover, Button } from 'frappe-ui'
|
import { createResource, Popover, Button } from 'frappe-ui'
|
||||||
import { X, LinkedinIcon, Twitter } from 'lucide-vue-next'
|
import { X, LinkedinIcon, Twitter } from 'lucide-vue-next'
|
||||||
import { sessionStore } from '@/stores/session'
|
import { sessionStore } from '@/stores/session'
|
||||||
|
import { decodeEntities } from '@/utils'
|
||||||
|
import DOMPurify from 'dompurify'
|
||||||
|
|
||||||
const dayjs = inject('$dayjs')
|
const dayjs = inject('$dayjs')
|
||||||
const { branding } = sessionStore()
|
const { branding } = sessionStore()
|
||||||
|
|||||||
@@ -119,7 +119,7 @@
|
|||||||
<FormControl
|
<FormControl
|
||||||
v-if="quizDetails.doc.enable_negative_marking"
|
v-if="quizDetails.doc.enable_negative_marking"
|
||||||
v-model="quizDetails.doc.marks_to_cut"
|
v-model="quizDetails.doc.marks_to_cut"
|
||||||
:label="__('Marks to Cut')"
|
:label="__('Marks to Deduct')"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -799,3 +799,9 @@ export const blockQuotesClick = () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const decodeEntities = (encodedString) => {
|
||||||
|
const textarea = document.createElement('textarea')
|
||||||
|
textarea.innerHTML = encodedString
|
||||||
|
return textarea.value
|
||||||
|
}
|
||||||
|
|||||||
@@ -1975,7 +1975,6 @@ def get_program_details(program_name):
|
|||||||
"member_count",
|
"member_count",
|
||||||
"course_count",
|
"course_count",
|
||||||
"published",
|
"published",
|
||||||
"allow_self_enrollment",
|
|
||||||
"enforce_course_order",
|
"enforce_course_order",
|
||||||
],
|
],
|
||||||
as_dict=1,
|
as_dict=1,
|
||||||
|
|||||||
Reference in New Issue
Block a user