- колонка `owner` связью с `users` в обеих коллекциях новым шагом схемы `202608140001`; чтение задачи сужено владельцем, и чужая, ничья и несуществующая дают один ответ; правило просмотра файлов сужено им же - приём по HTTP берёт владельца из сессии, а предъявителя без учётной записи пользователя отвергает до чтения тела: позже пришлось бы убирать уложенный файл, а уборки файлов сервис не умеет. Выборка воркера владельцем не сужается - удаление учётной записи с записями отвергается стражем, и вешает его сама сборка хранилища: сборка, забывшая его позвать, теряла защиту молча
62 lines
2.1 KiB
Go
62 lines
2.1 KiB
Go
package main
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
// Имя файла в хранилище в журнал не идёт: оно последняя часть ссылки
|
|
// `/api/files/...`, и строка журнала вместе с идентификатором записи собрала бы
|
|
// ссылку целиком. Инвариант проекта, critical.
|
|
func TestJournalRouteHidesStoredFileName(t *testing.T) {
|
|
cases := []struct {
|
|
name string
|
|
path string
|
|
want string
|
|
}{
|
|
{
|
|
name: "ссылка на файл теряет имя",
|
|
path: "/api/files/files/abc123def456ghi/9f1c-3b2a.mp3",
|
|
want: "/api/files/files/abc123def456ghi/<имя>",
|
|
},
|
|
{
|
|
name: "маршрут остаётся различимым",
|
|
path: "/api/files/files/abc123def456ghi/запись.ogg",
|
|
want: "/api/files/files/abc123def456ghi/<имя>",
|
|
},
|
|
{
|
|
name: "прочие пути не трогаются",
|
|
path: "/api/status/abc123def456ghi",
|
|
want: "/api/status/abc123def456ghi",
|
|
},
|
|
{
|
|
name: "приём не трогается",
|
|
path: "/api/audio",
|
|
want: "/api/audio",
|
|
},
|
|
{
|
|
name: "сам префикс без имени не портится",
|
|
path: "/api/files/",
|
|
want: "/api/files/",
|
|
},
|
|
}
|
|
|
|
for _, c := range cases {
|
|
t.Run(c.name, func(t *testing.T) {
|
|
assert.Equal(t, c.want, journalRoute(c.path))
|
|
})
|
|
}
|
|
}
|
|
|
|
// Отдельно и прямо: имени в готовой строке нет. Проверка судит результат, а не
|
|
// устройство — переписанная реализация обязана остаться зелёной.
|
|
func TestJournalRouteDropsNameEntirely(t *testing.T) {
|
|
const stored = "0f7b8dd3-d1cc-424c.mp3"
|
|
|
|
route := journalRoute("/api/files/files/rec0000000000000/" + stored)
|
|
|
|
assert.NotContains(t, route, stored, "имя файла в хранилище не доезжает до журнала")
|
|
assert.Contains(t, route, "rec0000000000000", "идентификатор записи остаётся: по нему прослеживается путь")
|
|
}
|