// db/refreshToken.db.js const prisma = require("./client") function toDate(x) { if (!x) return null if (x instanceof Date) return x const d = new Date(x) return Number.isNaN(d.getTime()) ? null : d } async function createRefreshToken(userId, input = {}) { const data = { userId: Number(userId), tokenHash: input.tokenHash, // required familyId: input.familyId, // required jti: input.jti, // required expiresAt: toDate(input.expiresAt) || new Date(Date.now() + 1000 * 60 * 60 * 24 * 30), createdByIp: input.createdByIp ?? null, userAgent: input.userAgent ?? null, } return prisma.refreshToken.create({ data }) } async function findRefreshTokenByHash(tokenHash, options = {}) { return prisma.refreshToken.findUnique({ where: { tokenHash }, select: options.select || undefined, include: options.include || undefined, }) } async function revokeRefreshTokenById(id, meta = {}) { return prisma.refreshToken.update({ where: { id }, data: { revokedAt: meta.revokedAt ?? new Date(), // optional audit createdByIp: meta.createdByIp ?? undefined, userAgent: meta.userAgent ?? undefined, }, }) } async function revokeRefreshTokenByHash(tokenHash, meta = {}) { return prisma.refreshToken.update({ where: { tokenHash }, data: { revokedAt: meta.revokedAt ?? new Date(), createdByIp: meta.createdByIp ?? undefined, userAgent: meta.userAgent ?? undefined, }, }) } // Rotation: eski token -> revoked + replacedById set, yeni token create async function rotateRefreshToken({ oldId, newToken = {}, meta = {} }) { return prisma.$transaction(async (tx) => { const created = await tx.refreshToken.create({ data: { userId: Number(newToken.userId), tokenHash: newToken.tokenHash, familyId: newToken.familyId, jti: newToken.jti, expiresAt: toDate(newToken.expiresAt), createdByIp: meta.createdByIp ?? null, userAgent: meta.userAgent ?? null, }, }) const revoked = await tx.refreshToken.update({ where: { id: oldId }, data: { revokedAt: meta.revokedAt ?? new Date(), replacedById: created.id, }, }) return { created, revoked } }) } // Reuse tespiti / güvenlik: aynı ailedeki tüm tokenları revoke et async function revokeRefreshTokenFamily(familyId) { return prisma.refreshToken.updateMany({ where: { familyId, revokedAt: null }, data: { revokedAt: new Date() }, }) } async function revokeAllUserRefreshTokens(userId) { return prisma.refreshToken.updateMany({ where: { userId: Number(userId), revokedAt: null }, data: { revokedAt: new Date() }, }) } module.exports = { createRefreshToken, findRefreshTokenByHash, revokeRefreshTokenById, revokeRefreshTokenByHash, rotateRefreshToken, revokeRefreshTokenFamily, revokeAllUserRefreshTokens, }