package models import ( "database/sql" "github.com/google/uuid" "gorm.io/gorm" ) func (m *SenlinAgentUser) BeforeCreate(tx *gorm.DB) error { return ensureIdentity(&m.Identity) } func (m *SenlinAgentProject) BeforeCreate(tx *gorm.DB) error { if err := ensureIdentity(&m.Identity); err != nil { return err } return resolveIdentity(tx, &SenlinAgentUser{}, m.OwnerID, &m.OwnerIdentity) } func (m *SenlinAgentInboxItem) BeforeCreate(tx *gorm.DB) error { if err := ensureIdentity(&m.Identity); err != nil { return err } if err := resolveIdentity(tx, &SenlinAgentProject{}, m.ProjectID, &m.ProjectIdentity); err != nil { return err } return resolveIdentity(tx, &SenlinAgentUser{}, m.CreatedBy, &m.CreatedByIdentity) } func (m *SenlinAgentInboxSuggestion) BeforeCreate(tx *gorm.DB) error { if err := ensureIdentity(&m.Identity); err != nil { return err } if err := resolveIdentity(tx, &SenlinAgentInboxItem{}, m.InboxItemID, &m.InboxItemIdentity); err != nil { return err } return resolveIdentity(tx, &SenlinAgentUser{}, m.CreatedBy, &m.CreatedByIdentity) } func (m *SenlinAgentTask) BeforeCreate(tx *gorm.DB) error { if err := ensureIdentity(&m.Identity); err != nil { return err } if err := resolveIdentity(tx, &SenlinAgentProject{}, m.ProjectID, &m.ProjectIdentity); err != nil { return err } if err := resolveIdentity(tx, &SenlinAgentUser{}, m.CreatedBy, &m.CreatedByIdentity); err != nil { return err } if err := resolveOptionalIdentity(tx, &SenlinAgentUser{}, m.AssigneeID, &m.AssigneeIdentity); err != nil { return err } if err := resolveOptionalIdentity(tx, &SenlinAgentTag{}, m.TagID, &m.TagIdentity); err != nil { return err } return resolveOptionalIdentity(tx, &SenlinAgentInboxItem{}, m.SourceInboxItemID, &m.SourceInboxItemIdentity) } func (m *SenlinAgentNote) BeforeCreate(tx *gorm.DB) error { if err := ensureIdentity(&m.Identity); err != nil { return err } if err := resolveIdentity(tx, &SenlinAgentProject{}, m.ProjectID, &m.ProjectIdentity); err != nil { return err } if err := resolveIdentity(tx, &SenlinAgentUser{}, m.CreatedBy, &m.CreatedByIdentity); err != nil { return err } return resolveOptionalIdentity(tx, &SenlinAgentInboxItem{}, m.SourceInboxItemID, &m.SourceInboxItemIdentity) } func (m *SenlinAgentSource) BeforeCreate(tx *gorm.DB) error { if err := ensureIdentity(&m.Identity); err != nil { return err } if err := resolveIdentity(tx, &SenlinAgentProject{}, m.ProjectID, &m.ProjectIdentity); err != nil { return err } if err := resolveIdentity(tx, &SenlinAgentUser{}, m.CreatedBy, &m.CreatedByIdentity); err != nil { return err } return resolveOptionalIdentity(tx, &SenlinAgentInboxItem{}, m.SourceInboxItemID, &m.SourceInboxItemIdentity) } func (m *SenlinAgentAISession) BeforeCreate(tx *gorm.DB) error { if err := ensureIdentity(&m.Identity); err != nil { return err } if err := resolveIdentity(tx, &SenlinAgentProject{}, m.ProjectID, &m.ProjectIdentity); err != nil { return err } if err := resolveIdentity(tx, &SenlinAgentUser{}, m.CreatedBy, &m.CreatedByIdentity); err != nil { return err } return resolveOptionalIdentity(tx, &SenlinAgentAIExpert{}, m.ExpertID, &m.ExpertIdentity) } func (m *SenlinAgentAIExpertCategory) BeforeCreate(_ *gorm.DB) error { return ensureIdentity(&m.Identity) } func (m *SenlinAgentAIExpert) BeforeCreate(tx *gorm.DB) error { if err := ensureIdentity(&m.Identity); err != nil { return err } return resolveIdentity(tx, &SenlinAgentAIExpertCategory{}, m.CategoryID, &m.CategoryIdentity) } func (m *SenlinAgentTag) BeforeCreate(tx *gorm.DB) error { if err := ensureIdentity(&m.Identity); err != nil { return err } return resolveIdentity(tx, &SenlinAgentProject{}, m.ProjectID, &m.ProjectIdentity) } func (m *SenlinAgentProjectChannel) BeforeCreate(tx *gorm.DB) error { if err := ensureIdentity(&m.Identity); err != nil { return err } return resolveIdentity(tx, &SenlinAgentProject{}, m.ProjectID, &m.ProjectIdentity) } func (m *SenlinAgentCronPlan) BeforeCreate(tx *gorm.DB) error { if err := ensureIdentity(&m.Identity); err != nil { return err } if err := resolveIdentity(tx, &SenlinAgentProject{}, m.ProjectID, &m.ProjectIdentity); err != nil { return err } return resolveIdentity(tx, &SenlinAgentUser{}, m.CreatedBy, &m.CreatedByIdentity) } func (m *SenlinAgentProjectEvent) BeforeCreate(tx *gorm.DB) error { if err := ensureIdentity(&m.Identity); err != nil { return err } if err := resolveIdentity(tx, &SenlinAgentProject{}, m.ProjectID, &m.ProjectIdentity); err != nil { return err } if err := resolveIdentity(tx, &SenlinAgentUser{}, m.ActorID, &m.ActorIdentity); err != nil { return err } return resolveEntityIdentity(tx, m.EntityType, m.EntityID, &m.EntityIdentity) } func (m *SenlinAgentAIKey) BeforeCreate(tx *gorm.DB) error { if err := ensureIdentity(&m.Identity); err != nil { return err } return resolveIdentity(tx, &SenlinAgentUser{}, m.UserID, &m.UserIdentity) } func (m *SenlinAgentAICallLog) BeforeCreate(tx *gorm.DB) error { if err := ensureIdentity(&m.Identity); err != nil { return err } return resolveIdentity(tx, &SenlinAgentUser{}, m.UserID, &m.UserIdentity) } func (m *SenlinAgentTaskShare) BeforeCreate(tx *gorm.DB) error { if err := ensureIdentity(&m.Identity); err != nil { return err } if err := resolveIdentity(tx, &SenlinAgentTask{}, m.TaskID, &m.TaskIdentity); err != nil { return err } return resolveEntityIdentity(tx, m.ObjectType, m.ObjectID, &m.ObjectIdentity) } func ensureIdentity(identity *string) error { if *identity != "" { return nil } next, err := uuidV7() if err != nil { return err } *identity = next return nil } func resolveIdentity(tx *gorm.DB, model any, id uint, identity *string) error { if id == 0 || *identity != "" { return nil } resolved, err := lookupIdentity(tx, model, id) if err != nil { return err } *identity = resolved return nil } func resolveOptionalIdentity(tx *gorm.DB, model any, id *uint, identity **string) error { if id == nil || *id == 0 || (identity != nil && *identity != nil && **identity != "") { return nil } resolved, err := lookupIdentity(tx, model, *id) if err != nil { return err } *identity = &resolved return nil } func resolveEntityIdentity(tx *gorm.DB, entityType string, entityID uint, identity *string) error { if entityID == 0 || *identity != "" { return nil } switch entityType { case "project": return resolveIdentity(tx, &SenlinAgentProject{}, entityID, identity) case "inbox", "inbox_item": return resolveIdentity(tx, &SenlinAgentInboxItem{}, entityID, identity) case "task": return resolveIdentity(tx, &SenlinAgentTask{}, entityID, identity) case "note": return resolveIdentity(tx, &SenlinAgentNote{}, entityID, identity) case "source": return resolveIdentity(tx, &SenlinAgentSource{}, entityID, identity) case "ai_session": return resolveIdentity(tx, &SenlinAgentAISession{}, entityID, identity) case "tag": return resolveIdentity(tx, &SenlinAgentTag{}, entityID, identity) default: return nil } } func lookupIdentity(tx *gorm.DB, model any, id uint) (string, error) { var identity string err := tx.Model(model).Select("identity").Where("id = ?", id).Row().Scan(&identity) if err == sql.ErrNoRows { return "", nil } return identity, err } func uuidV7() (string, error) { next, err := uuid.NewV7() if err != nil { return "", err } return next.String(), nil }