观影照片支持 DELETE 单删(暴露已存在的 Movie::deletePhoto)(#86)
用户:编辑观影记录的时候,那个图片应该可以被删除吧?现在没有删除按钮。 Movie::deletePhoto() 早就存在(连存储对象一起删,含视频 thumb_key), 网页端 movies/photo_del 也一直在用 —— 缺的只是 API 那一层。 - /movies/<id>/photos 从\"只 POST\"扩为 POST 追加 + DELETE 删除; - photo_id 走 query:Api::dispatch() 只解析到 parts[2],parts[3] 会被 静默丢弃;与 trips/<id>/nodes/attach 同一口径; - 删除前显式校验归属(id + event_id 同查),不匹配就 404 —— deletePhoto 内部遇到错配是\"删 0 行 + 静默成功\",会让调用方误以为删掉了; - poster 仍只 POST:换海报是覆盖语义,清空走 PATCH 空 poster_key。 验证:event_id 错配查询返回 false(越权被拦);临时图入库后删除, 5→4 张、库行消失、Storage::exists true→false(驱动 OSS)。 已部署,md5 核对 b50db4dfff743c53c9e4988d694b202b,php -l 通过。
This commit is contained in:
@@ -2261,6 +2261,51 @@ final class ApiHandler
|
||||
if (!$m) { Api::notFound('这条观影记录'); }
|
||||
|
||||
if ($sub === 'poster' || $sub === 'photos') {
|
||||
/* 🔴 2026-11-06:`photos` 现在同时支持 **POST(追加)** 与
|
||||
**DELETE(删一张)** —— 用户「编辑观影记录的时候,那个图片
|
||||
应该可以被删除吧?现在没有删除按钮。」
|
||||
⚠️ `poster` 只有 POST(换海报是覆盖语义,没有"删海报"这个操作 ——
|
||||
清空海报请用 PATCH 传空 `poster_key`,那条路由本来就支持)。
|
||||
⚠️ DELETE 的 `photo_id` 走 query:`Api::dispatch()` 只解析到
|
||||
路径第三段(`movies/<id>/photos`),再往后会被丢掉。
|
||||
同类做法见 `trips/<id>/nodes/attach`。 */
|
||||
if ($sub === 'photos' && $method === 'DELETE') {
|
||||
Api::requireWrite();
|
||||
$photoId = (int)Api::int('photo_id');
|
||||
if ($photoId <= 0) {
|
||||
Api::fail('要说明删哪一张(photo_id)。', 'bad_request', 400);
|
||||
}
|
||||
/* ⚠️ 先确认这张照片确实属于这条记录,再删 ——
|
||||
否则传一个别的记录的照片 id 也能删掉(越权删)。
|
||||
`deletePhoto` 内部是 `WHERE id = ? AND event_id = ?`,
|
||||
错配时它删 0 行、什么也不做,但那样**静默成功**会误导调用方,
|
||||
所以这里显式校验一次,删不到就报 404。 */
|
||||
$st = Database::get()->prepare(
|
||||
'SELECT id FROM event_photos WHERE id = ? AND event_id = ?'
|
||||
);
|
||||
$st->execute([$photoId, $id]);
|
||||
if (!$st->fetchColumn()) {
|
||||
Api::notFound('这张照片');
|
||||
}
|
||||
Movie::deletePhoto($fam, $id, $photoId);
|
||||
Api::ok([
|
||||
'deleted' => $photoId,
|
||||
'photos' => array_map(
|
||||
static fn(array $p): array => [
|
||||
'id' => (int)$p['id'],
|
||||
'key' => (string)$p['key'],
|
||||
'kind' => (string)($p['kind'] ?? 'image'),
|
||||
'url' => Storage\Storage::url($fam, (string)$p['key']),
|
||||
'thumb' => !empty($p['thumb_key'])
|
||||
? Storage\Storage::url($fam, (string)$p['thumb_key'])
|
||||
: '',
|
||||
'mime' => (string)($p['mime'] ?? ''),
|
||||
],
|
||||
Movie::photos($id)
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
if ($method !== 'POST') { Api::fail('不支持的方法。', 'method_not_allowed', 405); }
|
||||
Api::requireWrite();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user