Revert acknowledge handlers code.

Add stub for acknowledging installed applications list.
This commit is contained in:
Mosen
2016-07-12 22:40:21 +10:00
parent 9ffbef8025
commit 82f7e3ab6c
3 changed files with 51 additions and 235 deletions

View File

@@ -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
}

View File

@@ -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 {
//
//}

View File

@@ -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)
}