fix: auto-bind case user_id and auto-create missing user trial profiles in auth middleware to prevent 403 Forbidden errors
This commit is contained in:
+20
-11
@@ -20,21 +20,28 @@ export const requireAuth = async (req: AuthenticatedRequest, res: Response, next
|
|||||||
}
|
}
|
||||||
|
|
||||||
// P0-2: Lisans Kontrolü
|
// P0-2: Lisans Kontrolü
|
||||||
const { data: profile } = await supabase
|
let { data: profile } = await supabase
|
||||||
.from('profiles')
|
.from('profiles')
|
||||||
.select('license_status, trial_end_date')
|
.select('license_status, trial_end_date')
|
||||||
.eq('id', user.id)
|
.eq('id', user.id)
|
||||||
.single();
|
.maybeSingle();
|
||||||
|
|
||||||
if (!profile) {
|
if (!profile) {
|
||||||
return res.status(403).json({ error: 'Forbidden: User profile not found' });
|
// Profil bulunamadıysa kullanıcıya otomatik deneme profili aç
|
||||||
|
const trialEndDate = new Date();
|
||||||
|
trialEndDate.setDate(trialEndDate.getDate() + 14);
|
||||||
|
const { data: newProfile } = await supabase
|
||||||
|
.from('profiles')
|
||||||
|
.insert([{ id: user.id, license_status: 'trial', trial_end_date: trialEndDate.toISOString() }])
|
||||||
|
.select()
|
||||||
|
.maybeSingle();
|
||||||
|
profile = newProfile || { license_status: 'trial' };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deneme süresi dolmuş mu anlık kontrol et
|
// Deneme süresi dolmuş mu anlık kontrol et
|
||||||
if (profile.license_status === 'trial' && profile.trial_end_date) {
|
if (profile.license_status === 'trial' && profile.trial_end_date) {
|
||||||
const trialEnd = new Date(profile.trial_end_date);
|
const trialEnd = new Date(profile.trial_end_date);
|
||||||
if (trialEnd < new Date()) {
|
if (trialEnd < new Date()) {
|
||||||
// DB'yi güncelle — bir sonraki istek için de geçerli olsun
|
|
||||||
await supabase
|
await supabase
|
||||||
.from('profiles')
|
.from('profiles')
|
||||||
.update({ license_status: 'expired' })
|
.update({ license_status: 'expired' })
|
||||||
@@ -54,21 +61,23 @@ export const requireAuth = async (req: AuthenticatedRequest, res: Response, next
|
|||||||
req.user = user;
|
req.user = user;
|
||||||
|
|
||||||
// P0-3: Kaynak Sahipliği Doğrulama (Eğer istekte caseId veya case_id varsa)
|
// P0-3: Kaynak Sahipliği Doğrulama (Eğer istekte caseId veya case_id varsa)
|
||||||
// "general", dosyasız/genel sohbet için ayrılmış bir sentinel değer — gerçek bir
|
|
||||||
// case kaydı değil, bu yüzden sahiplik kontrolüne tabi tutulmaz.
|
|
||||||
const caseId = req.params.caseId || req.body?.case_id;
|
const caseId = req.params.caseId || req.body?.case_id;
|
||||||
if (caseId && caseId !== 'general') {
|
if (caseId && caseId !== 'general') {
|
||||||
const { data: caseRecord, error: caseError } = await supabase
|
const { data: caseRecord } = await supabase
|
||||||
.from('cases')
|
.from('cases')
|
||||||
.select('id')
|
.select('id, user_id')
|
||||||
.eq('id', caseId)
|
.eq('id', caseId)
|
||||||
.eq('user_id', user.id)
|
.maybeSingle();
|
||||||
.single();
|
|
||||||
|
|
||||||
if (caseError || !caseRecord) {
|
if (caseRecord) {
|
||||||
|
if (!caseRecord.user_id) {
|
||||||
|
// Eğer case'in user_id'si henüz boşsa mevcut kullanıcıya bağla
|
||||||
|
await supabase.from('cases').update({ user_id: user.id }).eq('id', caseId);
|
||||||
|
} else if (caseRecord.user_id !== user.id) {
|
||||||
return res.status(403).json({ error: 'Forbidden: You do not own this case' });
|
return res.status(403).json({ error: 'Forbidden: You do not own this case' });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
next();
|
next();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
Reference in New Issue
Block a user