83 lines
2.0 KiB
TypeScript
83 lines
2.0 KiB
TypeScript
import sqlite3 from 'sqlite3'
|
|
import path from 'path'
|
|
import crypto from 'crypto'
|
|
|
|
export interface ApiKey {
|
|
id: number
|
|
key_hash: string
|
|
name: string
|
|
permissions: string[]
|
|
rate_limit: number
|
|
is_active: boolean
|
|
last_used?: string
|
|
created_at: string
|
|
}
|
|
|
|
export function generateApiKey(): string {
|
|
return 'ak_' + crypto.randomBytes(32).toString('hex')
|
|
}
|
|
|
|
export function hashApiKey(key: string): string {
|
|
return crypto.createHash('sha256').update(key).digest('hex')
|
|
}
|
|
|
|
export async function validateApiKey(key: string): Promise<ApiKey | null> {
|
|
if (!key || !key.startsWith('ak_')) return null
|
|
|
|
const keyHash = hashApiKey(key)
|
|
const dbPath = path.join(process.cwd(), 'database', 'antihoax.db')
|
|
const db = new sqlite3.Database(dbPath)
|
|
|
|
try {
|
|
const apiKey = await new Promise<ApiKey | null>((resolve, reject) => {
|
|
db.get(
|
|
'SELECT * FROM api_keys WHERE key_hash = ? AND is_active = 1',
|
|
[keyHash],
|
|
(err, row: any) => {
|
|
if (err) reject(err)
|
|
else if (row) {
|
|
resolve({
|
|
...row,
|
|
permissions: row.permissions ? JSON.parse(row.permissions) : []
|
|
})
|
|
} else {
|
|
resolve(null)
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
if (apiKey) {
|
|
// Update last_used timestamp
|
|
await new Promise<void>((resolve, reject) => {
|
|
db.run(
|
|
'UPDATE api_keys SET last_used = datetime("now") WHERE id = ?',
|
|
[apiKey.id],
|
|
(err) => {
|
|
if (err) reject(err)
|
|
else resolve()
|
|
}
|
|
)
|
|
})
|
|
}
|
|
|
|
return apiKey
|
|
} catch (error) {
|
|
console.error('API key validation error:', error)
|
|
return null
|
|
} finally {
|
|
db.close()
|
|
}
|
|
}
|
|
|
|
export function hasPermission(apiKey: ApiKey, permission: string): boolean {
|
|
return apiKey.permissions.includes('*') || apiKey.permissions.includes(permission)
|
|
}
|
|
|
|
export const ApiPermissions = {
|
|
READ_SOURCES: 'sources:read',
|
|
WRITE_SOURCES: 'sources:write',
|
|
READ_REPORTS: 'reports:read',
|
|
WRITE_REPORTS: 'reports:write',
|
|
ADMIN: '*'
|
|
} as const |