zurri / src /utils /apiKey.ts
nexusbert's picture
initial commit
b5e5eac
import crypto from 'crypto';
import { AppDataSource } from '../config/database';
import { ApiKey } from '../entities/ApiKey';
const apiKeyRepository = AppDataSource.getRepository(ApiKey);
/**
* Generate a new API key
*/
export function generateApiKey(): string {
return `zurri_${crypto.randomBytes(32).toString('hex')}`;
}
/**
* Hash API key for storage
*/
export async function hashApiKey(key: string): Promise<string> {
return crypto.createHash('sha256').update(key).digest('hex');
}
/**
* Verify API key
*/
export async function verifyApiKey(
providedKey: string,
userId: string
): Promise<ApiKey | null> {
const hashedKey = await hashApiKey(providedKey);
const apiKey = await apiKeyRepository.findOne({
where: {
key: hashedKey,
userId,
isActive: true,
},
});
if (!apiKey) {
return null;
}
// Check expiry
if (apiKey.expiresAt && apiKey.expiresAt < new Date()) {
return null;
}
// Update usage stats
apiKey.usageCount += 1;
apiKey.lastUsedAt = new Date();
await apiKeyRepository.save(apiKey);
return apiKey;
}
/**
* Create API key for user
*/
export async function createApiKey(
userId: string,
options?: {
rateLimit?: number;
expiresAt?: Date;
}
): Promise<{ key: string; apiKey: ApiKey }> {
const rawKey = generateApiKey();
const hashedKey = await hashApiKey(rawKey);
const apiKey = apiKeyRepository.create({
key: hashedKey,
userId,
rateLimit: options?.rateLimit,
expiresAt: options?.expiresAt,
isActive: true,
});
const saved = await apiKeyRepository.save(apiKey);
return { key: rawKey, apiKey: saved };
}