удалён вход Telegram, владелец записи стал обязателен в схеме

- убраны клиент бота, транспорт обновлений, отправитель сообщений, сборка
  входа при старте, секция настроек и зависимость go-telegram-bot-api; из
  конвейера ушла доставка ответа отправителю — исход виден опросом готовности.
  Колонки адресата и значение источника остались в схеме: применённые шаги не
  переписываются
- шаг 202608140003 запрещает пустого владельца у аудиозаписи и у файла;
  существующие строки он не проверяет, и это принято сознательно — искать их
  надо запросом до выкладки
- ревью нашло два пред-существующих дефекта, оба закрыты: пустой второй ответ
  распознавателя стирал сохранённую расшифровку, а пустая расшифровка перестала
  быть заметной вместе с убранной доставкой. Попутно поднят golang.org/x/image
  до v0.45.0 — красный шаг vulns, воспроизводился и на чистом master
This commit is contained in:
av
2026-08-15 07:24:35 +03:00
parent 97ceb7bb69
commit 8f7c3a057a
74 changed files with 2453 additions and 2733 deletions
+46 -16
View File
@@ -42,9 +42,7 @@ func newRecordOf(t *testing.T, app core.App, ownerID string) *entity.AudioRecord
State: entity.StateUploaded,
StateEnteredAt: clock.Now(),
Source: entity.SourceApi,
}
if ownerID != "" {
record.OwnerID = &ownerID
OwnerID: ownerID,
}
require.NoError(t, NewAudioRecordRepository(app).Create(record))
return record
@@ -65,8 +63,7 @@ func TestGuardOwnerDeletion(t *testing.T) {
after, err := NewAudioRecordRepository(app).Get(record.Id)
require.NoError(t, err, "запись на месте")
require.NotNil(t, after.OwnerID, "и владелец у неё прежний")
assert.Equal(t, account.Id, *after.OwnerID)
assert.Equal(t, account.Id, after.OwnerID, "и владелец у неё прежний")
}
// Считаются все коллекции с владельцем, а не одни записи: файл переживает свою
@@ -119,19 +116,52 @@ func TestGuardOwnerDeletionLetsEmptyAccountGo(t *testing.T) {
require.NoError(t, app.Delete(account), "пустая учётная запись удаляется")
}
// Умолчания у колонки владельца нет: запись, чей владелец не назван, не
// достаётся никому по недосмотру схемы.
func TestOwnerColumnHasNoDefault(t *testing.T) {
// Колонка владельца пустого значения не принимает и умолчания не имеет:
// ничьей записи в хранилище не бывает, и завести её нечем — ни приёмом, ни
// конвейером, ни рукой в панели.
func TestOwnerColumnRefusesEmptyValue(t *testing.T) {
app := newTestStorage(t)
records, err := app.FindCollectionByNameOrId(migrations.RecordsCollection)
require.NoError(t, err)
for _, name := range []string{migrations.RecordsCollection, migrations.FilesCollection} {
t.Run(name, func(t *testing.T) {
collection, err := app.FindCollectionByNameOrId(name)
require.NoError(t, err)
field := records.Fields.GetByName("owner")
require.NotNil(t, field, "колонка владельца заведена")
field := collection.Fields.GetByName("owner")
require.NotNil(t, field, "колонка владельца заведена")
relation, ok := field.(*core.RelationField)
require.True(t, ok, "владелец — связь с учётной записью, а не строка")
assert.False(t, relation.Required, "пустое значение допустимо ради записей бота")
assert.False(t, relation.CascadeDelete, "удаление учётной записи не уносит архив следом")
relation, ok := field.(*core.RelationField)
require.True(t, ok, "владелец — связь с учётной записью, а не строка")
assert.True(t, relation.Required, "пустое значение колонка не принимает")
assert.False(t, relation.CascadeDelete, "удаление учётной записи не уносит архив следом")
})
}
}
// Та же норма со стороны сохранения: схема отвергает запись без владельца, а не
// только объявляет колонку обязательной.
func TestStorageRefusesRecordWithoutOwner(t *testing.T) {
app := newTestStorage(t)
record := &entity.AudioRecord{
State: entity.StateUploaded,
StateEnteredAt: clock.Now(),
Source: entity.SourceApi,
}
require.Error(t, NewAudioRecordRepository(app).Create(record),
"ничья запись в хранилище не ложится")
}
// И файл — наравне с записью: разное правило у них читалось бы как недосмотр.
func TestStorageRefusesFileWithoutOwner(t *testing.T) {
app := newTestStorage(t)
repo := NewFileRepository(app)
work, err := repo.Stage(".mp3", strings.NewReader("запись"))
require.NoError(t, err)
defer func() { require.NoError(t, work.Close()) }()
_, err = repo.Create("sample.mp3", work, contract.FileMeta{Format: "mp3"}, "")
require.Error(t, err, "ничей файл в хранилище не ложится")
}