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
|
// File is Winter's system_files row. AttachmentID is a string because
|
||||||
// Winter stores the morph FK as a string, never an integer.
|
// Winter stores the morph FK as a string, never an integer.
|
||||||
type File struct {
|
type File struct {
|
||||||
ID uint `gorm:"column:id;primaryKey"`
|
ID uint `gorm:"column:id;primaryKey"`
|
||||||
DiskName string `gorm:"column:disk_name"`
|
DiskName string `gorm:"column:disk_name"`
|
||||||
FileName string `gorm:"column:file_name"`
|
FileName string `gorm:"column:file_name"`
|
||||||
FileSize int64 `gorm:"column:file_size"`
|
FileSize int64 `gorm:"column:file_size"`
|
||||||
ContentType string `gorm:"column:content_type"`
|
ContentType string `gorm:"column:content_type"`
|
||||||
Title *string `gorm:"column:title"`
|
Title *string `gorm:"column:title"`
|
||||||
Description *string `gorm:"column:description"`
|
Description *string `gorm:"column:description"`
|
||||||
Field string `gorm:"column:field"`
|
Field string `gorm:"column:field"`
|
||||||
AttachmentID string `gorm:"column:attachment_id"`
|
AttachmentID string `gorm:"column:attachment_id"`
|
||||||
AttachmentType string `gorm:"column:attachment_type"`
|
AttachmentType string `gorm:"column:attachment_type"`
|
||||||
IsPublic bool `gorm:"column:is_public"`
|
// Pointer so GORM can distinguish unset (nil → DEFAULT TRUE) from
|
||||||
SortOrder int `gorm:"column:sort_order"`
|
// explicit false. A non-pointer bool with default:true cannot persist
|
||||||
Metadata *string `gorm:"column:metadata"`
|
// false because false is the zero value GORM replaces with the default.
|
||||||
CreatedAt time.Time `gorm:"column:created_at"`
|
IsPublic *bool `gorm:"column:is_public;not null;default:true"`
|
||||||
UpdatedAt time.Time `gorm:"column:updated_at"`
|
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" }
|
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
|
var all []any
|
||||||
|
|
||||||
// Register appends models so schema tooling can see File without a plugin registry.
|
// Register appends models so schema tooling can see File without a plugin registry.
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package attach
|
package attach
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"gocloud.dev/blob/memblob"
|
"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) {
|
func TestFileSelfRegisters(t *testing.T) {
|
||||||
for _, m := range All() {
|
for _, m := range All() {
|
||||||
switch m.(type) {
|
switch m.(type) {
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ CREATE TABLE attach_lifecycle_owners (
|
|||||||
if err := gdb.Create(&owner).Error; err != nil {
|
if err := gdb.Create(&owner).Error; err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
isPublic := true
|
||||||
file := attach.File{
|
file := attach.File{
|
||||||
DiskName: "abc123xyz.jpg",
|
DiskName: "abc123xyz.jpg",
|
||||||
FileName: "cover.jpg",
|
FileName: "cover.jpg",
|
||||||
@@ -63,7 +64,7 @@ CREATE TABLE attach_lifecycle_owners (
|
|||||||
Field: "photos",
|
Field: "photos",
|
||||||
AttachmentID: strconv.FormatUint(uint64(owner.ID), 10),
|
AttachmentID: strconv.FormatUint(uint64(owner.ID), 10),
|
||||||
AttachmentType: owner.MorphName(),
|
AttachmentType: owner.MorphName(),
|
||||||
IsPublic: true,
|
IsPublic: &isPublic,
|
||||||
}
|
}
|
||||||
if err := gdb.Create(&file).Error; err != nil {
|
if err := gdb.Create(&file).Error; err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -139,6 +140,51 @@ CREATE TABLE attach_lifecycle_owners (
|
|||||||
assertBlob(t, ctx, bucket, thumbKey, false)
|
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) {
|
func assertFileRow(t *testing.T, gdb *gorm.DB, id uint, want bool) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
var n int64
|
var n int64
|
||||||
|
|||||||
Reference in New Issue
Block a user