feat: kimlik doğrulama, ödeme, kredi ve AI rapor sihirbazı ekle
- better-auth ile giriş/oturum yönetimi (src/lib/auth, giris sayfası) - iyzico ödeme entegrasyonu ve paket satın alma akışı - kredi sistemi ve uygulama veritabanı şeması (drizzle) - AI destekli rapor üretimi ve tercih sihirbazı - rapor yazdırma sayfası ve site header/kullanıcı menüsü Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
71
src/lib/auth.ts
Normal file
71
src/lib/auth.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import { betterAuth } from "better-auth";
|
||||
import { drizzleAdapter } from "better-auth/adapters/drizzle";
|
||||
import { magicLink } from "better-auth/plugins";
|
||||
import { appDb, schema } from "./appdb";
|
||||
import { grantCredits, DENEME_KREDISI } from "./credits";
|
||||
|
||||
async function sendMagicLinkEmail(email: string, url: string) {
|
||||
if (!process.env.RESEND_API_KEY) {
|
||||
// Dev fallback: Resend anahtarı yoksa linki terminale yaz
|
||||
console.log(`\n[giris] Magic link for ${email}:\n${url}\n`);
|
||||
return;
|
||||
}
|
||||
const { Resend } = await import("resend");
|
||||
const resend = new Resend(process.env.RESEND_API_KEY);
|
||||
await resend.emails.send({
|
||||
from: process.env.EMAIL_FROM ?? "KolayTercih <onboarding@resend.dev>",
|
||||
to: email,
|
||||
subject: "KolayTercih giriş bağlantın",
|
||||
html: `<p>Merhaba,</p><p>KolayTercih'e giriş yapmak için <a href="${url}">buraya tıkla</a>. Bağlantı 5 dakika geçerlidir.</p><p>Bu isteği sen yapmadıysan bu e-postayı yok sayabilirsin.</p>`,
|
||||
});
|
||||
}
|
||||
|
||||
export const auth = betterAuth({
|
||||
baseURL: process.env.BETTER_AUTH_URL ?? "http://localhost:3000",
|
||||
secret: process.env.BETTER_AUTH_SECRET,
|
||||
database: drizzleAdapter(appDb, {
|
||||
provider: "sqlite",
|
||||
schema: {
|
||||
user: schema.user,
|
||||
session: schema.session,
|
||||
account: schema.account,
|
||||
verification: schema.verification,
|
||||
},
|
||||
}),
|
||||
user: {
|
||||
additionalFields: {
|
||||
creditBalance: { type: "number", defaultValue: 0, input: false },
|
||||
hasPaket: { type: "boolean", defaultValue: false, input: false },
|
||||
},
|
||||
},
|
||||
socialProviders: {
|
||||
google: {
|
||||
clientId: process.env.GOOGLE_CLIENT_ID ?? "",
|
||||
clientSecret: process.env.GOOGLE_CLIENT_SECRET ?? "",
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
magicLink({
|
||||
sendMagicLink: async ({ email, url }) => {
|
||||
await sendMagicLinkEmail(email, url);
|
||||
},
|
||||
}),
|
||||
],
|
||||
databaseHooks: {
|
||||
user: {
|
||||
create: {
|
||||
after: async (newUser) => {
|
||||
// refId = userId → UNIQUE(reason, refId) ile tek seferlik
|
||||
await grantCredits({
|
||||
userId: newUser.id,
|
||||
delta: DENEME_KREDISI,
|
||||
reason: "trial_grant",
|
||||
refId: newUser.id,
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export type Session = typeof auth.$Infer.Session;
|
||||
Reference in New Issue
Block a user