diff --git a/applications/acknowledge.go b/applications/acknowledge.go deleted file mode 100644 index e3729066..00000000 --- a/applications/acknowledge.go +++ /dev/null @@ -1,125 +0,0 @@ -package applications - -import ( - "database/sql" - "errors" - "fmt" - "github.com/micromdm/mdm" - // "github.com/micromdm/micromdm/device" - "github.com/micromdm/micromdm/device" -) - -func AppListPredicate(response mdm.Response) bool { - fmt.Println("InstalledApplicationList Predicate") - - if response.RequestType == "InstalledApplicationList" { - return true - } - - if response.InstalledApplicationList != nil { - return true - } - - return false -} - -func any(list []Application, predicate func(Application) bool) bool { - for _, v := range list { - if predicate(v) { - return true - } - } - - return false -} - -func AppListResponse(response mdm.Response, datastores map[string]interface{}) error { - store, found := datastores["applications"] - if !found { - return errors.New("Do not have access to datastore for saving application information") - } - - appsStore, ok := store.(Datastore) - if !ok { - return errors.New("could not acknowledge installed application list because the given datastore isnt an application datastore.") - } - - dstore, found := datastores["devices"] - if !found { - return errors.New("Do not have access to datastore for retrieving device information") - } - - deviceStore, ok := dstore.(device.Datastore) - if !ok { - return errors.New("could not acknowledge installed application list because the given device datastore isnt a device datastore.") - } - - device, err := deviceStore.GetDeviceByUDID(response.UDID) - if err != nil { - return err - } - - deviceApps, err := appsStore.GetApplicationsByDeviceUUID(device.UUID) - if err != nil { - return err - } - - var uuids []string - for _, app := range response.InstalledApplicationList { - //var uuid string - - existingApps, err := appsStore.Applications(Name{app.Name}, Version{app.Version}) - if err != nil { - return err - } - - if len(existingApps) > 0 { - existingApp := existingApps[0] - uuid = existingApp.UUID - uuids = append(uuids, existingApp.UUID) - } else { - dbApp := &Application{Name: app.Name} - - identifier := sql.NullString{} - identifier.Scan(app.Identifier) - dbApp.Identifier = identifier - - bundleSize := sql.NullInt64{} - bundleSize.Scan(app.BundleSize) - dbApp.BundleSize = bundleSize - - shortVersion := sql.NullString{} - shortVersion.Scan(app.ShortVersion) - dbApp.ShortVersion = shortVersion - - version := sql.NullString{} - version.Scan(app.Version) - dbApp.Version = version - - dynamicSize := sql.NullInt64{} - dynamicSize.Scan(app.DynamicSize) - dbApp.DynamicSize = dynamicSize - - isValidated := sql.NullBool{} - isValidated.Scan(app.IsValidated) - dbApp.IsValidated = isValidated - - uuid, err := appsStore.New(dbApp) - if err != nil { - return err - } - uuids = append(uuids, uuid) - } - - if !any(deviceApps, app) { - // App installed on device but not recorded - - //deviceApp := &DeviceApplication{ - // DeviceUUID: device.UUID, - // ApplicationUUID: app.UUID, - //} - } - } - - return nil -} diff --git a/connect/service.go b/connect/service.go index 7a535e4e..8a232bec 100644 --- a/connect/service.go +++ b/connect/service.go @@ -1,12 +1,13 @@ package connect import ( - "fmt" + "encoding/json" "github.com/micromdm/mdm" "github.com/micromdm/micromdm/command" "github.com/micromdm/micromdm/device" "github.com/pkg/errors" "golang.org/x/net/context" + "time" ) // Service defines methods for an MDM service @@ -14,10 +15,6 @@ type Service interface { Acknowledge(ctx context.Context, req mdm.Response) (int, error) NextCommand(ctx context.Context, req mdm.Response) ([]byte, int, error) FailCommand(ctx context.Context, req mdm.Response) (int, error) - - RegisterAckHandler(predicate func(req mdm.Response) bool, handler func(req mdm.Response, datastores map[string]interface{}) error, datastores map[string]interface{}) - FindAckHandler(req mdm.Response) (func(req mdm.Response) error, bool) - ExecAckHandler(req mdm.Response) error } // NewService creates a mdm service @@ -25,25 +22,27 @@ func NewService(devices device.Datastore, cs command.Service) Service { return &service{ commands: cs, devices: devices, - handlers: []ackHandler{}, } } -type ackHandler struct { - predicate func(req mdm.Response) bool - handler func(req mdm.Response) error -} - type service struct { devices device.Datastore commands command.Service - handlers []ackHandler } func (svc service) Acknowledge(ctx context.Context, req mdm.Response) (int, error) { - err := svc.ExecAckHandler(req) - if err != nil { - return 0, err + switch req.RequestType { + case "DeviceInformation": + if err := svc.ackQueryResponses(req); err != nil { + return 0, err + } + default: + // Need to handle the absence of RequestType in IOS8 devices + if req.QueryResponses.UDID != "" { + if err := svc.ackQueryResponses(req); err != nil { + return 0, err + } + } } total, err := svc.commands.DeleteCommand(req.UDID, req.CommandUUID) @@ -87,33 +86,46 @@ func (svc service) checkRequeue(deviceUDID string) (int, error) { return 0, nil } -// Register a handler function for a given request, include datastore dependencies as a map. -func (svc *service) RegisterAckHandler(predicate func(req mdm.Response) bool, handler func(req mdm.Response, datastores map[string]interface{}) error, datastores map[string]interface{}) { - datastoreInjectedHandler := func(req mdm.Response) error { - return handler(req, datastores) - } - newHandler := ackHandler{predicate: predicate, handler: datastoreInjectedHandler} - svc.handlers = append(svc.handlers, newHandler) -} +// Acknowledge Queries sent with DeviceInformation command +func (svc service) ackQueryResponses(req mdm.Response) error { + devices, err := svc.devices.Devices( + device.SerialNumber{SerialNumber: req.QueryResponses.SerialNumber}, + device.UDID{UDID: req.UDID}, + ) -// Find a handler function which is registered to deal with the RequestType -func (svc service) FindAckHandler(req mdm.Response) (func(req mdm.Response) error, bool) { - for i, h := range svc.handlers { - fmt.Println(i) - if h.predicate(req) { - return h.handler, true - } + if err != nil { + return err } - return nil, false -} - -// Execute any registered handler function which matches the given RequestType -func (svc service) ExecAckHandler(req mdm.Response) error { - handler, found := svc.FindAckHandler(req) - if !found { - return errors.New("There is no registered handler for the response.") + if len(devices) > 1 { + return errors.New("expected a single query result for device, got more than one.") } - return handler(req) + existing := devices[0] + + now := time.Now() + existing.LastCheckin = &now + existing.LastQueryResponse, err = json.Marshal(req.QueryResponses) + + if err != nil { + return err + } + + var serialNumber device.JsonNullString + serialNumber.Scan(req.QueryResponses.SerialNumber) + + existing.ProductName = req.QueryResponses.ProductName + existing.BuildVersion = req.QueryResponses.BuildVersion + existing.DeviceName = req.QueryResponses.DeviceName + existing.IMEI = req.QueryResponses.IMEI + existing.MEID = req.QueryResponses.MEID + existing.Model = req.QueryResponses.Model + existing.OSVersion = req.QueryResponses.OSVersion + existing.SerialNumber = serialNumber + + return svc.devices.Save("queryResponses", &existing) } + +//func (svc service) ackInstalledApplicationList(req mdm.Response) error { +// +//} diff --git a/device/acknowledge.go b/device/acknowledge.go deleted file mode 100644 index 28bc5011..00000000 --- a/device/acknowledge.go +++ /dev/null @@ -1,71 +0,0 @@ -package device - -import ( - "encoding/json" - "errors" - "github.com/micromdm/mdm" - "time" -) - -func AckQueryResponsesPredicate(req mdm.Response) bool { - if req.RequestType == "DeviceInformation" { - return true - } - - //// Need to handle the absence of RequestType in IOS8 devices - if req.QueryResponses.UDID != "" { - return true - } - - return false -} - -// Acknowledge Queries sent with DeviceInformation command -func AckQueryResponsesResponse(req mdm.Response, datastores map[string]interface{}) error { - store, found := datastores["devices"] - if !found { - return errors.New("Do not have access to datastore for saving device information") - } - - devicesStore, ok := store.(Datastore) - if !ok { - return errors.New("could not acknowledge device information because the given datastore isnt a device datastore.") - } - - devices, err := devicesStore.Devices( - SerialNumber{SerialNumber: req.QueryResponses.SerialNumber}, - UDID{UDID: req.UDID}, - ) - - if err != nil { - return err - } - - if len(devices) > 1 { - return errors.New("expected a single query result for device, got more than one.") - } - - existing := devices[0] - - now := time.Now() - existing.LastCheckin = &now - existing.LastQueryResponse, err = json.Marshal(req.QueryResponses) - - if err != nil { - return err - } - - var serialNumber JsonNullString - serialNumber.Scan(req.QueryResponses.SerialNumber) - - existing.ProductName = req.QueryResponses.ProductName - existing.BuildVersion = req.QueryResponses.BuildVersion - existing.DeviceName = req.QueryResponses.DeviceName - existing.IMEI = req.QueryResponses.IMEI - existing.MEID = req.QueryResponses.MEID - existing.Model = req.QueryResponses.Model - existing.OSVersion = req.QueryResponses.OSVersion - existing.SerialNumber = serialNumber - - return devicesStore.Save("queryResponses", &existing) -}