From af42a0850eba7673e7f8572b1ab8dc45efc2a724 Mon Sep 17 00:00:00 2001 From: Martin Angers Date: Wed, 15 Dec 2021 09:06:34 -0500 Subject: [PATCH] Migrate global scheduled queries endpoints to new pattern (#3235) --- server/datastore/mysql/scheduled_queries.go | 3 + server/service/endpoint_global_schedule.go | 136 ------------- server/service/endpoint_utils.go | 18 +- server/service/global_schedule.go | 178 ++++++++++++++++++ ...hedule_test.go => global_schedule_test.go} | 21 +++ server/service/handler.go | 26 +-- server/service/integration_core_test.go | 20 ++ server/service/service_global_schedule.go | 62 ------ server/service/transport_global_schedule.go | 52 ----- 9 files changed, 239 insertions(+), 277 deletions(-) delete mode 100644 server/service/endpoint_global_schedule.go create mode 100644 server/service/global_schedule.go rename server/service/{service_global_schedule_test.go => global_schedule_test.go} (66%) delete mode 100644 server/service/service_global_schedule.go delete mode 100644 server/service/transport_global_schedule.go diff --git a/server/datastore/mysql/scheduled_queries.go b/server/datastore/mysql/scheduled_queries.go index d573ce30cb..5ab5552210 100644 --- a/server/datastore/mysql/scheduled_queries.go +++ b/server/datastore/mysql/scheduled_queries.go @@ -157,6 +157,9 @@ func (d *Datastore) ScheduledQuery(ctx context.Context, id uint) (*fleet.Schedul ` sq := &fleet.ScheduledQuery{} if err := sqlx.GetContext(ctx, d.reader, sq, query, id); err != nil { + if err == sql.ErrNoRows { + return nil, ctxerr.Wrap(ctx, notFound("ScheduledQuery").WithID(id)) + } return nil, ctxerr.Wrap(ctx, err, "select scheduled query") } diff --git a/server/service/endpoint_global_schedule.go b/server/service/endpoint_global_schedule.go deleted file mode 100644 index 0575103a6b..0000000000 --- a/server/service/endpoint_global_schedule.go +++ /dev/null @@ -1,136 +0,0 @@ -package service - -import ( - "context" - - "github.com/fleetdm/fleet/v4/server/fleet" - "github.com/go-kit/kit/endpoint" -) - -//////////////////////////////////////////////////////////////////////////////// -// Get Global Schedule -//////////////////////////////////////////////////////////////////////////////// - -type getGlobalScheduleRequest struct { - ListOptions fleet.ListOptions -} - -type getGlobalScheduleResponse struct { - GlobalSchedule []*fleet.ScheduledQuery `json:"global_schedule"` - Err error `json:"error,omitempty"` -} - -func (r getGlobalScheduleResponse) error() error { return r.Err } - -func makeGetGlobalScheduleEndpoint(svc fleet.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(getGlobalScheduleRequest) - - gp, err := svc.GetGlobalScheduledQueries(ctx, req.ListOptions) - if err != nil { - return getGlobalScheduleResponse{Err: err}, nil - } - - return getGlobalScheduleResponse{ - GlobalSchedule: gp, - }, nil - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Modify Global Schedule -//////////////////////////////////////////////////////////////////////////////// - -type modifyGlobalScheduleRequest struct { - ID uint - payload fleet.ScheduledQueryPayload -} - -type modifyGlobalScheduleResponse struct { - Scheduled *fleet.ScheduledQuery `json:"scheduled,omitempty"` - Err error `json:"error,omitempty"` -} - -func (r modifyGlobalScheduleResponse) error() error { return r.Err } - -func makeModifyGlobalScheduleEndpoint(svc fleet.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(modifyGlobalScheduleRequest) - - sq, err := svc.ModifyGlobalScheduledQueries(ctx, req.ID, req.payload) - if err != nil { - return modifyGlobalScheduleResponse{Err: err}, nil - } - - return modifyGlobalScheduleResponse{ - Scheduled: sq, - }, nil - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Delete Global Schedule -//////////////////////////////////////////////////////////////////////////////// - -type deleteGlobalScheduleRequest struct { - ID uint -} - -type deleteGlobalScheduleResponse struct { - Err error `json:"error,omitempty"` -} - -func (r deleteGlobalScheduleResponse) error() error { return r.Err } - -func makeDeleteGlobalScheduleEndpoint(svc fleet.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(deleteGlobalScheduleRequest) - err := svc.DeleteGlobalScheduledQueries(ctx, req.ID) - if err != nil { - return deleteGlobalScheduleResponse{Err: err}, nil - } - - return deleteGlobalScheduleResponse{}, nil - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Global Schedule Query -//////////////////////////////////////////////////////////////////////////////// - -type globalScheduleQueryRequest struct { - QueryID uint `json:"query_id"` - Interval uint `json:"interval"` - Snapshot *bool `json:"snapshot"` - Removed *bool `json:"removed"` - Platform *string `json:"platform"` - Version *string `json:"version"` - Shard *uint `json:"shard"` -} - -type globalScheduleQueryResponse struct { - Scheduled *fleet.ScheduledQuery `json:"scheduled,omitempty"` - Err error `json:"error,omitempty"` -} - -func (r globalScheduleQueryResponse) error() error { return r.Err } - -func makeGlobalScheduleQueryEndpoint(svc fleet.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(globalScheduleQueryRequest) - - scheduled, err := svc.GlobalScheduleQuery(ctx, &fleet.ScheduledQuery{ - QueryID: req.QueryID, - Interval: req.Interval, - Snapshot: req.Snapshot, - Removed: req.Removed, - Platform: req.Platform, - Version: req.Version, - Shard: req.Shard, - }) - if err != nil { - return globalScheduleQueryResponse{Err: err}, nil - } - return globalScheduleQueryResponse{Scheduled: scheduled}, nil - } -} diff --git a/server/service/endpoint_utils.go b/server/service/endpoint_utils.go index 407e04dff5..4d79d1270f 100644 --- a/server/service/endpoint_utils.go +++ b/server/service/endpoint_utils.go @@ -64,12 +64,18 @@ func allFields(ifv reflect.Value) []reflect.StructField { return fields } -// makeDecoder creates a decoder for the type for the struct passed on. If the struct has at least 1 json tag -// it'll unmarshall the body. If the struct has a `url` tag with value list-options it'll gather fleet.ListOptions -// from the URL. And finally, any other `url` tag will be treated as an ID from the URL path pattern, and it'll -// be decoded and set accordingly. -// IDs are expected to be uint, and can be optional by setting the tag as follows: `url:"some-id,optional"` -// list-options are optional by default and it'll ignore the optional portion of the tag. +// makeDecoder creates a decoder for the type for the struct passed on. If the +// struct has at least 1 json tag it'll unmarshall the body. If the struct has +// a `url` tag with value list_options it'll gather fleet.ListOptions from the +// URL (similarly for host_options, carve_options that derive from the common +// list_options). +// +// Finally, any other `url` tag will be treated as a path variable (of the form +// /path/{name} in the route's path) from the URL path pattern, and it'll be +// decoded and set accordingly. Variables can be optional by setting the tag as +// follows: `url:"some-id,optional"`. +// The "list_options" are optional by default and it'll ignore the optional +// portion of the tag. func makeDecoder(iface interface{}) kithttp.DecodeRequestFunc { if iface == nil { return func(ctx context.Context, r *http.Request) (interface{}, error) { diff --git a/server/service/global_schedule.go b/server/service/global_schedule.go new file mode 100644 index 0000000000..f220f5d6ba --- /dev/null +++ b/server/service/global_schedule.go @@ -0,0 +1,178 @@ +package service + +import ( + "context" + + "github.com/fleetdm/fleet/v4/server/fleet" + "github.com/fleetdm/fleet/v4/server/ptr" +) + +//////////////////////////////////////////////////////////////////////////////// +// Get Global Schedule +//////////////////////////////////////////////////////////////////////////////// + +type getGlobalScheduleRequest struct { + ListOptions fleet.ListOptions `url:"list_options"` +} + +type getGlobalScheduleResponse struct { + GlobalSchedule []*fleet.ScheduledQuery `json:"global_schedule"` + Err error `json:"error,omitempty"` +} + +func (r getGlobalScheduleResponse) error() error { return r.Err } + +func getGlobalScheduleEndpoint(ctx context.Context, request interface{}, svc fleet.Service) (interface{}, error) { + req := request.(*getGlobalScheduleRequest) + + gp, err := svc.GetGlobalScheduledQueries(ctx, req.ListOptions) + if err != nil { + return getGlobalScheduleResponse{Err: err}, nil + } + + return getGlobalScheduleResponse{ + GlobalSchedule: gp, + }, nil +} + +func (svc *Service) GetGlobalScheduledQueries(ctx context.Context, opts fleet.ListOptions) ([]*fleet.ScheduledQuery, error) { + if err := svc.authz.Authorize(ctx, &fleet.Pack{}, fleet.ActionRead); err != nil { + return nil, err + } + + gp, err := svc.ds.EnsureGlobalPack(ctx) + if err != nil { + return nil, err + } + + return svc.ds.ListScheduledQueriesInPack(ctx, gp.ID, opts) +} + +//////////////////////////////////////////////////////////////////////////////// +// Global Schedule Query +//////////////////////////////////////////////////////////////////////////////// + +type globalScheduleQueryRequest struct { + QueryID uint `json:"query_id"` + Interval uint `json:"interval"` + Snapshot *bool `json:"snapshot"` + Removed *bool `json:"removed"` + Platform *string `json:"platform"` + Version *string `json:"version"` + Shard *uint `json:"shard"` +} + +type globalScheduleQueryResponse struct { + Scheduled *fleet.ScheduledQuery `json:"scheduled,omitempty"` + Err error `json:"error,omitempty"` +} + +func (r globalScheduleQueryResponse) error() error { return r.Err } + +func globalScheduleQueryEndpoint(ctx context.Context, request interface{}, svc fleet.Service) (interface{}, error) { + req := request.(*globalScheduleQueryRequest) + + scheduled, err := svc.GlobalScheduleQuery(ctx, &fleet.ScheduledQuery{ + QueryID: req.QueryID, + Interval: req.Interval, + Snapshot: req.Snapshot, + Removed: req.Removed, + Platform: req.Platform, + Version: req.Version, + Shard: req.Shard, + }) + if err != nil { + return globalScheduleQueryResponse{Err: err}, nil + } + return globalScheduleQueryResponse{Scheduled: scheduled}, nil +} + +func (svc *Service) GlobalScheduleQuery(ctx context.Context, sq *fleet.ScheduledQuery) (*fleet.ScheduledQuery, error) { + if err := svc.authz.Authorize(ctx, &fleet.Pack{}, fleet.ActionRead); err != nil { + return nil, err + } + + gp, err := svc.ds.EnsureGlobalPack(ctx) + if err != nil { + return nil, err + } + sq.PackID = gp.ID + + return svc.ScheduleQuery(ctx, sq) +} + +//////////////////////////////////////////////////////////////////////////////// +// Modify Global Schedule +//////////////////////////////////////////////////////////////////////////////// + +type modifyGlobalScheduleRequest struct { + ID uint `json:"-" url:"id"` + fleet.ScheduledQueryPayload +} + +type modifyGlobalScheduleResponse struct { + Scheduled *fleet.ScheduledQuery `json:"scheduled,omitempty"` + Err error `json:"error,omitempty"` +} + +func (r modifyGlobalScheduleResponse) error() error { return r.Err } + +func modifyGlobalScheduleEndpoint(ctx context.Context, request interface{}, svc fleet.Service) (interface{}, error) { + req := request.(*modifyGlobalScheduleRequest) + + sq, err := svc.ModifyGlobalScheduledQueries(ctx, req.ID, req.ScheduledQueryPayload) + if err != nil { + return modifyGlobalScheduleResponse{Err: err}, nil + } + + return modifyGlobalScheduleResponse{ + Scheduled: sq, + }, nil +} + +func (svc *Service) ModifyGlobalScheduledQueries(ctx context.Context, id uint, query fleet.ScheduledQueryPayload) (*fleet.ScheduledQuery, error) { + if err := svc.authz.Authorize(ctx, &fleet.Pack{}, fleet.ActionWrite); err != nil { + return nil, err + } + + gp, err := svc.ds.EnsureGlobalPack(ctx) + if err != nil { + return nil, err + } + + query.PackID = ptr.Uint(gp.ID) + + return svc.ModifyScheduledQuery(ctx, id, query) +} + +//////////////////////////////////////////////////////////////////////////////// +// Delete Global Schedule +//////////////////////////////////////////////////////////////////////////////// + +type deleteGlobalScheduleRequest struct { + ID uint `url:"id"` +} + +type deleteGlobalScheduleResponse struct { + Err error `json:"error,omitempty"` +} + +func (r deleteGlobalScheduleResponse) error() error { return r.Err } + +func deleteGlobalScheduleEndpoint(ctx context.Context, request interface{}, svc fleet.Service) (interface{}, error) { + req := request.(*deleteGlobalScheduleRequest) + err := svc.DeleteGlobalScheduledQueries(ctx, req.ID) + if err != nil { + return deleteGlobalScheduleResponse{Err: err}, nil + } + + return deleteGlobalScheduleResponse{}, nil +} + +func (svc *Service) DeleteGlobalScheduledQueries(ctx context.Context, id uint) error { + if err := svc.authz.Authorize(ctx, &fleet.Pack{}, fleet.ActionWrite); err != nil { + return err + } + + return svc.DeleteScheduledQuery(ctx, id) +} diff --git a/server/service/service_global_schedule_test.go b/server/service/global_schedule_test.go similarity index 66% rename from server/service/service_global_schedule_test.go rename to server/service/global_schedule_test.go index ce6d92be11..149e75a030 100644 --- a/server/service/service_global_schedule_test.go +++ b/server/service/global_schedule_test.go @@ -20,6 +20,18 @@ func TestGlobalScheduleAuth(t *testing.T) { ds.EnsureGlobalPackFunc = func(ctx context.Context) (*fleet.Pack, error) { return &fleet.Pack{}, nil } + ds.NewScheduledQueryFunc = func(ctx context.Context, sq *fleet.ScheduledQuery, opts ...fleet.OptionalArg) (*fleet.ScheduledQuery, error) { + return sq, nil + } + ds.ScheduledQueryFunc = func(ctx context.Context, id uint) (*fleet.ScheduledQuery, error) { + return &fleet.ScheduledQuery{}, nil + } + ds.SaveScheduledQueryFunc = func(ctx context.Context, sq *fleet.ScheduledQuery) (*fleet.ScheduledQuery, error) { + return sq, nil + } + ds.DeleteScheduledQueryFunc = func(ctx context.Context, id uint) error { + return nil + } var testCases = []struct { name string @@ -70,6 +82,15 @@ func TestGlobalScheduleAuth(t *testing.T) { _, err := svc.GetGlobalScheduledQueries(ctx, fleet.ListOptions{}) checkAuthErr(t, tt.shouldFailRead, err) + + _, err = svc.GlobalScheduleQuery(ctx, &fleet.ScheduledQuery{Name: "query", QueryName: "query"}) + checkAuthErr(t, tt.shouldFailWrite, err) + + _, err = svc.ModifyGlobalScheduledQueries(ctx, 1, fleet.ScheduledQueryPayload{}) + checkAuthErr(t, tt.shouldFailWrite, err) + + err = svc.DeleteGlobalScheduledQueries(ctx, 1) + checkAuthErr(t, tt.shouldFailWrite, err) }) } } diff --git a/server/service/handler.go b/server/service/handler.go index a87c8dcc9d..4856c92e8a 100644 --- a/server/service/handler.go +++ b/server/service/handler.go @@ -73,10 +73,6 @@ type FleetEndpoints struct { ApplyPackSpecs endpoint.Endpoint GetPackSpecs endpoint.Endpoint GetPackSpec endpoint.Endpoint - GlobalScheduleQuery endpoint.Endpoint - GetGlobalSchedule endpoint.Endpoint - ModifyGlobalSchedule endpoint.Endpoint - DeleteGlobalSchedule endpoint.Endpoint EnrollAgent endpoint.Endpoint GetClientConfig endpoint.Endpoint GetDistributedQueries endpoint.Endpoint @@ -184,10 +180,6 @@ func MakeFleetServerEndpoints(svc fleet.Service, urlPrefix string, limitStore th ApplyPackSpecs: authenticatedUser(svc, makeApplyPackSpecsEndpoint(svc)), GetPackSpecs: authenticatedUser(svc, makeGetPackSpecsEndpoint(svc)), GetPackSpec: authenticatedUser(svc, makeGetPackSpecEndpoint(svc)), - GlobalScheduleQuery: authenticatedUser(svc, makeGlobalScheduleQueryEndpoint(svc)), - GetGlobalSchedule: authenticatedUser(svc, makeGetGlobalScheduleEndpoint(svc)), - ModifyGlobalSchedule: authenticatedUser(svc, makeModifyGlobalScheduleEndpoint(svc)), - DeleteGlobalSchedule: authenticatedUser(svc, makeDeleteGlobalScheduleEndpoint(svc)), CreateLabel: authenticatedUser(svc, makeCreateLabelEndpoint(svc)), ModifyLabel: authenticatedUser(svc, makeModifyLabelEndpoint(svc)), GetLabel: authenticatedUser(svc, makeGetLabelEndpoint(svc)), @@ -283,10 +275,6 @@ type fleetHandlers struct { ApplyPackSpecs http.Handler GetPackSpecs http.Handler GetPackSpec http.Handler - GlobalScheduleQuery http.Handler - GetGlobalSchedule http.Handler - ModifyGlobalSchedule http.Handler - DeleteGlobalSchedule http.Handler EnrollAgent http.Handler GetClientConfig http.Handler GetDistributedQueries http.Handler @@ -381,10 +369,6 @@ func makeKitHandlers(e FleetEndpoints, opts []kithttp.ServerOption) *fleetHandle ApplyPackSpecs: newServer(e.ApplyPackSpecs, decodeApplyPackSpecsRequest), GetPackSpecs: newServer(e.GetPackSpecs, decodeNoParamsRequest), GetPackSpec: newServer(e.GetPackSpec, decodeGetGenericSpecRequest), - GlobalScheduleQuery: newServer(e.GlobalScheduleQuery, decodeGlobalScheduleQueryRequest), - GetGlobalSchedule: newServer(e.GetGlobalSchedule, decodeGetGlobalScheduleRequest), - ModifyGlobalSchedule: newServer(e.ModifyGlobalSchedule, decodeModifyGlobalScheduleRequest), - DeleteGlobalSchedule: newServer(e.DeleteGlobalSchedule, decodeDeleteGlobalScheduleRequest), EnrollAgent: newServer(e.EnrollAgent, decodeEnrollAgentRequest), GetClientConfig: newServer(e.GetClientConfig, decodeGetClientConfigRequest), GetDistributedQueries: newServer(e.GetDistributedQueries, decodeGetDistributedQueriesRequest), @@ -581,11 +565,6 @@ func attachFleetAPIRoutes(r *mux.Router, h *fleetHandlers) { r.Handle("/api/v1/fleet/spec/packs", h.GetPackSpecs).Methods("GET").Name("get_pack_specs") r.Handle("/api/v1/fleet/spec/packs/{name}", h.GetPackSpec).Methods("GET").Name("get_pack_spec") - r.Handle("/api/v1/fleet/global/schedule", h.GetGlobalSchedule).Methods("GET").Name("set_global_schedule") - r.Handle("/api/v1/fleet/global/schedule", h.GlobalScheduleQuery).Methods("POST").Name("add_to_global_schedule") - r.Handle("/api/v1/fleet/global/schedule/{id:[0-9]+}", h.ModifyGlobalSchedule).Methods("PATCH").Name("modify_global_schedule") - r.Handle("/api/v1/fleet/global/schedule/{id:[0-9]+}", h.DeleteGlobalSchedule).Methods("DELETE").Name("delete_global_schedule") - r.Handle("/api/v1/fleet/labels", h.CreateLabel).Methods("POST").Name("create_label") r.Handle("/api/v1/fleet/labels/{id:[0-9]+}", h.ModifyLabel).Methods("PATCH").Name("modify_label") r.Handle("/api/v1/fleet/labels/{id:[0-9]+}", h.GetLabel).Methods("GET").Name("get_label") @@ -684,6 +663,11 @@ func attachNewStyleFleetAPIRoutes(r *mux.Router, svc fleet.Service, opts []kitht e.GET("/api/v1/fleet/activities", listActivitiesEndpoint, listActivitiesRequest{}) + e.GET("/api/v1/fleet/global/schedule", getGlobalScheduleEndpoint, getGlobalScheduleRequest{}) + e.POST("/api/v1/fleet/global/schedule", globalScheduleQueryEndpoint, globalScheduleQueryRequest{}) + e.PATCH("/api/v1/fleet/global/schedule/{id:[0-9]+}", modifyGlobalScheduleEndpoint, modifyGlobalScheduleRequest{}) + e.DELETE("/api/v1/fleet/global/schedule/{id:[0-9]+}", deleteGlobalScheduleEndpoint, deleteGlobalScheduleRequest{}) + e.GET("/api/v1/fleet/carves", listCarvesEndpoint, listCarvesRequest{}) e.GET("/api/v1/fleet/carves/{id:[0-9]+}", getCarveEndpoint, getCarveRequest{}) e.GET("/api/v1/fleet/carves/{id:[0-9]+}/block/{block_id}", getCarveBlockEndpoint, getCarveBlockRequest{}) diff --git a/server/service/integration_core_test.go b/server/service/integration_core_test.go index 9b94910fed..8cfe48c90c 100644 --- a/server/service/integration_core_test.go +++ b/server/service/integration_core_test.go @@ -226,10 +226,12 @@ func (s *integrationTestSuite) TestUserRolesSpec() { func (s *integrationTestSuite) TestGlobalSchedule() { t := s.T() + // list the existing global schedules (none yet) gs := fleet.GlobalSchedulePayload{} s.DoJSON("GET", "/api/v1/fleet/global/schedule", nil, http.StatusOK, &gs) require.Len(t, gs.GlobalSchedule, 0) + // create a query that can be scheduled qr, err := s.ds.NewQuery(context.Background(), &fleet.Query{ Name: "TestQuery1", Description: "Some description", @@ -238,10 +240,12 @@ func (s *integrationTestSuite) TestGlobalSchedule() { }) require.NoError(t, err) + // schedule that query gsParams := fleet.ScheduledQueryPayload{QueryID: ptr.Uint(qr.ID), Interval: ptr.Uint(42)} r := globalScheduleQueryResponse{} s.DoJSON("POST", "/api/v1/fleet/global/schedule", gsParams, http.StatusOK, &r) + // list the scheduled queries, get the one just created gs = fleet.GlobalSchedulePayload{} s.DoJSON("GET", "/api/v1/fleet/global/schedule", nil, http.StatusOK, &gs) require.Len(t, gs.GlobalSchedule, 1) @@ -249,18 +253,34 @@ func (s *integrationTestSuite) TestGlobalSchedule() { assert.Equal(t, "TestQuery1", gs.GlobalSchedule[0].Name) id := gs.GlobalSchedule[0].ID + // list page 2, should be empty + s.DoJSON("GET", "/api/v1/fleet/global/schedule", nil, http.StatusOK, &gs, "page", "2", "per_page", "4") + require.Len(t, gs.GlobalSchedule, 0) + + // update the scheduled query gs = fleet.GlobalSchedulePayload{} gsParams = fleet.ScheduledQueryPayload{Interval: ptr.Uint(55)} s.DoJSON("PATCH", fmt.Sprintf("/api/v1/fleet/global/schedule/%d", id), gsParams, http.StatusOK, &gs) + // update a non-existing schedule + gsParams = fleet.ScheduledQueryPayload{Interval: ptr.Uint(66)} + s.DoJSON("PATCH", fmt.Sprintf("/api/v1/fleet/global/schedule/%d", id+1), gsParams, http.StatusNotFound, &gs) + + // read back that updated scheduled query gs = fleet.GlobalSchedulePayload{} s.DoJSON("GET", "/api/v1/fleet/global/schedule", nil, http.StatusOK, &gs) require.Len(t, gs.GlobalSchedule, 1) + assert.Equal(t, id, gs.GlobalSchedule[0].ID) assert.Equal(t, uint(55), gs.GlobalSchedule[0].Interval) + // delete the scheduled query r = globalScheduleQueryResponse{} s.DoJSON("DELETE", fmt.Sprintf("/api/v1/fleet/global/schedule/%d", id), nil, http.StatusOK, &r) + // delete a non-existing schedule + s.DoJSON("DELETE", fmt.Sprintf("/api/v1/fleet/global/schedule/%d", id+1), nil, http.StatusNotFound, &r) + + // list the scheduled queries, back to none gs = fleet.GlobalSchedulePayload{} s.DoJSON("GET", "/api/v1/fleet/global/schedule", nil, http.StatusOK, &gs) require.Len(t, gs.GlobalSchedule, 0) diff --git a/server/service/service_global_schedule.go b/server/service/service_global_schedule.go deleted file mode 100644 index f08985ffc5..0000000000 --- a/server/service/service_global_schedule.go +++ /dev/null @@ -1,62 +0,0 @@ -package service - -import ( - "context" - - "github.com/fleetdm/fleet/v4/server/fleet" - "github.com/fleetdm/fleet/v4/server/ptr" -) - -func (svc *Service) GlobalScheduleQuery(ctx context.Context, sq *fleet.ScheduledQuery) (*fleet.ScheduledQuery, error) { - if err := svc.authz.Authorize(ctx, &fleet.Pack{}, fleet.ActionRead); err != nil { - return nil, err - } - - gp, err := svc.ds.EnsureGlobalPack(ctx) - if err != nil { - return nil, err - } - sq.PackID = gp.ID - - return svc.ScheduleQuery(ctx, sq) -} - -func (svc *Service) GetGlobalScheduledQueries(ctx context.Context, opts fleet.ListOptions) ([]*fleet.ScheduledQuery, error) { - if err := svc.authz.Authorize(ctx, &fleet.Pack{}, fleet.ActionRead); err != nil { - return nil, err - } - - gp, err := svc.ds.EnsureGlobalPack(ctx) - if err != nil { - return nil, err - } - - return svc.ds.ListScheduledQueriesInPack(ctx, gp.ID, opts) -} - -func (svc *Service) ModifyGlobalScheduledQueries( - ctx context.Context, - id uint, - query fleet.ScheduledQueryPayload, -) (*fleet.ScheduledQuery, error) { - if err := svc.authz.Authorize(ctx, &fleet.Pack{}, fleet.ActionWrite); err != nil { - return nil, err - } - - gp, err := svc.ds.EnsureGlobalPack(ctx) - if err != nil { - return nil, err - } - - query.PackID = ptr.Uint(gp.ID) - - return svc.ModifyScheduledQuery(ctx, id, query) -} - -func (svc *Service) DeleteGlobalScheduledQueries(ctx context.Context, id uint) error { - if err := svc.authz.Authorize(ctx, &fleet.Pack{}, fleet.ActionWrite); err != nil { - return err - } - - return svc.DeleteScheduledQuery(ctx, id) -} diff --git a/server/service/transport_global_schedule.go b/server/service/transport_global_schedule.go deleted file mode 100644 index 2815927a1a..0000000000 --- a/server/service/transport_global_schedule.go +++ /dev/null @@ -1,52 +0,0 @@ -package service - -import ( - "context" - "encoding/json" - "net/http" -) - -func decodeGetGlobalScheduleRequest(ctx context.Context, r *http.Request) (interface{}, error) { - opts, err := listOptionsFromRequest(r) - if err != nil { - return nil, err - } - var req getGlobalScheduleRequest - req.ListOptions = opts - return req, nil -} - -func decodeModifyGlobalScheduleRequest(ctx context.Context, r *http.Request) (interface{}, error) { - id, err := uintFromRequest(r, "id") - if err != nil { - return nil, err - } - var req modifyGlobalScheduleRequest - - if err := json.NewDecoder(r.Body).Decode(&req.payload); err != nil { - return nil, err - } - - req.ID = uint(id) - return req, nil -} - -func decodeDeleteGlobalScheduleRequest(ctx context.Context, r *http.Request) (interface{}, error) { - id, err := uintFromRequest(r, "id") - if err != nil { - return nil, err - } - var req deleteGlobalScheduleRequest - req.ID = uint(id) - return req, nil -} - -func decodeGlobalScheduleQueryRequest(ctx context.Context, r *http.Request) (interface{}, error) { - var req globalScheduleQueryRequest - - if err := json.NewDecoder(r.Body).Decode(&req); err != nil { - return nil, err - } - - return req, nil -}