diff --git a/docs/quality/uygulama-durumu.md b/docs/quality/uygulama-durumu.md index dddcded..828944b 100644 --- a/docs/quality/uygulama-durumu.md +++ b/docs/quality/uygulama-durumu.md @@ -2170,3 +2170,9 @@ Doğrulama: 293 otomatik test ve üretim derlemesi başarılı. Gerçek iki hesa Harici ICS etkinlikleri daha önce ortak `sessionStorage` anahtarında tutuluyordu. Kayıtlar artık normalize edilmiş hesap e-postasına bağlı anahtarda saklanıyor; hesap değişiminde takvim temizlenip yeni hesabın etkinlikleri yükleniyor. Browser QA, anahtarın hesap kapsamlı olduğunu ve sekme değişimi sonrası kalıcılığı doğruluyor. Doğrulama: browser QA başarılı; 293 otomatik test ve üretim derlemesi başarılı. Gerçek iki hesaplı tarayıcı kabulü ve OAuth takvim senkronizasyonu açık. + +### 2026-09-06 · Giriş ve belge uyarısı anahtarlarının normalizasyonu + +Son giriş zaman damgası, oturum ziyaret damgası ve belge son kullanma uyarısı anahtarları ortak `hesapAnahtari` yardımcısını kullanıyor. E-posta boşlukları/büyük harfleri normalize ediliyor ve özel karakterler kodlanıyor; hesap kapsamlı istemci kayıtları artık tutarlı anahtar üretir. + +Doğrulama: 293 otomatik test ve üretim derlemesi başarılı. Gerçek iki hesaplı tarayıcı kabulü açık. diff --git a/src/context/AppContext.jsx b/src/context/AppContext.jsx index 563bd6f..70bb65f 100644 --- a/src/context/AppContext.jsx +++ b/src/context/AppContext.jsx @@ -20,6 +20,7 @@ const AppContext = createContext(); // İhale önbelleği: tam havuz (10.000+ kayıt) localStorage kotasına sığmaz. const TENDER_CACHE_KEY = 'ihaleist_tenders'; const TENDER_CACHE_LIMIT = 300; +const hesapAnahtari = (prefix, email) => `${prefix}:${encodeURIComponent(String(email || '').trim().toLowerCase())}`; // localStorage her zaman yazılabilir değildir (kota dolu, gizli sekme, site // verisi kapalı). Yazma hatası uygulamayı çökertmemeli. @@ -150,15 +151,15 @@ export const AppProvider = ({ children }) => { useEffect(() => { if (!authUser) return; try { - const anahtar = 'ihaleist_son_giris:' + authUser.email; + const anahtar = hesapAnahtari('ihaleist_son_giris', authUser.email); const onceki = Number(localStorage.getItem(anahtar)) || null; - const oturum = sessionStorage.getItem('ihaleist_oturum_giris:' + authUser.email); + const oturum = sessionStorage.getItem(hesapAnahtari('ihaleist_oturum_giris', authUser.email)); if (oturum !== null) { // aynı sekmede yenileme: damga sabit kalır setOncekiGiris(Number(oturum) || null); return; } setOncekiGiris(onceki); - sessionStorage.setItem('ihaleist_oturum_giris:' + authUser.email, String(onceki || 0)); + sessionStorage.setItem(hesapAnahtari('ihaleist_oturum_giris', authUser.email), String(onceki || 0)); localStorage.setItem(anahtar, String(Date.now())); } catch { /* depolama kapalıysa kart bugünü gösterir */ } }, [authUser?.email]); @@ -708,7 +709,7 @@ export const AppProvider = ({ children }) => { useEffect(() => { if (!veriSenkron) return; const session = getToken(); - const uyariAnahtari = 'ihaleist_belge_uyari_gunu:' + authUser?.email; + const uyariAnahtari = hesapAnahtari('ihaleist_belge_uyari_gunu', authUser?.email); const bugun = new Date().toISOString().slice(0, 10); try { if (localStorage.getItem(uyariAnahtari) === bugun) return; } catch { /* yoksay */ } listDocuments().then((d) => {