mirror of
https://github.com/micromdm/micromdm/
synced 2026-08-13 22:15:42 +08:00
Fix wrong positional parameters.
Add handler for InstalledApplicationList request type. installed applications are inserted but their relationship to the current device is not yet recorded. work in progress.
This commit is contained in:
@@ -66,13 +66,13 @@ func (store pgStore) New(a *Application) (string, error) {
|
||||
dynamic_size,
|
||||
is_validated
|
||||
)
|
||||
VALUES ($0, $1, $2, $3, $4, $5, $6)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
||||
ON CONFLICT (name, version) DO UPDATE SET
|
||||
identifier=$1,
|
||||
short_version=$2,
|
||||
bundle_size=$4,
|
||||
dynamic_size=$5,
|
||||
is_validated=$6
|
||||
identifier=$2,
|
||||
short_version=$3,
|
||||
bundle_size=$5,
|
||||
dynamic_size=$6,
|
||||
is_validated=$7
|
||||
RETURNING application_uuid;`,
|
||||
a.Name,
|
||||
a.Identifier,
|
||||
@@ -92,7 +92,16 @@ func (store pgStore) New(a *Application) (string, error) {
|
||||
|
||||
// Retrieve a list of applications
|
||||
func (store pgStore) Applications(params ...interface{}) ([]Application, error) {
|
||||
stmt := `SELECT * FROM applications`
|
||||
stmt := `SELECT
|
||||
application_uuid,
|
||||
name,
|
||||
identifier,
|
||||
short_version,
|
||||
version,
|
||||
bundle_size,
|
||||
dynamic_size,
|
||||
is_validated
|
||||
FROM applications`
|
||||
stmt = addWhereFilters(stmt, "OR", params...)
|
||||
|
||||
var apps []Application
|
||||
@@ -106,13 +115,25 @@ func (store pgStore) Applications(params ...interface{}) ([]Application, error)
|
||||
|
||||
// Retrieve only applications which are installed on the given device.
|
||||
func (store pgStore) GetApplicationsByDeviceUUID(deviceUUID string) ([]Application, error) {
|
||||
if len(deviceUUID) == 0 {
|
||||
return nil, errors.New("empty uuid supplied to GetApplicationsByDeviceUUID")
|
||||
}
|
||||
|
||||
var apps []Application
|
||||
query := `SELECT * FROM applications
|
||||
query := `SELECT
|
||||
applications.application_uuid AS application_uuid,
|
||||
name,
|
||||
identifier,
|
||||
short_version,
|
||||
version,
|
||||
bundle_size,
|
||||
dynamic_size,
|
||||
is_validated
|
||||
FROM applications
|
||||
RIGHT JOIN devices_applications ON applications.application_uuid = devices_applications.application_uuid
|
||||
WHERE devices_applications.device_uuid=$1`
|
||||
|
||||
err := store.Select(&apps, query, deviceUUID)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -122,6 +143,14 @@ func (store pgStore) GetApplicationsByDeviceUUID(deviceUUID string) ([]Applicati
|
||||
|
||||
// Associate the given applications with the given device uuid by inserting into `device_applications`.
|
||||
func (store pgStore) SaveApplicationByDeviceUUID(deviceUUID string, app *Application) error {
|
||||
if deviceUUID == "" {
|
||||
return errors.New("empty uuid supplied to SaveApplicationByDeviceUUID for deviceUUID")
|
||||
}
|
||||
|
||||
if app.UUID == "" {
|
||||
return errors.New("empty uuid supplied to SaveApplicationByDeviceUUID for application")
|
||||
}
|
||||
|
||||
stmt := `INSERT INTO devices_applications (
|
||||
device_uuid, application_uuid
|
||||
) VALUES ($1, $2)`
|
||||
|
||||
@@ -41,6 +41,11 @@ func (svc service) Acknowledge(ctx context.Context, req mdm.Response) (int, erro
|
||||
if err := svc.ackQueryResponses(req); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
case "InstalledApplicationList":
|
||||
if err := svc.ackInstalledApplicationList(req); err != nil {
|
||||
fmt.Printf("Got an error acknowledging InstalledApplicationList: %v\n", err)
|
||||
return 0, err
|
||||
}
|
||||
default:
|
||||
// Need to handle the absence of RequestType in IOS8 devices
|
||||
if req.QueryResponses.UDID != "" {
|
||||
@@ -137,62 +142,93 @@ func (svc service) ackQueryResponses(req mdm.Response) error {
|
||||
|
||||
// Acknowledge a response to `InstalledApplicationList`.
|
||||
func (svc service) ackInstalledApplicationList(req mdm.Response) error {
|
||||
device, err := svc.devices.GetDeviceByUDID(req.UDID)
|
||||
fmt.Println("Acknowledging installed applications")
|
||||
|
||||
device, err := svc.devices.GetDeviceByUDID(req.UDID, "device_uuid")
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "getting a device record by udid")
|
||||
}
|
||||
|
||||
requestApps := make([]apps.Application, len(req.InstalledApplicationList))
|
||||
// Update or insert application records that do not exist, returning the UUID so that it can be inserted for
|
||||
// the device sending the response.
|
||||
for _, reqApp := range req.InstalledApplicationList {
|
||||
identifier := sql.NullString{reqApp.Identifier, reqApp.Identifier != ""}
|
||||
shortVersion := sql.NullString{reqApp.ShortVersion, reqApp.ShortVersion != ""}
|
||||
version := sql.NullString{reqApp.Version, reqApp.Version != ""}
|
||||
|
||||
bundleSize := sql.NullInt64{}
|
||||
bundleSize.Scan(reqApp.BundleSize)
|
||||
|
||||
dynamicSize := sql.NullInt64{}
|
||||
dynamicSize.Scan(reqApp.DynamicSize)
|
||||
|
||||
newApp := apps.Application{
|
||||
Name: reqApp.Name,
|
||||
Identifier: identifier,
|
||||
ShortVersion: shortVersion,
|
||||
Version: version,
|
||||
BundleSize: bundleSize,
|
||||
DynamicSize: dynamicSize,
|
||||
}
|
||||
appUuid, err := svc.apps.New(&newApp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
newApp.UUID = appUuid
|
||||
requestApps = append(requestApps, newApp)
|
||||
}
|
||||
|
||||
deviceApps, err := svc.apps.GetApplicationsByDeviceUUID(device.UUID)
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "getting applications by device uuid")
|
||||
}
|
||||
|
||||
var removed []apps.Application = make([]apps.Application, len(req.InstalledApplicationList))
|
||||
var deviceAppsRemaining []apps.Application = make([]apps.Application, len(req.InstalledApplicationList))
|
||||
var deviceRemoved []apps.Application = make([]apps.Application, len(req.InstalledApplicationList))
|
||||
var deviceNotRemoved []apps.Application = make([]apps.Application, len(req.InstalledApplicationList))
|
||||
|
||||
// Check to see whether installed applications exist in the latest response
|
||||
// If they do not, they are added to the removed slice.
|
||||
// TODO: This is a pretty horrible algorithm and I should re-design it at some point. m.
|
||||
fmt.Println("Determining apps removed")
|
||||
removedouter:
|
||||
for _, deviceApp := range deviceApps {
|
||||
for _, app := range req.InstalledApplicationList {
|
||||
if deviceApp.Version.Valid && deviceApp.Version.String == app.Version && deviceApp.Name == app.Name {
|
||||
deviceAppsRemaining = append(deviceAppsRemaining, deviceApp)
|
||||
for _, app := range requestApps {
|
||||
if deviceApp.Version == app.Version && deviceApp.Name == app.Name {
|
||||
deviceNotRemoved = append(deviceNotRemoved, deviceApp)
|
||||
continue removedouter
|
||||
}
|
||||
}
|
||||
|
||||
removed = append(removed, deviceApp)
|
||||
deviceRemoved = append(deviceRemoved, deviceApp)
|
||||
}
|
||||
|
||||
// Any installed applications that are already represented in the `applications` table AND
|
||||
// allocated to the device in `devices_applications` should be skipped.
|
||||
var updated []apps.Application = make([]apps.Application, len(req.InstalledApplicationList))
|
||||
|
||||
fmt.Println("Determining apps changed or added")
|
||||
skip:
|
||||
for _, ackApp := range req.InstalledApplicationList {
|
||||
for _, app := range deviceAppsRemaining {
|
||||
if app.Name == ackApp.Name && app.Version.Valid && app.Version.String == ackApp.Version {
|
||||
for _, ackApp := range requestApps {
|
||||
for _, app := range deviceNotRemoved {
|
||||
if app.Name == ackApp.Name && app.Version == ackApp.Version {
|
||||
continue skip
|
||||
}
|
||||
}
|
||||
|
||||
identifier := sql.NullString{ackApp.Identifier, ackApp.Identifier != ""}
|
||||
|
||||
appUpdated := apps.Application{
|
||||
Name: ackApp.Name,
|
||||
Identifier: identifier,
|
||||
//ShortVersion: sql.NullString{}.Scan(ackApp.ShortVersion),
|
||||
//Version: sql.NullString{}.Scan(ackApp.Version),
|
||||
//BundleSize: sql.NullInt64{}.Scan(ackApp.BundleSize),
|
||||
//DynamicSize: sql.NullInt64{}.Scan(ackApp.DynamicSize),
|
||||
//IsValidated: sql.NullBool{}.Scan(ackApp.IsValidated),
|
||||
}
|
||||
updated = append(updated, appUpdated)
|
||||
updated = append(updated, ackApp)
|
||||
}
|
||||
|
||||
fmt.Printf("removed %#v\n", removed)
|
||||
fmt.Printf("updated %#v\n", updated)
|
||||
fmt.Printf("removed %d application(s)\n", len(deviceRemoved))
|
||||
fmt.Printf("updated %d application(s)\n", len(updated))
|
||||
|
||||
for _, insertApp := range updated {
|
||||
if err := svc.apps.SaveApplicationByDeviceUUID(device.UUID, &insertApp); err != nil {
|
||||
fmt.Printf("could not save application, no valid uuid: %s\n", insertApp.Name)
|
||||
// return errors.Wrap(err, "saving installed application for a device")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user