fix(hooks): 🐛 修复一些xss的问题
This commit is contained in:
4
.github/workflows/greetings.yml
vendored
4
.github/workflows/greetings.yml
vendored
@@ -2,6 +2,10 @@ name: Greetings
|
||||
|
||||
on: [pull_request_target, issues]
|
||||
|
||||
# 顶层设置最小权限,推荐 contents: read
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
greeting:
|
||||
# 跳过 Renovate PR
|
||||
|
||||
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
@@ -5,6 +5,10 @@ on:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
# 确保默认情况下所有 job 都只有只读权限,只有需要写权限的 job(比如发布 release 的 job)才会单独提升权限,其他 job 依然保持最小权限,最大程度保护仓库安全
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: release-${{ github.ref }}
|
||||
cancel-in-progress: true # 如果有新的发布任务,取消正在进行的任务
|
||||
|
||||
@@ -213,13 +213,17 @@ const addFriend = async () => {
|
||||
globalStore.addFriendModalInfo.uid = uid
|
||||
}
|
||||
|
||||
// 注入 enableAllScroll 方法
|
||||
const { enableScroll } = inject('popoverControls', { enableScroll: () => {} })
|
||||
let enableScroll = () => {}
|
||||
|
||||
const handleOpenMsgSession = async (uid: string) => {
|
||||
enableScroll() // 在打开新会话前恢复所有滚动
|
||||
await openMsgSession(uid)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// 注入 enableAllScroll 方法
|
||||
enableScroll.bind(inject('popoverControls', { enableScroll }))
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -171,7 +171,7 @@ const { themes } = storeToRefs(settingStore)
|
||||
const arrow = ref(false)
|
||||
/** 输入框dom元素 */
|
||||
const messageInputDom = ref<HTMLElement>()
|
||||
const activeItem = ref(inject('activeItem') as SessionItem)
|
||||
const activeItem = ref()
|
||||
/** ait 虚拟列表 */
|
||||
const virtualListInstAit = useTemplateRef<VirtualListInst>('virtualListInst-ait')
|
||||
/** AI 虚拟列表 */
|
||||
@@ -257,6 +257,7 @@ const closeMenu = (event: any) => {
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
activeItem.value = inject('activeItem') as SessionItem
|
||||
onKeyStroke('Enter', () => {
|
||||
if (ait.value && Number(selectedAIKey.value) > -1) {
|
||||
const item = personList.value.find((item) => item.uid === selectedAitKey.value) as CacheUserItem
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
<n-flex
|
||||
align="center"
|
||||
justify="center"
|
||||
class="emoji-item"
|
||||
class="emoji-item py-4px"
|
||||
v-for="(item, index) in emojiStore.emojiList"
|
||||
:key="index"
|
||||
@click.stop="chooseEmoji(item.expressionUrl, 'url')">
|
||||
|
||||
@@ -96,6 +96,16 @@ export const useCommon = () => {
|
||||
imgCount: 0
|
||||
})
|
||||
|
||||
/**
|
||||
* 判断 URL 是否安全
|
||||
* @param url URL 字符串
|
||||
* @returns 是否安全
|
||||
*/
|
||||
const isSafeUrl = (url: string) => {
|
||||
// 只允许 http/https 协议,且不能包含 javascript: 或 data:
|
||||
return /^(https?:\/\/|\/)/.test(url) && !/^javascript:/i.test(url) && !/^data:/i.test(url)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前光标选取的信息(需要判断是否为空)
|
||||
*/
|
||||
@@ -308,7 +318,12 @@ export const useCommon = () => {
|
||||
const author = dom.name
|
||||
// 创建一个img标签节点作为头像
|
||||
const imgNode = document.createElement('img')
|
||||
imgNode.src = dom.avatar
|
||||
if (isSafeUrl(dom.avatar)) {
|
||||
imgNode.src = dom.avatar
|
||||
} else {
|
||||
// 设置为默认头像或空
|
||||
imgNode.src = 'avatar/001.png'
|
||||
}
|
||||
imgNode.style.cssText = `
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
@@ -424,7 +439,13 @@ export const useCommon = () => {
|
||||
let content = dom.content
|
||||
// 创建一个img标签节点作为头像
|
||||
const imgNode = document.createElement('img')
|
||||
imgNode.src = AvatarUtils.getAvatarUrl(dom.avatar)
|
||||
const avatarUrl = AvatarUtils.getAvatarUrl(dom.avatar)
|
||||
if (isSafeUrl(avatarUrl)) {
|
||||
imgNode.src = avatarUrl
|
||||
} else {
|
||||
// 设置为默认头像或空
|
||||
imgNode.src = 'avatar/001.png'
|
||||
}
|
||||
imgNode.style.cssText = `
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
@@ -461,7 +482,6 @@ export const useCommon = () => {
|
||||
content = content.find((item: string) => item.startsWith('data:image/'))
|
||||
reply.value.imgCount = imageCount
|
||||
}
|
||||
console.log(content)
|
||||
|
||||
// todo: 暂时用http开头的图片判断,后续需要优化
|
||||
if (content.startsWith('http')) {
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<!-- 主体内容区域 -->
|
||||
<div ref="contentRef" class="flex-1 overflow-auto">
|
||||
<!-- 图片展示区域 -->
|
||||
<div class="min-h-[calc(100vh-124px)] flex-center">
|
||||
<div ref="imgContainerRef" class="min-h-[calc(100vh-124px)] flex-center">
|
||||
<img
|
||||
ref="imageRef"
|
||||
:src="currentImage"
|
||||
@@ -18,8 +18,9 @@
|
||||
cursor: isDragging ? 'grabbing' : 'grab'
|
||||
}"
|
||||
class="max-w-90% max-h-90% select-none"
|
||||
:class="[{ 'transition-transform duration-200': !isDragging }, { 'mt-62px': !isScrollbar }]"
|
||||
:class="[{ 'transition-transform duration-200': !isDragging }]"
|
||||
@mousedown="startDrag"
|
||||
@load="checkScrollbar"
|
||||
alt="preview" />
|
||||
|
||||
<!-- 提示文本 -->
|
||||
@@ -132,7 +133,8 @@ const imagePosition = reactive({ x: 0, y: 0 })
|
||||
const imageRef = ref<HTMLImageElement>()
|
||||
// 添加响应式变量来跟踪是否有滚动条
|
||||
const contentScrollbar = useTemplateRef<HTMLElement>('contentRef')
|
||||
const isScrollbar = ref(false)
|
||||
// 图片容器
|
||||
const imgContainer = useTemplateRef<HTMLElement>('imgContainerRef')
|
||||
//提示相关的响应式变量
|
||||
const showTip = ref(false)
|
||||
const tipText = ref('')
|
||||
@@ -360,8 +362,9 @@ const handleKeydown = (e: KeyboardEvent) => {
|
||||
// 检查是否有滚动条的函数
|
||||
const checkScrollbar = () => {
|
||||
setTimeout(() => {
|
||||
if (contentScrollbar.value) {
|
||||
isScrollbar.value = contentScrollbar.value.scrollHeight > contentScrollbar.value.clientHeight
|
||||
if (imgContainer.value && contentScrollbar.value) {
|
||||
imgContainer.value.style.height =
|
||||
contentScrollbar.value.scrollHeight > contentScrollbar.value.clientHeight ? 'auto' : '100%'
|
||||
}
|
||||
}, 16)
|
||||
}
|
||||
@@ -369,9 +372,6 @@ const checkScrollbar = () => {
|
||||
onMounted(async () => {
|
||||
// 显示窗口
|
||||
await getCurrentWebviewWindow().show()
|
||||
setTimeout(() => {
|
||||
checkScrollbar()
|
||||
}, 16)
|
||||
|
||||
await addListener(
|
||||
appWindow.listen('update-image', (event: any) => {
|
||||
|
||||
Reference in New Issue
Block a user