Files
parakasa/lib/sms/verification-actions.ts
2026-01-29 16:49:51 +03:00

125 lines
4.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"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 }
}