给所有请求都加上jwt,隐藏生成jwt的secret(放到.env中),隐藏app-secret(放在pm2运行配置文件中,后续直接读取环境配置即可)
This commit is contained in:
@@ -0,0 +1,186 @@
|
||||
/**
|
||||
* 查找所有使用 postgrest 函数的文件
|
||||
* 使用方法: node scripts/find-postgrest-calls.js
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const postgrestFunctions = [
|
||||
'postgrestGet',
|
||||
'postgrestPost',
|
||||
'postgrestPut',
|
||||
'postgrestDelete'
|
||||
];
|
||||
|
||||
function findPostgrestCalls(dir, results = {}) {
|
||||
const files = fs.readdirSync(dir);
|
||||
|
||||
for (const file of files) {
|
||||
const filePath = path.join(dir, file);
|
||||
const stat = fs.statSync(filePath);
|
||||
|
||||
// 跳过 node_modules 和其他不相关目录
|
||||
if (stat.isDirectory()) {
|
||||
if (!file.startsWith('.') && file !== 'node_modules' && file !== 'build') {
|
||||
findPostgrestCalls(filePath, results);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// 只检查 .ts 和 .tsx 文件
|
||||
if (!file.endsWith('.ts') && !file.endsWith('.tsx')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const content = fs.readFileSync(filePath, 'utf-8');
|
||||
const lines = content.split('\n');
|
||||
|
||||
// 查找 postgrest 函数调用
|
||||
const calls = [];
|
||||
lines.forEach((line, index) => {
|
||||
postgrestFunctions.forEach(fn => {
|
||||
if (line.includes(`${fn}(`)) {
|
||||
calls.push({
|
||||
line: index + 1,
|
||||
code: line.trim(),
|
||||
function: fn
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (calls.length > 0) {
|
||||
const relativePath = path.relative(process.cwd(), filePath);
|
||||
results[relativePath] = calls;
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
// 执行查找
|
||||
console.log('🔍 正在查找所有 postgrest 调用...\n');
|
||||
const appDir = path.join(process.cwd(), 'app');
|
||||
const results = findPostgrestCalls(appDir);
|
||||
|
||||
// 分类显示结果
|
||||
const apiFiles = [];
|
||||
const routeFiles = [];
|
||||
const otherFiles = [];
|
||||
|
||||
Object.keys(results).forEach(file => {
|
||||
if (file.includes('app/api/')) {
|
||||
apiFiles.push(file);
|
||||
} else if (file.includes('app/routes/')) {
|
||||
routeFiles.push(file);
|
||||
} else {
|
||||
otherFiles.push(file);
|
||||
}
|
||||
});
|
||||
|
||||
// 显示统计
|
||||
console.log('📊 统计结果');
|
||||
console.log('=====================================');
|
||||
console.log(`API 文件: ${apiFiles.length} 个`);
|
||||
console.log(`路由文件: ${routeFiles.length} 个`);
|
||||
console.log(`其他文件: ${otherFiles.length} 个`);
|
||||
console.log(`总计: ${Object.keys(results).length} 个文件\n`);
|
||||
|
||||
// 显示 API 文件
|
||||
if (apiFiles.length > 0) {
|
||||
console.log('📁 API 文件');
|
||||
console.log('=====================================');
|
||||
apiFiles.forEach(file => {
|
||||
console.log(`\n${file}`);
|
||||
results[file].forEach(call => {
|
||||
console.log(` 行 ${call.line}: ${call.function}()`);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 显示路由文件
|
||||
if (routeFiles.length > 0) {
|
||||
console.log('\n\n📄 路由文件');
|
||||
console.log('=====================================');
|
||||
routeFiles.forEach(file => {
|
||||
console.log(`\n${file}`);
|
||||
results[file].forEach(call => {
|
||||
console.log(` 行 ${call.line}: ${call.function}()`);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 显示其他文件
|
||||
if (otherFiles.length > 0) {
|
||||
console.log('\n\n📦 其他文件');
|
||||
console.log('=====================================');
|
||||
otherFiles.forEach(file => {
|
||||
console.log(`\n${file}`);
|
||||
results[file].forEach(call => {
|
||||
console.log(` 行 ${call.line}: ${call.function}()`);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 生成 Markdown 清单
|
||||
const mdContent = `# PostgreSQL 调用清单
|
||||
|
||||
生成时间: ${new Date().toLocaleString('zh-CN')}
|
||||
|
||||
## 统计
|
||||
|
||||
- API 文件: ${apiFiles.length} 个
|
||||
- 路由文件: ${routeFiles.length} 个
|
||||
- 其他文件: ${otherFiles.length} 个
|
||||
- **总计: ${Object.keys(results).length} 个文件**
|
||||
|
||||
## API 文件
|
||||
|
||||
${apiFiles.map(file => `- [ ] \`${file}\` (${results[file].length} 处调用)`).join('\n')}
|
||||
|
||||
## 路由文件
|
||||
|
||||
${routeFiles.map(file => `- [ ] \`${file}\` (${results[file].length} 处调用)`).join('\n')}
|
||||
|
||||
${otherFiles.length > 0 ? `## 其他文件\n\n${otherFiles.map(file => `- [ ] \`${file}\` (${results[file].length} 处调用)`).join('\n')}` : ''}
|
||||
|
||||
## 修改建议
|
||||
|
||||
### 优先级 1:路由文件(高优先级)
|
||||
路由文件直接处理用户请求,应优先修改:
|
||||
|
||||
${routeFiles.slice(0, 5).map((file, i) => `${i + 1}. \`${file}\``).join('\n')}
|
||||
|
||||
### 优先级 2:API 文件(中优先级)
|
||||
API 文件被路由调用,可以创建带 JWT 的封装:
|
||||
|
||||
${apiFiles.slice(0, 5).map((file, i) => `${i + 1}. \`${file}\``).join('\n')}
|
||||
|
||||
### 修改模板
|
||||
|
||||
\`\`\`typescript
|
||||
// 在 loader/action 中
|
||||
import { getJwtFromRequest } from "~/api/jwt-helper.server";
|
||||
|
||||
export async function loader({ request }: LoaderFunctionArgs) {
|
||||
const jwt = await getJwtFromRequest(request);
|
||||
|
||||
// 方式 1: 直接传递
|
||||
const response = await postgrestGet('table_name', { token: jwt });
|
||||
|
||||
// 方式 2: 使用现有参数
|
||||
const response = await postgrestGet('table_name', {
|
||||
...otherParams,
|
||||
token: jwt
|
||||
});
|
||||
|
||||
return json(response);
|
||||
}
|
||||
\`\`\`
|
||||
`;
|
||||
|
||||
fs.writeFileSync('POSTGREST_CALLS_CHECKLIST.md', mdContent);
|
||||
console.log('\n\n✅ 已生成清单文件: POSTGREST_CALLS_CHECKLIST.md');
|
||||
console.log('\n💡 提示: 可以用这个文件追踪修改进度');
|
||||
|
||||
@@ -0,0 +1,186 @@
|
||||
/**
|
||||
* 查找所有使用 postgrest 函数的文件
|
||||
* 使用方法: node scripts/find-postgrest-calls.js
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const postgrestFunctions = [
|
||||
'postgrestGet',
|
||||
'postgrestPost',
|
||||
'postgrestPut',
|
||||
'postgrestDelete'
|
||||
];
|
||||
|
||||
function findPostgrestCalls(dir, results = {}) {
|
||||
const files = fs.readdirSync(dir);
|
||||
|
||||
for (const file of files) {
|
||||
const filePath = path.join(dir, file);
|
||||
const stat = fs.statSync(filePath);
|
||||
|
||||
// 跳过 node_modules 和其他不相关目录
|
||||
if (stat.isDirectory()) {
|
||||
if (!file.startsWith('.') && file !== 'node_modules' && file !== 'build') {
|
||||
findPostgrestCalls(filePath, results);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// 只检查 .ts 和 .tsx 文件
|
||||
if (!file.endsWith('.ts') && !file.endsWith('.tsx')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const content = fs.readFileSync(filePath, 'utf-8');
|
||||
const lines = content.split('\n');
|
||||
|
||||
// 查找 postgrest 函数调用
|
||||
const calls = [];
|
||||
lines.forEach((line, index) => {
|
||||
postgrestFunctions.forEach(fn => {
|
||||
if (line.includes(`${fn}(`)) {
|
||||
calls.push({
|
||||
line: index + 1,
|
||||
code: line.trim(),
|
||||
function: fn
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (calls.length > 0) {
|
||||
const relativePath = path.relative(process.cwd(), filePath);
|
||||
results[relativePath] = calls;
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
// 执行查找
|
||||
console.log('🔍 正在查找所有 postgrest 调用...\n');
|
||||
const appDir = path.join(process.cwd(), 'app');
|
||||
const results = findPostgrestCalls(appDir);
|
||||
|
||||
// 分类显示结果
|
||||
const apiFiles = [];
|
||||
const routeFiles = [];
|
||||
const otherFiles = [];
|
||||
|
||||
Object.keys(results).forEach(file => {
|
||||
if (file.includes('app/api/')) {
|
||||
apiFiles.push(file);
|
||||
} else if (file.includes('app/routes/')) {
|
||||
routeFiles.push(file);
|
||||
} else {
|
||||
otherFiles.push(file);
|
||||
}
|
||||
});
|
||||
|
||||
// 显示统计
|
||||
console.log('📊 统计结果');
|
||||
console.log('=====================================');
|
||||
console.log(`API 文件: ${apiFiles.length} 个`);
|
||||
console.log(`路由文件: ${routeFiles.length} 个`);
|
||||
console.log(`其他文件: ${otherFiles.length} 个`);
|
||||
console.log(`总计: ${Object.keys(results).length} 个文件\n`);
|
||||
|
||||
// 显示 API 文件
|
||||
if (apiFiles.length > 0) {
|
||||
console.log('📁 API 文件');
|
||||
console.log('=====================================');
|
||||
apiFiles.forEach(file => {
|
||||
console.log(`\n${file}`);
|
||||
results[file].forEach(call => {
|
||||
console.log(` 行 ${call.line}: ${call.function}()`);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 显示路由文件
|
||||
if (routeFiles.length > 0) {
|
||||
console.log('\n\n📄 路由文件');
|
||||
console.log('=====================================');
|
||||
routeFiles.forEach(file => {
|
||||
console.log(`\n${file}`);
|
||||
results[file].forEach(call => {
|
||||
console.log(` 行 ${call.line}: ${call.function}()`);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 显示其他文件
|
||||
if (otherFiles.length > 0) {
|
||||
console.log('\n\n📦 其他文件');
|
||||
console.log('=====================================');
|
||||
otherFiles.forEach(file => {
|
||||
console.log(`\n${file}`);
|
||||
results[file].forEach(call => {
|
||||
console.log(` 行 ${call.line}: ${call.function}()`);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 生成 Markdown 清单
|
||||
const mdContent = `# PostgreSQL 调用清单
|
||||
|
||||
生成时间: ${new Date().toLocaleString('zh-CN')}
|
||||
|
||||
## 统计
|
||||
|
||||
- API 文件: ${apiFiles.length} 个
|
||||
- 路由文件: ${routeFiles.length} 个
|
||||
- 其他文件: ${otherFiles.length} 个
|
||||
- **总计: ${Object.keys(results).length} 个文件**
|
||||
|
||||
## API 文件
|
||||
|
||||
${apiFiles.map(file => `- [ ] \`${file}\` (${results[file].length} 处调用)`).join('\n')}
|
||||
|
||||
## 路由文件
|
||||
|
||||
${routeFiles.map(file => `- [ ] \`${file}\` (${results[file].length} 处调用)`).join('\n')}
|
||||
|
||||
${otherFiles.length > 0 ? `## 其他文件\n\n${otherFiles.map(file => `- [ ] \`${file}\` (${results[file].length} 处调用)`).join('\n')}` : ''}
|
||||
|
||||
## 修改建议
|
||||
|
||||
### 优先级 1:路由文件(高优先级)
|
||||
路由文件直接处理用户请求,应优先修改:
|
||||
|
||||
${routeFiles.slice(0, 5).map((file, i) => `${i + 1}. \`${file}\``).join('\n')}
|
||||
|
||||
### 优先级 2:API 文件(中优先级)
|
||||
API 文件被路由调用,可以创建带 JWT 的封装:
|
||||
|
||||
${apiFiles.slice(0, 5).map((file, i) => `${i + 1}. \`${file}\``).join('\n')}
|
||||
|
||||
### 修改模板
|
||||
|
||||
\`\`\`typescript
|
||||
// 在 loader/action 中
|
||||
import { getJwtFromRequest } from "~/api/jwt-helper.server";
|
||||
|
||||
export async function loader({ request }: LoaderFunctionArgs) {
|
||||
const jwt = await getJwtFromRequest(request);
|
||||
|
||||
// 方式 1: 直接传递
|
||||
const response = await postgrestGet('table_name', { token: jwt });
|
||||
|
||||
// 方式 2: 使用现有参数
|
||||
const response = await postgrestGet('table_name', {
|
||||
...otherParams,
|
||||
token: jwt
|
||||
});
|
||||
|
||||
return json(response);
|
||||
}
|
||||
\`\`\`
|
||||
`;
|
||||
|
||||
fs.writeFileSync('POSTGREST_CALLS_CHECKLIST.md', mdContent);
|
||||
console.log('\n\n✅ 已生成清单文件: POSTGREST_CALLS_CHECKLIST.md');
|
||||
console.log('\n💡 提示: 可以用这个文件追踪修改进度');
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* JWT Secret 生成工具
|
||||
*
|
||||
* 用法:
|
||||
* node scripts/generate-jwt-secret.js
|
||||
*
|
||||
* 生成一个强随机的 JWT Secret,可以直接用于 .env 文件
|
||||
*/
|
||||
|
||||
const crypto = require('crypto');
|
||||
|
||||
// 生成 64 字节(128 个十六进制字符)的强随机密钥
|
||||
const secret = crypto.randomBytes(64).toString('hex');
|
||||
|
||||
console.log('\n==================== JWT Secret 生成成功 ====================\n');
|
||||
console.log('请将以下内容添加到你的 .env 文件中:\n');
|
||||
console.log(`JWT_SECRET=${secret}\n`);
|
||||
console.log('⚠️ 重要提醒:');
|
||||
console.log('1. 不要将此密钥提交到版本控制系统(Git)');
|
||||
console.log('2. 生产环境请使用密钥管理服务(如 AWS Secrets Manager)');
|
||||
console.log('3. 不同环境(开发/测试/生产)应使用不同的密钥');
|
||||
console.log('4. 建议每 3-6 个月轮换一次密钥');
|
||||
console.log('5. 密钥长度: 128 个字符(64 字节)\n');
|
||||
console.log('============================================================\n');
|
||||
Reference in New Issue
Block a user