release: v1.2.0 — unified images/ storage and legacy migration
ci / ci (22, ubuntu-latest) (push) Canceled after 0s
Publish Docker image / build (linux/amd64, ubuntu-latest, amd64) (push) Canceled after 0s
Publish Docker image / build (linux/arm64, ubuntu-24.04-arm, arm64) (push) Canceled after 0s
Publish Docker image / merge (push) Canceled after 0s
GitHub Release / release (push) Canceled after 0s
ci / ci (22, ubuntu-latest) (push) Canceled after 0s
Publish Docker image / build (linux/amd64, ubuntu-latest, amd64) (push) Canceled after 0s
Publish Docker image / build (linux/arm64, ubuntu-24.04-arm, arm64) (push) Canceled after 0s
Publish Docker image / merge (push) Canceled after 0s
GitHub Release / release (push) Canceled after 0s
Consolidate local images under data/images/, add docker migrate CLI, startup index sync with orphan cleanup, and remove upload folder UI/API.
This commit is contained in:
1 parent
3dee0437e6
commit
469d3be735
50 files changed
+1273
-956
No files matched your search
@@ -2,8 +2,9 @@ import type { DeleteResponse } from '~/types/image'
|
||||
import { requireApiOrAdminAuth, assertImageOwnership, resolveActivitySource } from '../../utils/access'
|
||||
import { createApiError } from '../../utils/api-error'
|
||||
import { insertActivityLog } from '../../utils/db'
|
||||
import { validateImageKey } from '../../utils/image-key'
|
||||
import { deleteImage, headImage } from '../../utils/storage'
|
||||
import { getImageIndexRow, deleteImageIndex } from '../../utils/image-index'
|
||||
import { toCanonicalImageKey, validateImageKey } from '../../utils/image-key'
|
||||
import { deleteImage, headImage, resolveStorageImageKey } from '../../utils/storage'
|
||||
import { logInfo } from '../../utils/logger'
|
||||
|
||||
interface DeleteBody {
|
||||
@@ -19,11 +20,43 @@ export default defineEventHandler(async (event) => {
|
||||
const key = (typeof query.key === 'string' ? query.key : undefined)
|
||||
?? body?.key
|
||||
|
||||
if (!key || !validateImageKey(key)) {
|
||||
if (
|
||||
!key
|
||||
|| (
|
||||
!validateImageKey(key)
|
||||
&& !toCanonicalImageKey(key)
|
||||
&& !getImageIndexRow(key)
|
||||
)
|
||||
) {
|
||||
createApiError(event, 'INVALID_IMAGE_KEY', '无效的图片路径', 400)
|
||||
}
|
||||
|
||||
const existing = await headImage(key)
|
||||
const storageKey = await resolveStorageImageKey(key) ?? key
|
||||
const existing = await headImage(storageKey)
|
||||
const indexed = getImageIndexRow(key) ?? getImageIndexRow(storageKey)
|
||||
|
||||
if (!existing && indexed) {
|
||||
await assertImageOwnership(event, indexed.user_id)
|
||||
deleteImageIndex(key)
|
||||
if (storageKey !== key) deleteImageIndex(storageKey)
|
||||
|
||||
insertActivityLog({
|
||||
action: 'delete',
|
||||
key,
|
||||
originalName: indexed.original_name,
|
||||
size: indexed.size,
|
||||
contentType: indexed.content_type,
|
||||
source: resolveActivitySource(event),
|
||||
userId: indexed.user_id ?? null,
|
||||
backendId: indexed.backend_id ?? null
|
||||
})
|
||||
|
||||
logInfo('delete orphan index', { key })
|
||||
|
||||
const response: DeleteResponse = { success: true }
|
||||
return response
|
||||
}
|
||||
|
||||
if (!existing) {
|
||||
createApiError(event, 'IMAGE_NOT_FOUND', '图片不存在', 404)
|
||||
}
|
||||
@@ -31,7 +64,7 @@ export default defineEventHandler(async (event) => {
|
||||
await assertImageOwnership(event, existing.userId)
|
||||
|
||||
try {
|
||||
await deleteImage(key)
|
||||
await deleteImage(storageKey, key)
|
||||
} catch {
|
||||
createApiError(event, 'DELETE_FAILED', '删除失败', 500)
|
||||
}
|
||||
@@ -47,7 +80,7 @@ export default defineEventHandler(async (event) => {
|
||||
backendId: existing.backendId ?? null
|
||||
})
|
||||
|
||||
logInfo('delete success', { key, size: existing.size })
|
||||
logInfo('delete success', { key: storageKey, size: existing.size })
|
||||
|
||||
const response: DeleteResponse = { success: true }
|
||||
return response
|
||||
|
||||
Reference in new issue
Block a user