fix(05): WR-04 default File.IsPublic to true without trapping false
This commit is contained in:
@@ -22,25 +22,37 @@ type Owner interface {
|
||||
// File is Winter's system_files row. AttachmentID is a string because
|
||||
// Winter stores the morph FK as a string, never an integer.
|
||||
type File struct {
|
||||
ID uint `gorm:"column:id;primaryKey"`
|
||||
DiskName string `gorm:"column:disk_name"`
|
||||
FileName string `gorm:"column:file_name"`
|
||||
FileSize int64 `gorm:"column:file_size"`
|
||||
ContentType string `gorm:"column:content_type"`
|
||||
Title *string `gorm:"column:title"`
|
||||
Description *string `gorm:"column:description"`
|
||||
Field string `gorm:"column:field"`
|
||||
AttachmentID string `gorm:"column:attachment_id"`
|
||||
AttachmentType string `gorm:"column:attachment_type"`
|
||||
IsPublic bool `gorm:"column:is_public"`
|
||||
SortOrder int `gorm:"column:sort_order"`
|
||||
Metadata *string `gorm:"column:metadata"`
|
||||
CreatedAt time.Time `gorm:"column:created_at"`
|
||||
UpdatedAt time.Time `gorm:"column:updated_at"`
|
||||
ID uint `gorm:"column:id;primaryKey"`
|
||||
DiskName string `gorm:"column:disk_name"`
|
||||
FileName string `gorm:"column:file_name"`
|
||||
FileSize int64 `gorm:"column:file_size"`
|
||||
ContentType string `gorm:"column:content_type"`
|
||||
Title *string `gorm:"column:title"`
|
||||
Description *string `gorm:"column:description"`
|
||||
Field string `gorm:"column:field"`
|
||||
AttachmentID string `gorm:"column:attachment_id"`
|
||||
AttachmentType string `gorm:"column:attachment_type"`
|
||||
// Pointer so GORM can distinguish unset (nil → DEFAULT TRUE) from
|
||||
// explicit false. A non-pointer bool with default:true cannot persist
|
||||
// false because false is the zero value GORM replaces with the default.
|
||||
IsPublic *bool `gorm:"column:is_public;not null;default:true"`
|
||||
SortOrder int `gorm:"column:sort_order"`
|
||||
Metadata *string `gorm:"column:metadata"`
|
||||
CreatedAt time.Time `gorm:"column:created_at"`
|
||||
UpdatedAt time.Time `gorm:"column:updated_at"`
|
||||
}
|
||||
|
||||
func (File) TableName() string { return "system_files" }
|
||||
|
||||
// Public reports Winter's is_public flag. A nil pointer is treated as true,
|
||||
// matching the SQL DEFAULT TRUE and File::create() behaviour.
|
||||
func (f File) Public() bool {
|
||||
if f.IsPublic == nil {
|
||||
return true
|
||||
}
|
||||
return *f.IsPublic
|
||||
}
|
||||
|
||||
var all []any
|
||||
|
||||
// Register appends models so schema tooling can see File without a plugin registry.
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package attach
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"gocloud.dev/blob/memblob"
|
||||
@@ -12,6 +14,29 @@ func TestFileTableName(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileIsPublicDefaultsTrue(t *testing.T) {
|
||||
unset := File{}
|
||||
if !unset.Public() {
|
||||
t.Fatal("unset IsPublic must be public")
|
||||
}
|
||||
f, ok := reflect.TypeOf(File{}).FieldByName("IsPublic")
|
||||
if !ok {
|
||||
t.Fatal("missing IsPublic")
|
||||
}
|
||||
tag := f.Tag.Get("gorm")
|
||||
if !strings.Contains(tag, "default:true") {
|
||||
t.Fatalf("gorm tag = %q, want default:true", tag)
|
||||
}
|
||||
priv := false
|
||||
if (File{IsPublic: &priv}).Public() {
|
||||
t.Fatal("explicit false must not be public")
|
||||
}
|
||||
pub := true
|
||||
if !(File{IsPublic: &pub}).Public() {
|
||||
t.Fatal("explicit true must be public")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileSelfRegisters(t *testing.T) {
|
||||
for _, m := range All() {
|
||||
switch m.(type) {
|
||||
|
||||
@@ -55,6 +55,7 @@ CREATE TABLE attach_lifecycle_owners (
|
||||
if err := gdb.Create(&owner).Error; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
isPublic := true
|
||||
file := attach.File{
|
||||
DiskName: "abc123xyz.jpg",
|
||||
FileName: "cover.jpg",
|
||||
@@ -63,7 +64,7 @@ CREATE TABLE attach_lifecycle_owners (
|
||||
Field: "photos",
|
||||
AttachmentID: strconv.FormatUint(uint64(owner.ID), 10),
|
||||
AttachmentType: owner.MorphName(),
|
||||
IsPublic: true,
|
||||
IsPublic: &isPublic,
|
||||
}
|
||||
if err := gdb.Create(&file).Error; err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -139,6 +140,51 @@ CREATE TABLE attach_lifecycle_owners (
|
||||
assertBlob(t, ctx, bucket, thumbKey, false)
|
||||
}
|
||||
|
||||
func TestFileCreateDefaultsIsPublic(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("requires testcontainers postgres")
|
||||
}
|
||||
gdb := attachGorm(t)
|
||||
if err := lagoon.Migrate(gdb, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
file := attach.File{
|
||||
DiskName: "abc123xyz.jpg",
|
||||
FileName: "cover.jpg",
|
||||
FileSize: 1,
|
||||
ContentType: "image/jpeg",
|
||||
}
|
||||
if err := gdb.Create(&file).Error; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var got attach.File
|
||||
if err := gdb.First(&got, file.ID).Error; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !got.Public() {
|
||||
t.Fatalf("Create without IsPublic stored %v, want true", got.IsPublic)
|
||||
}
|
||||
|
||||
priv := false
|
||||
hidden := attach.File{
|
||||
DiskName: "def456uvw.jpg",
|
||||
FileName: "secret.jpg",
|
||||
FileSize: 1,
|
||||
ContentType: "image/jpeg",
|
||||
IsPublic: &priv,
|
||||
}
|
||||
if err := gdb.Create(&hidden).Error; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var gotHidden attach.File
|
||||
if err := gdb.First(&gotHidden, hidden.ID).Error; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if gotHidden.Public() {
|
||||
t.Fatal("explicit is_public=false must persist")
|
||||
}
|
||||
}
|
||||
|
||||
func assertFileRow(t *testing.T, gdb *gorm.DB, id uint, want bool) {
|
||||
t.Helper()
|
||||
var n int64
|
||||
|
||||
Reference in New Issue
Block a user