mirror of
https://github.com/fleetdm/fleet
synced 2026-05-24 09:28:54 +00:00
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #38536 This PR moves all logic to create new activities to activity bounded context. The old service and ActivityModule methods are not facades that route to the new activity bounded context. The facades will be removed in a subsequent PR. # Checklist for submitter - [x] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. ## Testing - [x] Added/updated automated tests - [x] QA'd all new/changed functionality manually <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added webhook support for activity events with configurable endpoint and enable/disable settings. * Enhanced automation-initiated activity creation without requiring a user context. * Improved activity service architecture with centralized creation and management. * **Improvements** * Refactored activity creation to use a dedicated service layer for better separation of concerns. * Added support for host-specific and automation-originated activities. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
115 lines
3.4 KiB
Go
115 lines
3.4 KiB
Go
// Package activityacl provides the anti-corruption layer between the activity
|
|
// bounded context and legacy Fleet code.
|
|
//
|
|
// This package is the ONLY place that imports both activity types and fleet types.
|
|
// It translates between them, allowing the activity context to remain decoupled
|
|
// from legacy code.
|
|
package activityacl
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/fleetdm/fleet/v4/server/activity"
|
|
"github.com/fleetdm/fleet/v4/server/fleet"
|
|
)
|
|
|
|
// FleetServiceAdapter provides access to Fleet service methods
|
|
// for data that the activity bounded context doesn't own.
|
|
type FleetServiceAdapter struct {
|
|
svc fleet.ActivityLookupService
|
|
}
|
|
|
|
// NewFleetServiceAdapter creates a new adapter for the Fleet service.
|
|
func NewFleetServiceAdapter(svc fleet.ActivityLookupService) *FleetServiceAdapter {
|
|
return &FleetServiceAdapter{svc: svc}
|
|
}
|
|
|
|
// Ensure FleetServiceAdapter implements the required interfaces
|
|
var (
|
|
_ activity.UserProvider = (*FleetServiceAdapter)(nil)
|
|
_ activity.HostProvider = (*FleetServiceAdapter)(nil)
|
|
_ activity.AppConfigProvider = (*FleetServiceAdapter)(nil)
|
|
_ activity.UpcomingActivityActivator = (*FleetServiceAdapter)(nil)
|
|
)
|
|
|
|
// UsersByIDs fetches users by their IDs from the Fleet service.
|
|
func (a *FleetServiceAdapter) UsersByIDs(ctx context.Context, ids []uint) ([]*activity.User, error) {
|
|
if len(ids) == 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
// Fetch only the requested users by their IDs
|
|
users, err := a.svc.UsersByIDs(ctx, ids)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Convert to activity.User
|
|
result := make([]*activity.User, 0, len(users))
|
|
for _, u := range users {
|
|
result = append(result, convertUser(u))
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
// FindUserIDs searches for users by name/email prefix and returns their IDs.
|
|
func (a *FleetServiceAdapter) FindUserIDs(ctx context.Context, query string) ([]uint, error) {
|
|
if query == "" {
|
|
return nil, nil
|
|
}
|
|
|
|
// Search users via Fleet service with the query
|
|
users, err := a.svc.ListUsers(ctx, fleet.UserListOptions{
|
|
ListOptions: fleet.ListOptions{
|
|
MatchQuery: query,
|
|
},
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
ids := make([]uint, 0, len(users))
|
|
for _, u := range users {
|
|
ids = append(ids, u.ID)
|
|
}
|
|
return ids, nil
|
|
}
|
|
|
|
// GetHostLite fetches minimal host information for authorization.
|
|
func (a *FleetServiceAdapter) GetHostLite(ctx context.Context, hostID uint) (*activity.Host, error) {
|
|
host, err := a.svc.GetHostLite(ctx, hostID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &activity.Host{
|
|
ID: host.ID,
|
|
TeamID: host.TeamID,
|
|
}, nil
|
|
}
|
|
|
|
func convertUser(u *fleet.UserSummary) *activity.User {
|
|
return &activity.User{
|
|
ID: u.ID,
|
|
Name: u.Name,
|
|
Email: u.Email,
|
|
Gravatar: u.GravatarURL,
|
|
APIOnly: u.APIOnly,
|
|
}
|
|
}
|
|
|
|
// GetActivitiesWebhookConfig returns the webhook configuration for activities.
|
|
func (a *FleetServiceAdapter) GetActivitiesWebhookConfig(ctx context.Context) (*activity.ActivitiesWebhookSettings, error) {
|
|
settings, err := a.svc.GetActivitiesWebhookSettings(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &activity.ActivitiesWebhookSettings{
|
|
Enable: settings.Enable,
|
|
DestinationURL: settings.DestinationURL,
|
|
}, nil
|
|
}
|
|
|
|
// ActivateNextUpcomingActivity activates the next upcoming activity in the queue.
|
|
func (a *FleetServiceAdapter) ActivateNextUpcomingActivity(ctx context.Context, hostID uint, fromCompletedExecID string) error {
|
|
return a.svc.ActivateNextUpcomingActivityForHost(ctx, hostID, fromCompletedExecID)
|
|
}
|