From 79e8b8869aa8358c42ad74c9b3004d7b4cde4e50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E4=B8=80=E4=B9=8B?= Date: Fri, 25 Apr 2025 15:41:02 +0800 Subject: [PATCH] =?UTF-8?q?=E8=84=9A=E6=9C=AC=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/service/service_worker/client.ts | 27 +++++ .../service_worker/permission_verify.ts | 45 +++++++-- src/app/service/service_worker/resource.ts | 10 +- src/app/service/service_worker/runtime.ts | 12 +-- src/app/service/service_worker/script.ts | 50 ++++++++++ src/app/service/service_worker/value.ts | 1 - src/pages/components/ScriptSetting/Match.tsx | 98 ++++++++----------- .../components/ScriptSetting/Permission.tsx | 70 +++++-------- 8 files changed, 192 insertions(+), 121 deletions(-) diff --git a/src/app/service/service_worker/client.ts b/src/app/service/service_worker/client.ts index 9ac90fd..acec47f 100644 --- a/src/app/service/service_worker/client.ts +++ b/src/app/service/service_worker/client.ts @@ -10,6 +10,7 @@ import { v4 as uuidv4 } from "uuid"; import Cache from "@App/app/cache"; import CacheKey from "@App/app/cache_key"; import { Subscribe } from "@App/app/repo/subscribe"; +import { Permission } from "@App/app/repo/permission"; export class ServiceWorkerClient extends Client { constructor(msg: MessageSend) { @@ -59,6 +60,16 @@ export class ScriptClient extends Client { return this.do("excludeUrl", { uuid, url, remove }); } + // 重置匹配项 + resetMatch(uuid: string, match: string[] | undefined) { + return this.do("resetMatch", { uuid, match }); + } + + // 重置排除项 + resetExclude(uuid: string, exclude: string[] | undefined) { + return this.do("resetExclude", { uuid, exclude }); + } + requestCheckUpdate(uuid: string) { return this.do("requestCheckUpdate", uuid); } @@ -158,6 +169,22 @@ export class PermissionClient extends Client { getPermissionInfo(uuid: string): ReturnType { return this.do("getInfo", uuid); } + + deletePermission(uuid: string, permission: string, permissionValue: string) { + return this.do("deletePermission", { uuid, permission, permissionValue }); + } + + getScriptPermissions(uuid: string): ReturnType { + return this.do("getScriptPermissions", uuid); + } + + addPermission(permission: Permission) { + return this.do("addPermission", permission); + } + + resetPermission(uuid: string) { + return this.do("resetPermission", uuid); + } } export class SynchronizeClient extends Client { diff --git a/src/app/service/service_worker/permission_verify.ts b/src/app/service/service_worker/permission_verify.ts index 1898624..130ec65 100644 --- a/src/app/service/service_worker/permission_verify.ts +++ b/src/app/service/service_worker/permission_verify.ts @@ -96,15 +96,6 @@ export default class PermissionVerify { reject: (reason: any) => void; }> = new Queue(); - async removePermissionCache(uuid: string) { - // 先删除缓存 - (await Cache.getInstance().list()).forEach((key) => { - if (key.startsWith(`permission:${uuid}:`)) { - Cache.getInstance().del(key); - } - }); - } - private permissionDAO: PermissionDAO = new PermissionDAO(); constructor(private group: Group) {} @@ -310,9 +301,45 @@ export default class PermissionVerify { return Promise.resolve({ script, confirm, likeNum }); } + async deletePermission(data: { uuid: string; permission: string; permissionValue: string }) { + const oldConfirm = await this.permissionDAO.findByKey(data.uuid, data.permission, data.permissionValue); + if (!oldConfirm) { + throw new Error("permission not found"); + } else { + await this.permissionDAO.delete(this.permissionDAO.key(oldConfirm)); + // 删除缓存 + Cache.getInstance().del(CacheKey.permissionConfirm(data.uuid, oldConfirm)); + } + } + + getScriptPermissions(uuid: string) { + // 获取脚本的所有权限 + return this.permissionDAO.find((key, item) => item.uuid === uuid); + } + + // 添加权限 + async addPermission(permission: Permission) { + await this.permissionDAO.save(permission); + Cache.getInstance().del(CacheKey.permissionConfirm(permission.uuid, permission)); + } + + // 重置权限 + async resetPermission(uuid: string) { + // 删除所有权限 + const permissions = await this.permissionDAO.find((key, item) => item.uuid === uuid); + permissions.forEach((item) => { + this.permissionDAO.delete(this.permissionDAO.key(item)); + Cache.getInstance().del(CacheKey.permissionConfirm(uuid, item)); + }); + } + init() { this.dealConfirmQueue(); this.group.on("confirm", this.userConfirm.bind(this)); this.group.on("getInfo", this.getInfo.bind(this)); + this.group.on("deletePermission", this.deletePermission.bind(this)); + this.group.on("getScriptPermissions", this.getScriptPermissions.bind(this)); + this.group.on("addPermission", this.getInfo.bind(this)); + this.group.on("resetPermission", this.resetPermission.bind(this)); } } diff --git a/src/app/service/service_worker/resource.ts b/src/app/service/service_worker/resource.ts index 9909120..44d1dec 100644 --- a/src/app/service/service_worker/resource.ts +++ b/src/app/service/service_worker/resource.ts @@ -305,7 +305,15 @@ export class ResourceService { return { url: urls[0], hash }; } - deleteResource(url: string) { + async deleteResource(url: string) { + // 删除缓存 + const res = await this.resourceDAO.get(url); + if (!res) { + throw new Error("resource not found"); + } + Object.keys(res.link).forEach((key) => { + this.cache.delete(key); + }); return this.resourceDAO.delete(url); } diff --git a/src/app/service/service_worker/runtime.ts b/src/app/service/service_worker/runtime.ts index 23d09ef..e0723ea 100644 --- a/src/app/service/service_worker/runtime.ts +++ b/src/app/service/service_worker/runtime.ts @@ -384,15 +384,15 @@ export class RuntimeService { // 加载页面脚本, 会把脚本信息放入缓存中 // 如果脚本开启, 则注册脚本 async loadPageScript(script: Script) { - const matches = script.metadata["match"]; + const scriptRes = await this.script.buildScriptRunResource(script); + const matches = scriptRes.metadata["match"]; if (!matches) { return; } - const scriptRes = await this.script.buildScriptRunResource(script); scriptRes.code = compileInjectScript(scriptRes); - matches.push(...(script.metadata["include"] || [])); + matches.push(...(scriptRes.metadata["include"] || [])); const patternMatches = dealPatternMatches(matches); const scriptMatchInfo: ScriptMatchInfo = Object.assign( { matches: patternMatches.result, excludeMatches: [], customizeExcludeMatches: [] }, @@ -435,11 +435,11 @@ export class RuntimeService { // 如果脚本开启, 则注册脚本 if (script.status === SCRIPT_STATUS_ENABLE) { - if (!script.metadata["noframes"]) { + if (!scriptRes.metadata["noframes"]) { registerScript.allFrames = true; } - if (script.metadata["run-at"]) { - registerScript.runAt = getRunAt(script.metadata["run-at"]); + if (scriptRes.metadata["run-at"]) { + registerScript.runAt = getRunAt(scriptRes.metadata["run-at"]); } if (await Cache.getInstance().get("registryScript:" + script.uuid)) { await chrome.userScripts.update([registerScript]); diff --git a/src/app/service/service_worker/script.ts b/src/app/service/service_worker/script.ts index e31d474..3f75390 100644 --- a/src/app/service/service_worker/script.ts +++ b/src/app/service/service_worker/script.ts @@ -320,6 +320,54 @@ export class ScriptService { }); } + async resetExclude({ uuid, exclude }: { uuid: string; exclude: string[] | undefined }) { + const script = await this.scriptDAO.get(uuid); + if (!script) { + throw new Error("script not found"); + } + script.selfMetadata = script.selfMetadata || {}; + if (exclude) { + script.selfMetadata.exclude = exclude; + } else { + delete script.selfMetadata.exclude; + } + return this.scriptDAO + .update(uuid, script) + .then(() => { + // 广播一下 + this.mq.publish("installScript", { script, update: true }); + return true; + }) + .catch((e) => { + this.logger.error("reset exclude error", Logger.E(e)); + throw e; + }); + } + + async resetMatch({ uuid, match }: { uuid: string; match: string[] | undefined }) { + const script = await this.scriptDAO.get(uuid); + if (!script) { + throw new Error("script not found"); + } + script.selfMetadata = script.selfMetadata || {}; + if (match) { + script.selfMetadata.match = match; + } else { + delete script.selfMetadata.match; + } + return this.scriptDAO + .update(uuid, script) + .then(() => { + // 广播一下 + this.mq.publish("installScript", { script, update: true }); + return true; + }) + .catch((e) => { + this.logger.error("reset match error", Logger.E(e)); + throw e; + }); + } + async checkUpdate(uuid: string, source: "user" | "system") { // 检查更新 const script = await this.scriptDAO.get(uuid); @@ -443,6 +491,8 @@ export class ScriptService { this.group.on("getCode", this.getCode.bind(this)); this.group.on("getScriptRunResource", this.buildScriptRunResource.bind(this)); this.group.on("excludeUrl", this.excludeUrl.bind(this)); + this.group.on("resetMatch", this.resetMatch.bind(this)); + this.group.on("resetExclude", this.resetExclude.bind(this)); this.group.on("requestCheckUpdate", this.requestCheckUpdate.bind(this)); // 定时检查更新, 每10分钟检查一次 diff --git a/src/app/service/service_worker/value.ts b/src/app/service/service_worker/value.ts index a4e8aac..313b065 100644 --- a/src/app/service/service_worker/value.ts +++ b/src/app/service/service_worker/value.ts @@ -42,7 +42,6 @@ export class ValueService { const storageName = getStorageName(script); let oldValue; // 使用事务来保证数据一致性 - console.log("setValue", key, value); await Cache.getInstance().tx("setValue:" + storageName, async () => { const valueModel = await this.valueDAO.get(storageName); if (!valueModel) { diff --git a/src/pages/components/ScriptSetting/Match.tsx b/src/pages/components/ScriptSetting/Match.tsx index ad4d1c9..bd0fdd0 100644 --- a/src/pages/components/ScriptSetting/Match.tsx +++ b/src/pages/components/ScriptSetting/Match.tsx @@ -4,14 +4,15 @@ import { Script, ScriptDAO } from "@App/app/repo/scripts"; import { Space, Popconfirm, Button, Divider, Typography, Modal, Input } from "@arco-design/web-react"; import Table, { ColumnProps } from "@arco-design/web-react/es/Table"; import { IconDelete } from "@arco-design/web-react/icon"; +import { scriptClient } from "@App/pages/store/features/script"; type MatchItem = { // id是为了避免match重复 id: number; match: string; - self: boolean; - hasMatch: boolean; - isExclude: boolean; + byUser: boolean; + hasMatch: boolean; // 是否已经匹配 + isExclude: boolean; // 是否是排除项 }; const Match: React.FC<{ @@ -40,23 +41,13 @@ const Match: React.FC<{ }); const v: MatchItem[] = []; matchArr.forEach((value, index) => { - if (matchMap.has(value)) { - v.push({ - id: index, - match: value, - self: false, - hasMatch: false, - isExclude: false, - }); - } else { - v.push({ - id: index, - match: value, - self: true, - hasMatch: false, - isExclude: false, - }); - } + v.push({ + id: index, + match: value, + byUser: !matchMap.has(value), + hasMatch: false, + isExclude: false, + }); }); setMatch(v); @@ -68,23 +59,13 @@ const Match: React.FC<{ const e: MatchItem[] = []; excludeArr.forEach((value, index) => { const hasMatch = matchMap.has(value); - if (excludeMap.has(value)) { - e.push({ - id: index, - match: value, - self: false, - hasMatch, - isExclude: true, - }); - } else { - e.push({ - id: index, - match: value, - self: true, - hasMatch, - isExclude: true, - }); - } + e.push({ + id: index, + match: value, + byUser: !excludeMap.has(value), + hasMatch, + isExclude: true, + }); }); setExclude(e); }); @@ -99,8 +80,8 @@ const Match: React.FC<{ }, { title: t("user_setting"), - dataIndex: "self", - key: "self", + dataIndex: "byUser", + key: "byUser", width: 100, render(col) { if (col) { @@ -119,18 +100,21 @@ const Match: React.FC<{ title={`${t("confirm_delete_exclude")}${item.hasMatch ? ` ${t("after_deleting_match_item")}` : ""}`} onOk={() => { exclude.splice(exclude.indexOf(item), 1); - scriptCtrl + // 删除所有排除 + scriptClient .resetExclude( - script.id, + script.uuid, exclude.map((m) => m.match) ) .then(() => { setExclude([...exclude]); + // 如果包含在里面,再加回match if (item.hasMatch) { match.push(item); - scriptCtrl + // 重置匹配 + scriptClient .resetMatch( - script.id, + script.uuid, match.map((m) => m.match) ) .then(() => { @@ -148,22 +132,22 @@ const Match: React.FC<{ return ( { match.splice(match.indexOf(item), 1); - scriptCtrl + scriptClient .resetMatch( - script.id, + script.uuid, match.map((m) => m.match) ) .then(() => { setMatch([...match]); // 添加到exclue - if (!item.self) { + if (!item.byUser) { exclude.push(item); - scriptCtrl + scriptClient .resetExclude( - script.id, + script.uuid, exclude.map((m) => m.match) ) .then(() => { @@ -192,13 +176,13 @@ const Match: React.FC<{ match.push({ id: Math.random(), match: matchValue, - self: true, + byUser: true, hasMatch: false, isExclude: false, }); - scriptCtrl + scriptClient .resetMatch( - script.id, + script.uuid, match.map((m) => m.match) ) .then(() => { @@ -224,13 +208,13 @@ const Match: React.FC<{ exclude.push({ id: Math.random(), match: excludeValue, - self: true, + byUser: true, hasMatch: false, isExclude: true, }); - scriptCtrl + scriptClient .resetExclude( - script.id, + script.uuid, exclude.map((m) => m.match) ) .then(() => { @@ -263,7 +247,7 @@ const Match: React.FC<{ { - scriptCtrl.resetMatch(script.id, undefined).then(() => { + scriptClient.resetMatch(script.uuid, undefined).then(() => { setMatch([]); }); }} @@ -292,7 +276,7 @@ const Match: React.FC<{ { - scriptCtrl.resetExclude(script.id, undefined).then(() => { + scriptClient.resetExclude(script.uuid, undefined).then(() => { setExclude([]); }); }} diff --git a/src/pages/components/ScriptSetting/Permission.tsx b/src/pages/components/ScriptSetting/Permission.tsx index 01cbcfd..16418fe 100644 --- a/src/pages/components/ScriptSetting/Permission.tsx +++ b/src/pages/components/ScriptSetting/Permission.tsx @@ -2,19 +2,10 @@ import React, { useEffect, useState } from "react"; import { Permission } from "@App/app/repo/permission"; import { Script } from "@App/app/repo/scripts"; import { useTranslation } from "react-i18next"; -import { - Space, - Popconfirm, - Message, - Button, - Checkbox, - Input, - Modal, - Select, - Typography, -} from "@arco-design/web-react"; +import { Space, Popconfirm, Message, Button, Checkbox, Input, Modal, Select, Typography } from "@arco-design/web-react"; import Table, { ColumnProps } from "@arco-design/web-react/es/Table"; import { IconDelete } from "@arco-design/web-react/icon"; +import { permissionClient } from "@App/pages/store/features/script"; const PermissionManager: React.FC<{ script: Script; @@ -56,14 +47,15 @@ const PermissionManager: React.FC<{ { - permissionCtrl - .deletePermission(script!.id, { - permission: item.permission, - permissionValue: item.permissionValue, - }) + permissionClient + .deletePermission(script.uuid, item.permission, item.permissionValue) .then(() => { Message.success(t("delete_success")!); - setPermission(permission.filter((i) => i.id !== item.id)); + setPermission( + permission.filter( + (i) => !(i.permission == item.permission && i.permissionValue == item.permissionValue) + ) + ); }) .catch(() => { Message.error(t("delete_failed")!); @@ -80,7 +72,7 @@ const PermissionManager: React.FC<{ useEffect(() => { if (script) { - permissionCtrl.getPermissions(script.id).then((list) => { + permissionClient.getScriptPermissions(script.uuid).then((list) => { setPermission(list); }); } @@ -95,20 +87,17 @@ const PermissionManager: React.FC<{ onOk={() => { if (permissionValue) { permission.push({ - id: 0, - uuid: script.id, + uuid: script.uuid, permission: permissionValue.permission, permissionValue: permissionValue.permissionValue, allow: permissionValue.allow, createtime: new Date().getTime(), updatetime: 0, }); - permissionCtrl - .addPermission(script.id, permissionValue) - .then(() => { - setPermission([...permission]); - setPermissionVisible(false); - }); + permissionClient.addPermission(permissionValue).then(() => { + setPermission([...permission]); + setPermissionVisible(false); + }); } }} > @@ -116,27 +105,22 @@ const PermissionManager: React.FC<{ { - permissionValue && - setPermissionValue({ ...permissionValue, permissionValue: e }); + permissionValue && setPermissionValue({ ...permissionValue, permissionValue: e }); }} /> { - permissionValue && - setPermissionValue({ ...permissionValue, allow: e }); + permissionValue && setPermissionValue({ ...permissionValue, allow: e }); }} > {t("allow")} @@ -144,17 +128,14 @@ const PermissionManager: React.FC<{
- - {t("permission_management")} - + {t("permission_management")}
- +
); };