feat(model): add Status field and constants to User and File
Add Status field (gorm, indexed, default active) to both User and File models. Add User status constants: StatusActive, StatusAdminDeleted. Add File status constant: StatusUserDeleted. Add tests verifying Status field is excluded from JSON serialization. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -4,6 +4,9 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// StatusUserDeleted marks a file that has been deleted by the user (soft delete).
|
||||||
|
const StatusUserDeleted = "user_deleted"
|
||||||
|
|
||||||
// File represents a file or directory entry in the virtual filesystem.
|
// File represents a file or directory entry in the virtual filesystem.
|
||||||
type File struct {
|
type File struct {
|
||||||
ID string `gorm:"primaryKey;type:varchar(36)" json:"id"`
|
ID string `gorm:"primaryKey;type:varchar(36)" json:"id"`
|
||||||
@@ -14,6 +17,7 @@ type File struct {
|
|||||||
MimeType string `gorm:"type:varchar(127)" json:"mime_type"`
|
MimeType string `gorm:"type:varchar(127)" json:"mime_type"`
|
||||||
StoragePath string `gorm:"type:varchar(512)" json:"storage_path"`
|
StoragePath string `gorm:"type:varchar(512)" json:"storage_path"`
|
||||||
Hash string `gorm:"type:varchar(64)" json:"-"`
|
Hash string `gorm:"type:varchar(64)" json:"-"`
|
||||||
|
Status string `gorm:"type:varchar(32);not null;default:active;index" json:"-"`
|
||||||
IsDir bool `gorm:"default:false" json:"is_dir"`
|
IsDir bool `gorm:"default:false" json:"is_dir"`
|
||||||
CreatedAt time.Time `json:"created_at"`
|
CreatedAt time.Time `json:"created_at"`
|
||||||
UpdatedAt time.Time `json:"updated_at"`
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFile_StatusExcludedFromJSON(t *testing.T) {
|
||||||
|
f := &File{
|
||||||
|
ID: "1",
|
||||||
|
UserID: "u1",
|
||||||
|
ParentID: nil,
|
||||||
|
Name: "test.txt",
|
||||||
|
Size: 100,
|
||||||
|
MimeType: "text/plain",
|
||||||
|
Status: StatusActive,
|
||||||
|
IsDir: false,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := json.Marshal(f)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("json.Marshal: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var result map[string]any
|
||||||
|
if err := json.Unmarshal(data, &result); err != nil {
|
||||||
|
t.Fatalf("json.Unmarshal: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := result["status"]; ok {
|
||||||
|
t.Errorf("Status field should be excluded from JSON (json:\"-\"), but it appeared in output")
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := result["hash"]; ok {
|
||||||
|
t.Errorf("Hash field should be excluded from JSON (json:\"-\"), but it appeared in output")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStatusConstants(t *testing.T) {
|
||||||
|
if StatusActive != "active" {
|
||||||
|
t.Errorf("StatusActive = %q, want \"active\"", StatusActive)
|
||||||
|
}
|
||||||
|
if StatusUserDeleted != "user_deleted" {
|
||||||
|
t.Errorf("StatusUserDeleted = %q, want \"user_deleted\"", StatusUserDeleted)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,6 +11,13 @@ type User struct {
|
|||||||
Email string `gorm:"uniqueIndex;type:varchar(255);not null" json:"email"`
|
Email string `gorm:"uniqueIndex;type:varchar(255);not null" json:"email"`
|
||||||
PasswordHash string `gorm:"type:varchar(255);not null" json:"-"`
|
PasswordHash string `gorm:"type:varchar(255);not null" json:"-"`
|
||||||
IsAdmin bool `gorm:"default:false" json:"is_admin"`
|
IsAdmin bool `gorm:"default:false" json:"is_admin"`
|
||||||
|
Status string `gorm:"type:varchar(32);not null;default:active;index" json:"-"`
|
||||||
CreatedAt time.Time `json:"created_at"`
|
CreatedAt time.Time `json:"created_at"`
|
||||||
UpdatedAt time.Time `json:"updated_at"`
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// User status constants.
|
||||||
|
const (
|
||||||
|
StatusActive = "active"
|
||||||
|
StatusAdminDeleted = "admin_deleted"
|
||||||
|
)
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestUserJSONOmitsStatusField(t *testing.T) {
|
||||||
|
u := User{
|
||||||
|
ID: "user-1",
|
||||||
|
Username: "alice",
|
||||||
|
Email: "alice@example.com",
|
||||||
|
Status: StatusActive,
|
||||||
|
}
|
||||||
|
|
||||||
|
raw, err := json.Marshal(u)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("json.Marshal: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var m map[string]interface{}
|
||||||
|
if err := json.Unmarshal(raw, &m); err != nil {
|
||||||
|
t.Fatalf("json.Unmarshal: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := m["status"]; ok {
|
||||||
|
t.Error("Status field should not appear in JSON output")
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user