| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051 |
- #!/usr/bin/env node
- import { existsSync, readFileSync, readdirSync } from 'node:fs'
- import { dirname, join, resolve } from 'node:path'
- import { fileURLToPath } from 'node:url'
- const scriptDir = dirname(fileURLToPath(import.meta.url))
- const config = JSON.parse(readFileSync(resolve(scriptDir, 'community-db.config.json'), 'utf8'))
- const target = resolve(process.cwd(), process.argv[2] || resolve(scriptDir, config.exportDir))
- if (!existsSync(target)) {
- console.log(JSON.stringify({ target, checkedFiles: 0, findings: [] }, null, 2))
- process.exit(0)
- }
- const files = listSqlFiles(target)
- const sensitiveWords = config.sensitiveColumns.map(word => new RegExp(`\\b${escapeRegExp(word)}\\b`, 'i'))
- const sensitivePatterns = config.sensitivePatterns.map(pattern => new RegExp(pattern, 'i'))
- const findings = []
- for (const file of files) {
- const content = readFileSync(file, 'utf8')
- const lines = content.split('\n')
- lines.forEach((line, index) => {
- const matchedWord = sensitiveWords.find(pattern => pattern.test(line))
- const matchedPattern = sensitivePatterns.find(pattern => pattern.test(line))
- if (matchedWord || matchedPattern) {
- findings.push({ file, line: index + 1, text: line.trim().slice(0, 160) })
- }
- })
- }
- const summary = { target, checkedFiles: files.length, findings }
- console.log(JSON.stringify(summary, null, 2))
- if (findings.length > 0) {
- process.exit(1)
- }
- function listSqlFiles(root) {
- return readdirSync(root, { withFileTypes: true }).flatMap((entry) => {
- const absolutePath = join(root, entry.name)
- if (entry.isDirectory()) {
- return listSqlFiles(absolutePath)
- }
- return entry.name.endsWith('.sql') ? [absolutePath] : []
- })
- }
- function escapeRegExp(value) {
- return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
- }
|