v1.10.88 품질·보안 개선과 미디어 카탈로그 database 전환을 반영한다.

세션·로그인 제한, ZIP/업로드 스트리밍, CSP 최소 강제와 Report-Only, Playwright 격리 검증을 추가하고 미디어 목록을 reconcile 후 database 모드로 고정한다.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-22 11:05:40 +09:00
parent 9bc0f0a90e
commit de767095ba
116 changed files with 8128 additions and 2933 deletions

View File

@@ -13,6 +13,8 @@ import {
isPostBodyThumbnailUrl,
isPostCardThumbnailUrl
} from '../../lib/post-card-thumbnail-url.js'
import { recordMediaCatalogFile } from '../repositories/media-catalog-repository'
import { resolveUploadUrlPath } from './upload-root'
export {
getPageCoverThumbnailUrl,
@@ -183,7 +185,7 @@ export const getPostThumbnailDiskPath = (imageUrl) => {
return ''
}
return join(process.cwd(), 'public', decodeUrlPathPart(thumbnailUrl.replace(/^\/+/, '')))
return resolveUploadUrlPath(decodeUrlPathPart(thumbnailUrl))
}
/**
@@ -198,7 +200,7 @@ export const getPostBodyThumbnailDiskPath = (imageUrl) => {
return ''
}
return join(process.cwd(), 'public', decodeUrlPathPart(thumbnailUrl.replace(/^\/+/, '')))
return resolveUploadUrlPath(decodeUrlPathPart(thumbnailUrl))
}
/**
@@ -213,7 +215,7 @@ export const getPostBodyPreviewThumbnailDiskPath = (imageUrl) => {
return ''
}
return join(process.cwd(), 'public', decodeUrlPathPart(thumbnailUrl.replace(/^\/+/, '')))
return resolveUploadUrlPath(decodeUrlPathPart(thumbnailUrl))
}
/**
@@ -228,7 +230,7 @@ export const getPostLightboxThumbnailDiskPath = (imageUrl) => {
return ''
}
return join(process.cwd(), 'public', decodeUrlPathPart(thumbnailUrl.replace(/^\/+/, '')))
return resolveUploadUrlPath(decodeUrlPathPart(thumbnailUrl))
}
/**
@@ -243,7 +245,7 @@ export const getPageCoverThumbnailDiskPath = (imageUrl) => {
return ''
}
return join(process.cwd(), 'public', decodeUrlPathPart(thumbnailUrl.replace(/^\/+/, '')))
return resolveUploadUrlPath(decodeUrlPathPart(thumbnailUrl))
}
/**
@@ -256,7 +258,7 @@ export const getPostImageDiskPath = (imageUrl) => {
return ''
}
return join(process.cwd(), 'public', decodeUrlPathPart(imageUrl.replace(/^\/+/, '')))
return resolveUploadUrlPath(decodeUrlPathPart(imageUrl))
}
/**
@@ -384,6 +386,13 @@ export const createPostThumbnailForImageUrl = async (imageUrl) => {
.webp({ quality: POST_THUMBNAIL_QUALITY })
.toFile(temporaryPath))
if (created) {
await recordMediaCatalogFile(thumbnailUrl, {
origin: 'derived',
role: 'card'
})
}
return created ? thumbnailUrl : ''
}
@@ -419,6 +428,13 @@ export const createPageCoverThumbnailForImageUrl = async (imageUrl) => {
.webp({ quality: PAGE_COVER_THUMBNAIL_QUALITY })
.toFile(temporaryPath))
if (created) {
await recordMediaCatalogFile(thumbnailUrl, {
origin: 'derived',
role: 'page_cover'
})
}
return created ? thumbnailUrl : ''
}
@@ -481,6 +497,21 @@ export const createPostBodyThumbnailForImageUrl = async (imageUrl) => {
return ''
}
await Promise.all([
recordMediaCatalogFile(thumbnailUrl, {
origin: 'derived',
role: 'body'
}),
recordMediaCatalogFile(getPostBodyPreviewThumbnailUrl(imageUrl), {
origin: 'derived',
role: 'body'
}),
recordMediaCatalogFile(getPostLightboxThumbnailUrl(imageUrl), {
origin: 'derived',
role: 'body'
})
])
return thumbnailUrl
}