package migrations import ( "errors" "fmt" "github.com/pocketbase/pocketbase/core" ) // up202608140003 запрещает пустого владельца у аудиозаписи и у её файла. // // Прежде пустое значение допускалось, и цену за это платили записи, принятые // ботом: связи чата Telegram с учётной записью сервис не вёл, и владельца у них // не было вовсе. Вход Telegram убран, заводить ничью запись стало некому, и // обязательность переезжает из приёма в схему — туда, где её держит хранилище, а // не договорённость. Разница не косметическая: пока обязательность жила в // приёме, ничью запись заводили руками в панели, она уходила в конвейер, стоила // денег на распознавание и не доставалась потом никому. // // Существующих строк шаг **не смотрит**, и это проверено прогоном: хранилище // держит обязательность связи проверкой записи при сохранении, а не ограничением // таблицы, поэтому смена признака на базе с ничьей записью проходит зелёным и // такую запись оставляет. Искать ничьи строки надо до выкладки и запросом — // `SELECT count(*) FROM audio_records WHERE owner = ”` и то же по `files`; // прогон самого шага на копии этого не показывает. // // Оставленная ничья запись становится незакрываемой: захват идёт сырым запросом // мимо проверки и выдаёт её воркеру, а всякое сохранение — включая то, которым // ставится признак остановки, — отказывает. Порядок выкладки поэтому начинается // с проверки данных, а не с прогона шага. func up202608140003(app core.App) error { for _, name := range []string{RecordsCollection, FilesCollection} { if err := setOwnerRequired(app, name, true); err != nil { return err } } return nil } // down202608140003 возвращает колонке необязательность. Записей это не касается: // пустых значений среди них нет, а появиться им теперь неоткуда. func down202608140003(app core.App) error { for _, name := range []string{RecordsCollection, FilesCollection} { if err := setOwnerRequired(app, name, false); err != nil { return err } } return nil } // setOwnerRequired правит признак обязательности у колонки владельца одной // коллекции. Колонка ищется по имени и приводится к типу связи: шаг, молча // пропустивший чужой тип, оставил бы схему в состоянии, о котором никто не // узнает. func setOwnerRequired(app core.App, collectionName string, required bool) error { collection, err := app.FindCollectionByNameOrId(collectionName) if err != nil { return fmt.Errorf("failed to find collection %s: %w", collectionName, err) } field := collection.Fields.GetByName("owner") if field == nil { return errors.New("collection " + collectionName + " has no owner field") } relation, ok := field.(*core.RelationField) if !ok { return errors.New("owner field of collection " + collectionName + " is not a relation") } relation.Required = required if err := app.Save(collection); err != nil { return fmt.Errorf("failed to change owner requirement in %s: %w", collectionName, err) } return nil }