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()