fix: bind Telegram pairing to expiring single-use account challenges

This commit is contained in:
2026-09-06 14:50:11 +03:00
parent aca1f5c3d1
commit 283bfe5990
9 changed files with 137 additions and 23 deletions
+28
View File
@@ -0,0 +1,28 @@
import { randomBytes, createHash } from 'node:crypto';
const digest = code => createHash('sha256').update(code).digest('hex');
export function createTelegramLinker(store,clock=Date.now) {
function validate(email,code) {
const snapshot=store.getDataSnapshot(email),value=snapshot.veri.telegram;
if(typeof code!=='string'||!/^[a-f0-9]{48}$/.test(code)||value?.challengeHash!==digest(code)||
!Number.isFinite(value.expiresAt)||clock()>=value.expiresAt)
throw Object.assign(new Error('Bağlama kodu geçersiz veya süresi dolmuş. Yeni kod oluşturun.'),{status:400});
return {value,revision:snapshot.revisions.telegram ?? null};
}
return {
issue(email) {
const snapshot=store.getDataSnapshot(email);
if(snapshot.veri.telegram?.chatId)throw Object.assign(new Error('Önce mevcut Telegram bağlantısını kaldırın.'),{status:409});
const code=randomBytes(24).toString('hex'),issuedAt=clock(),expiresAt=issuedAt+10*60000;
store.setData(email,'telegram',{challengeHash:digest(code),issuedAt,expiresAt},snapshot.revisions.telegram ?? null);
return {kod:code,expiresAt};
},
async link(email,code,find) {
const {value}=validate(email,code);
const found=await find(code,{issuedAt:value.issuedAt,expiresAt:value.expiresAt,now:clock()});
if(!found)throw Object.assign(new Error('Kod özel sohbette bulunamadı. Yeni kodu bota gönderip tekrar doğrulayın.'),{status:404});
const current=validate(email,code);
store.setData(email,'telegram',{chatId:found.chatId,ad:found.ad,baglanma:new Date(clock()).toISOString()},current.revision);
return found;
},
};
}