terms: seed-on-fetch + rename/delete sync (v0.3.3)
- public route `/manifest/terms/:packKey/:fileName` 가 sendFile 전에 `ensurePackTermsDir(packKey)` 를 호출하도록 수정. 관리자가 사이트 약관 페이지를 한 번도 열지 않은 fresh 배포에서도 설치기가 정상적으로 약관을 받을 수 있다. `loadPackDefinition` 으로 실제 pack 만 허용해 임의 키로 빈 폴더가 생성되는 것을 차단. - `renamePack`: pack JSON 이름이 바뀌면 `manifest/terms/<oldKey>/` 도 `<newKey>/` 로 함께 rename. - `deletePackKeys`: pack 삭제 시 약관 폴더도 `fs.rm` 으로 정리 — 동일 key 재생성 시 옛 약관 부활 방지. - `ensurePackTermsDir` export. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -6,7 +6,7 @@ import {
|
||||
manifestRootPath, manifestDirPath, manifestTermsDirPath,
|
||||
fileDirPath, viewsDirPath, publicDirPath
|
||||
} from '../shared/paths.js'
|
||||
import { isPublicTermsFile } from '../shared/store.js'
|
||||
import { ensurePackTermsDir, isPublicTermsFile, loadPackDefinition } from '../shared/store.js'
|
||||
import { loadEnv } from '../shared/env.js'
|
||||
import { t, localeDict } from './i18n.js'
|
||||
import { indexRouter } from './routes/index.js'
|
||||
@@ -66,17 +66,32 @@ app.get('/manifest.json', (_req, res) => {
|
||||
// 설치기 + 사이트가 약관(markdown) 을 가져갈 수 있도록 .md 만 허용한다.
|
||||
// 음악퀴즈(pack) 별로 manifest/terms/<packKey>/<file>.md 에서 노출한다.
|
||||
// _meta.json 같은 시스템 파일이나 경로 탈출은 isPublicTermsFile 에서 차단.
|
||||
app.get('/manifest/terms/:packKey/:fileName', (req, res) => {
|
||||
const { packKey, fileName } = req.params
|
||||
if (!isPublicTermsFile(packKey, fileName)) {
|
||||
res.status(404).send('Not Found')
|
||||
return
|
||||
//
|
||||
// fresh 배포에서 관리자가 약관 페이지를 한 번도 열지 않은 상태로 설치기가 약관을
|
||||
// 요청하는 경우에도 작동하도록, 실제 pack 이면 ensurePackTermsDir 로 v0.3.1
|
||||
// 전역 .md 들을 시드 복사한 뒤 sendFile 한다. 임의 packKey 로 빈 폴더가
|
||||
// 생성되는 것은 loadPackDefinition 으로 차단.
|
||||
app.get('/manifest/terms/:packKey/:fileName', async (req, res, next) => {
|
||||
try {
|
||||
const { packKey, fileName } = req.params
|
||||
if (!isPublicTermsFile(packKey, fileName)) {
|
||||
res.status(404).send('Not Found')
|
||||
return
|
||||
}
|
||||
const pack = await loadPackDefinition(packKey)
|
||||
if (!pack) {
|
||||
res.status(404).send('Not Found')
|
||||
return
|
||||
}
|
||||
await ensurePackTermsDir(packKey)
|
||||
res.type('text/markdown; charset=utf-8')
|
||||
res.sendFile(path.join(manifestTermsDirPath, packKey, fileName), (err) => {
|
||||
if (!err || res.headersSent) return
|
||||
res.status(404).send('Not Found')
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
res.type('text/markdown; charset=utf-8')
|
||||
res.sendFile(path.join(manifestTermsDirPath, packKey, fileName), (err) => {
|
||||
if (!err || res.headersSent) return
|
||||
res.status(404).send('Not Found')
|
||||
})
|
||||
})
|
||||
|
||||
// 설치기에서 개별 음악퀴즈 JSON을 가져갈 수 있도록 파일 단위로만 허용.
|
||||
|
||||
Reference in New Issue
Block a user