"use server" import { createClient } from "@/lib/supabase-server" import { createClient as createSupabaseClient } from "@supabase/supabase-js" import { cookies } from "next/headers" import { NetGsmService } from "./netgsm" // We will reuse sendTestSms logic or create a specific one. sendTestSms uses Netgsm Service. // Better to export a generic 'sendSms' from lib/sms/actions.ts or just invoke the service directly. // lib/sms/actions.ts has `sendBulkSms` and `sendTestSms`. I should probably expose a generic `sendSms` there. // Admin client for Auth Codes table access const supabaseAdmin = createSupabaseClient( process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.SUPABASE_SERVICE_ROLE_KEY!, { auth: { autoRefreshToken: false, persistSession: false } } ) export async function sendVerificationCode() { const supabase = createClient() const { data: { user } } = await supabase.auth.getUser() if (!user) return { error: "Kullanıcı bulunamadı." } // 1. Get user phone const { data: profile } = await supabaseAdmin .from('profiles') .select('phone') .eq('id', user.id) .single() if (!profile?.phone) { return { error: "Profilinizde telefon numarası tanımlı değil. Lütfen yöneticinizle iletişime geçin." } } // 2. Generate Code const code = Math.floor(100000 + Math.random() * 900000).toString() // 6 digit const expiresAt = new Date(Date.now() + 5 * 60 * 1000) // 5 mins // 3. Store in DB // First, delete old codes for this email/user await supabaseAdmin.from('auth_codes').delete().eq('email', user.email!) const { error: dbError } = await supabaseAdmin.from('auth_codes').insert({ email: user.email!, code, expires_at: expiresAt.toISOString() }) if (dbError) { console.error("Auth code db error:", dbError) return { error: "Doğrulama kodu oluşturulamadı." } } // 4. Send SMS // We import the logic from Netgsm service wrapper // Since we don't have a direct 'sendSms' export in existing actions that accepts phone/message directly without admin assertion (which we have here via admin client, but the helper function `sendTestSms` does its own checks). // I will use a direct call to the generic `NetgsmService` logic if I can, or modify `lib/sms/actions.ts` to export it. // To avoid modifying too many files, I'll instantiate NetgsmService here if I can import it, or just use `sendBulkSms` with one number? // `sendBulkSms` asserts admin user. But here the calling user IS logged in (but might not be admin?). // Actually, `sendVerificationCode` is called by the logging-in user (who might be just 'user' role). // `lib/sms/actions.ts` -> `assertAdmin()` checks if current user is admin. // So if a normal user logs in, `sendBulkSms` will fail. // WE NEED A SYSTEM LEVEL SEND FUNCTION. // I will read credentials directly using Admin Client here. const { data: settings } = await supabaseAdmin.from('sms_settings').select('*').single() if (!settings) return { error: "SMS servisi yapılandırılmamış." } // Import the class dynamically or duplicate usage? // The class is in `./netgsm.ts` (based on actions.ts imports). // Let's import { NetGsmService } from "./netgsm" // NetGsmService imported at top const mobileService = new NetGsmService({ username: settings.username, password: settings.password, header: settings.header, apiUrl: settings.api_url }) const smsResult = await mobileService.sendSms(profile.phone, `Giris Dogrulama Kodunuz: ${code}`) if (!smsResult.success) { console.error("SMS Send Error:", smsResult) return { error: "SMS gönderilemedi. Lütfen daha sonra tekrar deneyin." } } return { success: true, phone: profile.phone.slice(-4) } // Return last 4 digits } export async function verifyCode(code: string) { const supabase = createClient() const { data: { user } } = await supabase.auth.getUser() if (!user) return { error: "Oturum bulunamadı." } // Check code const { data: record, error } = await supabaseAdmin .from('auth_codes') .select('*') .eq('email', user.email!) .eq('code', code) .gt('expires_at', new Date().toISOString()) .single() if (error || !record) { return { error: "Geçersiz veya süresi dolmuş kod." } } // Success: Set Cookie cookies().set('parakasa_2fa_verified', 'true', { httpOnly: true, secure: process.env.NODE_ENV === 'production', sameSite: 'lax', path: '/', maxAge: 60 * 60 * 24 // 24 hours }) // Delete used code await supabaseAdmin.from('auth_codes').delete().eq('id', record.id) return { success: true } }