permissions.service.ts•2.8 kB
import { Injectable } from '@nestjs/common';
import * as fs from 'fs';
import * as path from 'path';
interface PermissionConfig {
permissions: {
allowedTables: string[];
readOnlyTables: string[];
allowedOperations: Record<string, string[]>;
forbiddenOperations: string[];
maxQueryLimit: number;
};
audit: {
enabled: boolean;
logPath: string;
trackChanges: boolean;
};
}
@Injectable()
export class PermissionsService {
private config: PermissionConfig;
constructor() {
this.loadConfig();
}
private loadConfig() {
const configPath = path.join(process.cwd(), 'database-permissions.json');
try {
const configData = fs.readFileSync(configPath, 'utf8');
this.config = JSON.parse(configData);
} catch (error) {
console.error('Failed to load permissions config, using defaults');
this.config = {
permissions: {
allowedTables: ['users'],
readOnlyTables: [],
allowedOperations: {
users: ['SELECT', 'INSERT', 'UPDATE', 'DELETE'],
},
forbiddenOperations: ['DROP TABLE', 'DROP DATABASE', 'TRUNCATE', 'ALTER TABLE'],
maxQueryLimit: 1000,
},
audit: {
enabled: true,
logPath: './logs/audit.log',
trackChanges: true,
},
};
}
}
canAccessTable(tableName: string): boolean {
const allTables = [
...this.config.permissions.allowedTables,
...this.config.permissions.readOnlyTables,
];
return allTables.includes(tableName);
}
isReadOnlyTable(tableName: string): boolean {
return this.config.permissions.readOnlyTables.includes(tableName);
}
canPerformOperation(tableName: string, operation: string): boolean {
if (!this.canAccessTable(tableName)) {
return false;
}
const allowedOps = this.config.permissions.allowedOperations[tableName] || [];
return allowedOps.includes(operation);
}
validateSql(sql: string): { valid: boolean; error?: string } {
const upperSql = sql.toUpperCase();
// 检查禁止的操作
for (const forbidden of this.config.permissions.forbiddenOperations) {
if (upperSql.includes(forbidden.toUpperCase())) {
return {
valid: false,
error: `禁止的操作: ${forbidden}`,
};
}
}
return { valid: true };
}
getAllowedTables(): string[] {
return this.config.permissions.allowedTables;
}
getReadOnlyTables(): string[] {
return this.config.permissions.readOnlyTables;
}
getMaxQueryLimit(): number {
return this.config.permissions.maxQueryLimit;
}
isAuditEnabled(): boolean {
return this.config.audit.enabled;
}
shouldTrackChanges(): boolean {
return this.config.audit.trackChanges;
}
}