у записи появился владелец: чужую больше не отдают

- колонка `owner` связью с `users` в обеих коллекциях новым шагом схемы
  `202608140001`; чтение задачи сужено владельцем, и чужая, ничья и
  несуществующая дают один ответ; правило просмотра файлов сужено им же
- приём по HTTP берёт владельца из сессии, а предъявителя без учётной записи
  пользователя отвергает до чтения тела: позже пришлось бы убирать уложенный
  файл, а уборки файлов сервис не умеет. Выборка воркера владельцем не сужается
- удаление учётной записи с записями отвергается стражем, и вешает его сама
  сборка хранилища: сборка, забывшая его позвать, теряла защиту молча
This commit is contained in:
av
2026-08-14 12:18:11 +03:00
parent b7d4660aef
commit 8af8ec2e54
46 changed files with 2520 additions and 101 deletions
@@ -45,7 +45,7 @@ func newFile(t *testing.T, app core.App) *entity.File {
require.NoError(t, err)
defer func() { require.NoError(t, work.Close()) }()
file, err := repo.CreateLocal("sample.mp3", work)
file, err := repo.CreateLocal("sample.mp3", work, "")
require.NoError(t, err)
return file
}
@@ -246,7 +246,7 @@ func TestSave_RefusesWriteFromLostAcquisition(t *testing.T) {
require.ErrorAs(t, err, &lost)
// И состояние не поехало.
after, err := repo.GetByID(mine.Id)
after, err := readJobByID(t, app, mine.Id)
require.NoError(t, err)
assert.Equal(t, entity.StateCreated, after.State)
}
@@ -261,7 +261,7 @@ func TestSave_WithoutHolderWritesAnyway(t *testing.T) {
require.NoError(t, repo.Save(job, ""))
after, err := repo.GetByID(job.Id)
after, err := readJobByID(t, app, job.Id)
require.NoError(t, err)
assert.Equal(t, entity.StateConverted, after.State)
}
@@ -291,7 +291,7 @@ func TestPanelRules_StateChangeByRequestClearsAcquisition(t *testing.T) {
// запросом к записи, а не сохранением из кода.
patchRecord(t, app, job.Id, `{"state":"`+entity.StateCreated+`"}`)
after, err := repo.GetByID(job.Id)
after, err := readJobByID(t, app, job.Id)
require.NoError(t, err)
assert.Nil(t, after.AcquisitionID, "признак захвата снят")
assert.Nil(t, after.AcquireTime, "время захвата снято")
@@ -323,7 +323,7 @@ func TestPanelRules_DoNotTouchPipelineWrites(t *testing.T) {
acquired.MoveToStateAndDelay(entity.StateTranscribe, &delay)
require.NoError(t, repo.Save(acquired, "holder"))
after, err := repo.GetByID(job.Id)
after, err := readJobByID(t, app, job.Id)
require.NoError(t, err)
require.NotNil(t, after.DelayTime, "задержка, поставленная шагом, пережила сохранение")
@@ -333,7 +333,7 @@ func TestPanelRules_DoNotTouchPipelineWrites(t *testing.T) {
after.Die("attempts exhausted: 6")
require.NoError(t, repo.Save(after, ""))
dead, err := repo.GetByID(job.Id)
dead, err := readJobByID(t, app, job.Id)
require.NoError(t, err)
assert.Equal(t, entity.StateDead, dead.State)
assert.Equal(t, 6, dead.Attempts, "число попыток мёртвой задачи сохранено")
@@ -404,9 +404,22 @@ func TestSave_KeepsOwnerEditMadeWhileStepHeldTheJob(t *testing.T) {
acquired.MoveToState(entity.StateConverted)
require.NoError(t, repo.Save(acquired, "holder"))
after, err := repo.GetByID(job.Id)
after, err := readJobByID(t, app, job.Id)
require.NoError(t, err)
assert.Equal(t, entity.StateConverted, after.State, "шаг свой результат записал")
require.NotNil(t, after.TgChatId)
assert.Equal(t, int64(999999), *after.TgChatId, "правка владельца пережила сохранение шага")
}
// readJobByID читает задачу мимо сужения владельцем: проверки хранилища смотрят
// задачи без владельца, а читающий метод их не отдаёт никому. Отображение при
// этом то же самое — сверяется именно оно.
func readJobByID(t *testing.T, app core.App, id string) (*entity.TranscribeJob, error) {
t.Helper()
record, err := app.FindRecordById(migrations.JobsCollection, id)
if err != nil {
return nil, err
}
return recordToJob(record), nil
}