package repository import ( "context" "gorm.io/gorm" "github.com/gochat/gochat/internal/model" ) // PermissibleRepo provides data access for Permissible (polymorphic permission records). // Reference: Chatwoot PlatformAppPermissible + P2B M12 spec // // Each Permissible record means "PlatformApp X can operate on Resource Y". // Resource types (PermissibleType) include: Account, User, AgentBot. type PermissibleRepo struct { db *gorm.DB } // NewPermissibleRepo creates a new Permissible repository. func NewPermissibleRepo(db *gorm.DB) *PermissibleRepo { return &PermissibleRepo{db: db} } // Create inserts a new Permissible record. func (r *PermissibleRepo) Create(ctx context.Context, permissible *model.Permissible) error { return r.db.WithContext(ctx).Create(permissible).Error } // GetByID retrieves a Permissible by primary key. func (r *PermissibleRepo) GetByID(ctx context.Context, id uint) (*model.Permissible, error) { var permissible model.Permissible if err := r.db.WithContext(ctx).First(&permissible, id).Error; err != nil { return nil, err } return &permissible, nil } // FindByPlatformAppID retrieves all Permissible records for a given PlatformApp. // Returns all permissions granted to a specific platform app. func (r *PermissibleRepo) FindByPlatformAppID(ctx context.Context, platformAppID uint) ([]model.Permissible, error) { var permissibles []model.Permissible if err := r.db.WithContext(ctx). Where("platform_app_id = ?", platformAppID). Find(&permissibles).Error; err != nil { return nil, err } return permissibles, nil } // FindByResource retrieves all Permissible records for a given resource (polymorphic). // Returns which platform apps can access a specific resource (e.g. "which apps can access Account X"). func (r *PermissibleRepo) FindByResource(ctx context.Context, permissibleType string, permissibleID uint) ([]model.Permissible, error) { var permissibles []model.Permissible if err := r.db.WithContext(ctx). Where("permissible_type = ? AND permissible_id = ?", permissibleType, permissibleID). Find(&permissibles).Error; err != nil { return nil, err } return permissibles, nil } // FindByPlatformAppAndResource checks if a specific PlatformApp has permission on a specific resource. // Returns the Permissible record if it exists, or nil if no permission is granted. func (r *PermissibleRepo) FindByPlatformAppAndResource(ctx context.Context, platformAppID uint, permissibleType string, permissibleID uint) (*model.Permissible, error) { var permissible model.Permissible if err := r.db.WithContext(ctx). Where("platform_app_id = ? AND permissible_type = ? AND permissible_id = ?", platformAppID, permissibleType, permissibleID). First(&permissible).Error; err != nil { return nil, err } return &permissible, nil } // Delete removes a Permissible record by primary key (hard delete — no soft delete on Permissible). func (r *PermissibleRepo) Delete(ctx context.Context, id uint) error { return r.db.WithContext(ctx).Delete(&model.Permissible{}, id).Error } // DeleteByPlatformAppAndResource removes a specific permission for a PlatformApp on a resource. func (r *PermissibleRepo) DeleteByPlatformAppAndResource(ctx context.Context, platformAppID uint, permissibleType string, permissibleID uint) error { return r.db.WithContext(ctx). Where("platform_app_id = ? AND permissible_type = ? AND permissible_id = ?", platformAppID, permissibleType, permissibleID). Delete(&model.Permissible{}).Error } // DeleteByPlatformAppID removes all Permissible records for a given PlatformApp. // Used for cleanup when a PlatformApp is deleted. func (r *PermissibleRepo) DeleteByPlatformAppID(ctx context.Context, platformAppID uint) error { return r.db.WithContext(ctx). Where("platform_app_id = ?", platformAppID). Delete(&model.Permissible{}).Error }