Enforce API key quota within the database transaction
This commit is contained in:
+3
-4
@@ -1174,10 +1174,8 @@ const server = http.createServer(async (req, res) => {
|
||||
|
||||
if (req.method === 'POST') {
|
||||
try {
|
||||
const mevcut = store.listApiKeys(user.email).length;
|
||||
kotaKontrol(user.email, 'apiAnahtari', mevcut, 1, { isAdmin: user.isAdmin });
|
||||
const body = await readBody(req).catch(() => ({}));
|
||||
const k = store.createApiKey(user.email, body.ad);
|
||||
const body = await readBody(req);
|
||||
const k = store.createApiKey(user.email, body.ad, { limit: haklar(user.email, { isAdmin: user.isAdmin }).apiAnahtari });
|
||||
// `anahtar` YALNIZCA burada döner; sunucuda yalnızca hash'i saklanır
|
||||
return json(res, 200, { success: true, anahtar: k });
|
||||
} catch (e) {
|
||||
@@ -1188,6 +1186,7 @@ const server = http.createServer(async (req, res) => {
|
||||
const ok = store.revokeApiKey(user.email, url.searchParams.get('id'));
|
||||
return json(res, ok ? 200 : 404, { success: ok, error: ok ? undefined : 'Anahtar bulunamadı veya bu hesaba ait değil.', anahtarlar: store.listApiKeys(user.email), limit: haklar(user.email, { isAdmin: user.isAdmin }).apiAnahtari });
|
||||
}
|
||||
if (req.method !== 'GET') return json(res, 405, { success: false, error: 'Desteklenmeyen metot.' });
|
||||
return json(res, 200, { success: true, anahtarlar: store.listApiKeys(user.email), limit: haklar(user.email, { isAdmin: user.isAdmin }).apiAnahtari });
|
||||
}
|
||||
|
||||
|
||||
+22
-7
@@ -224,13 +224,28 @@ export function setData(email, anahtar, deger) {
|
||||
const sha256 = (s) => crypto.createHash('sha256').update(String(s)).digest('hex');
|
||||
|
||||
/** Yeni anahtar üretir. Ham değer YALNIZCA bir kez döner, saklanmaz. */
|
||||
export function createApiKey(email, ad) {
|
||||
const ham = 'ih_live_' + crypto.randomBytes(24).toString('base64url');
|
||||
const id = crypto.randomUUID();
|
||||
withDb((db) => db.prepare(
|
||||
'INSERT INTO api_anahtarlari (id,email,ad,onek,hash,olusturma) VALUES (?,?,?,?,?,?)'
|
||||
).run(id, email, ad || 'API Anahtarı', ham.slice(0, 12), sha256(ham), now()));
|
||||
return { id, ad: ad || 'API Anahtarı', onek: ham.slice(0, 12), anahtar: ham, olusturma: now() };
|
||||
export function createApiKey(email, ad, { limit = null } = {}) {
|
||||
if (ad != null && typeof ad !== 'string') throw new Error('Anahtar adı metin olmalı.');
|
||||
const name = ad?.trim() || 'API Anahtarı';
|
||||
if (name.length > 120) throw new Error('Anahtar adı en fazla 120 karakter olabilir.');
|
||||
if (limit !== null && (!Number.isInteger(limit) || limit < 0)) throw new Error('Geçersiz anahtar kotası.');
|
||||
return withDb((db) => {
|
||||
db.exec('BEGIN IMMEDIATE');
|
||||
try {
|
||||
const count = db.prepare('SELECT COUNT(*) n FROM api_anahtarlari WHERE email=? AND iptal=0').get(email).n;
|
||||
if (limit !== null && count >= limit) {
|
||||
const error = new Error(`Planınızda en fazla ${limit} API anahtarı oluşturabilirsiniz. Kullanılmayan bir anahtarı iptal edin veya Planlar sekmesini kontrol edin.`);
|
||||
error.kod = 'KOTA_ASILDI';
|
||||
throw error;
|
||||
}
|
||||
const ham = 'ih_live_' + crypto.randomBytes(24).toString('base64url');
|
||||
const id = crypto.randomUUID(), olusturma = now();
|
||||
db.prepare('INSERT INTO api_anahtarlari (id,email,ad,onek,hash,olusturma) VALUES (?,?,?,?,?,?)')
|
||||
.run(id, email, name, ham.slice(0, 12), sha256(ham), olusturma);
|
||||
db.exec('COMMIT');
|
||||
return { id, ad:name, onek:ham.slice(0,12), anahtar:ham, olusturma };
|
||||
} catch (error) { db.exec('ROLLBACK'); throw error; }
|
||||
});
|
||||
}
|
||||
|
||||
export function listApiKeys(email) {
|
||||
|
||||
Reference in New Issue
Block a user