From 43aab58c9ecb1203770ba382efbdbae299ca87ec Mon Sep 17 00:00:00 2001
From: liu <2021943741@qq.com>
Date: 星期一, 26 十月 2026 15:12:31 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev_business' into dev_business

---
 scripts/clear_unit_permission_cache.py |   61 ++++++++++++++++++++++++++++++
 1 files changed, 61 insertions(+), 0 deletions(-)

diff --git a/scripts/clear_unit_permission_cache.py b/scripts/clear_unit_permission_cache.py
new file mode 100644
index 0000000..34b1571
--- /dev/null
+++ b/scripts/clear_unit_permission_cache.py
@@ -0,0 +1,61 @@
+import socket
+import re
+import json
+import sys
+from pathlib import Path
+
+source = Path('yudao-server/src/main/resources/application-local.yaml').read_text(encoding='utf-8')
+block = re.search(r'(?m)^    redis:\s*\n((?:      [^\n]*\n)+)', source).group(1)
+redis = {key: value.split(' #')[0].strip().strip('\"\'') for key, value in re.findall(r'(?m)^      (host|port|database|password):\s*([^\n]*)', block)}
+connection = socket.create_connection((redis['host'], int(redis.get('port', 6379))), timeout=10)
+stream = connection.makefile('rb')
+
+def read():
+    kind = stream.read(1)
+    value = stream.readline().rstrip(b'\r\n')
+    if kind == b'-':
+        raise RuntimeError(value.decode())
+    if kind == b':':
+        return int(value)
+    if kind == b'$':
+        size = int(value)
+        if size < 0:
+            return None
+        result = stream.read(size)
+        stream.read(2)
+        return result
+    if kind == b'*':
+        return [read() for _ in range(int(value))]
+    return value
+
+def command(*parts):
+    values = [str(p).encode() if not isinstance(p, bytes) else p for p in parts]
+    connection.sendall(b'*' + str(len(values)).encode() + b'\r\n' + b''.join(b'$' + str(len(v)).encode() + b'\r\n' + v + b'\r\n' for v in values))
+    return read()
+
+if redis.get('password'):
+    command('AUTH', redis['password'])
+command('SELECT', redis.get('database', 0))
+plan = json.loads(Path('scripts/permission-fix-plan.json').read_text(encoding='utf-8'))
+suffixes = tuple(':' + key for key in set(plan['allKeys'] + [pair[0] for pair in plan['aliases']]))
+keys = []
+cursor = b'0'
+while True:
+    cursor, batch = command('SCAN', cursor, 'MATCH', '*permission_menu_ids*', 'COUNT', 100)
+    keys.extend(key for key in batch if key.decode().endswith(suffixes))
+    if cursor == b'0':
+        break
+menu_suffixes = tuple(':' + str(int(value)) for value in sys.argv[1:])
+if menu_suffixes:
+    cursor = b'0'
+    while True:
+        cursor, batch = command('SCAN', cursor, 'MATCH', '*menu_role_ids*', 'COUNT', 100)
+        keys.extend(key for key in batch if key.decode().endswith(menu_suffixes))
+        if cursor == b'0':
+            break
+print('Target permission cache keys:', [key.decode() for key in keys])
+if keys:
+    print('Deleted permission cache entries:', command('DEL', *keys))
+else:
+    print('No stale affected permission cache entries')
+connection.close()

--
Gitblit v1.9.3