54 lines
1.3 KiB
TypeScript
54 lines
1.3 KiB
TypeScript
import { createHash, randomBytes } from 'crypto'
|
|
import { prisma } from '@/lib/prisma'
|
|
|
|
const DEFAULT_TTL_MS = 7 * 24 * 60 * 60 * 1000
|
|
|
|
function hashMaterialShareToken(token: string): string {
|
|
return createHash('sha256').update(token).digest('hex')
|
|
}
|
|
|
|
export function getMaterialShareTokenHash(token: string): string {
|
|
return hashMaterialShareToken(token)
|
|
}
|
|
|
|
export async function createMaterialShareToken(
|
|
materialId: string,
|
|
createdByUserId: string,
|
|
ttlMs = DEFAULT_TTL_MS
|
|
): Promise<{ token: string; expiresAt: Date }> {
|
|
const token = randomBytes(32).toString('base64url')
|
|
const expiresAt = new Date(Date.now() + ttlMs)
|
|
|
|
await prisma.materialShareToken.create({
|
|
data: {
|
|
tokenHash: hashMaterialShareToken(token),
|
|
materialId,
|
|
createdByUserId,
|
|
expiresAt,
|
|
},
|
|
})
|
|
|
|
return { token, expiresAt }
|
|
}
|
|
|
|
export async function findValidMaterialShareToken(token: string, materialId?: string) {
|
|
const normalizedToken = token?.trim()
|
|
if (!normalizedToken) return null
|
|
|
|
const now = new Date()
|
|
return prisma.materialShareToken.findFirst({
|
|
where: {
|
|
tokenHash: hashMaterialShareToken(normalizedToken),
|
|
...(materialId ? { materialId } : {}),
|
|
revokedAt: null,
|
|
expiresAt: { gt: now },
|
|
material: {
|
|
deletedAt: null,
|
|
},
|
|
},
|
|
include: {
|
|
material: true,
|
|
},
|
|
})
|
|
}
|