Files
micromdm/checkin/service.go
mosen e4ab7e0b17 Hotfix/last check in (#34)
* Convert all time.Time pointers to value types.
Use UTC time when updating `last_checkin`.
Update `last_checkin` correctly on Authenticate, TokenUpdate, and query response.
Set database defaults to golangs zero value for time.Time which is `0001-01-01`.

* Add down migration for time defaults.
2016-10-12 16:20:48 +11:00

148 lines
3.4 KiB
Go

package checkin
import (
"errors"
"fmt"
"github.com/micromdm/mdm"
"github.com/micromdm/micromdm/command"
"github.com/micromdm/micromdm/device"
"github.com/micromdm/micromdm/management"
"time"
)
// Service defines methods for and MDM Checkin service
type Service interface {
Authenticate(mdm.CheckinCommand) error
TokenUpdate(mdm.CheckinCommand) error
Checkout(mdm.CheckinCommand) error
// EnrollDEP returns an enrollment profile
// during DEP Enrollment
EnrollDEP(udid, serial string) ([]byte, error)
}
// NewService creates a checkin service
// profile holds an enrollment profile
func NewService(devices device.Datastore, ms management.Service, cs command.Service, profile []byte) Service {
return &service{
devices: devices,
mgmt: ms,
commands: cs,
profile: profile,
}
}
type service struct {
devices device.Datastore
mgmt management.Service
commands command.Service
profile []byte
}
func (svc service) Authenticate(cmd mdm.CheckinCommand) error {
var udid, serialNumber device.JsonNullString
if err := udid.Scan(cmd.UDID); err != nil {
return err
}
if err := serialNumber.Scan(cmd.SerialNumber); err != nil {
return err
}
dev := &device.Device{
UDID: udid,
SerialNumber: serialNumber,
OSVersion: cmd.OSVersion,
BuildVersion: cmd.BuildVersion,
ProductName: cmd.ProductName,
IMEI: cmd.IMEI,
MEID: cmd.MEID,
MDMTopic: cmd.Topic,
Model: cmd.Model,
DeviceName: cmd.DeviceName,
LastCheckin: time.Now().UTC(),
}
_, err := svc.devices.New("authenticate", dev)
return err
}
func (svc service) TokenUpdate(cmd mdm.CheckinCommand) error {
if cmd.UserID != "" {
// don't handle user updates for now
return nil
}
token := cmd.Token.String()
unlockToken := cmd.UnlockToken.String()
existing, err := svc.devices.GetDeviceByUDID(cmd.UDID, []string{"device_uuid"}...)
if err != nil {
return err
}
existing.Token = token
existing.MDMTopic = cmd.Topic
existing.PushMagic = cmd.PushMagic
existing.UnlockToken = unlockToken
existing.AwaitingConfiguration = cmd.AwaitingConfiguration
existing.Enrolled = true
existing.LastCheckin = time.Now().UTC()
err = svc.devices.Save("tokenUpdate", existing)
if err != nil {
return err
}
// trigger a push notification
svc.mgmt.Push(cmd.UDID)
return nil
}
func (svc service) Checkout(cmd mdm.CheckinCommand) error {
existing, err := svc.devices.GetDeviceByUDID(cmd.UDID, []string{"device_uuid"}...)
if err != nil {
return err
}
existing.Enrolled = false
err = svc.devices.Save("checkout", existing)
if err != nil {
return err
}
return nil
}
func (svc service) EnrollDEP(udid, serial string) ([]byte, error) {
err := svc.initialSetup(udid, serial)
if err != nil {
// TODO: stop ignoring the error there
fmt.Println(err)
}
return svc.profile, nil
}
func (svc service) initialSetup(deviceUDID, serial string) error {
devs, err := svc.devices.Devices(device.SerialNumber{SerialNumber: serial})
if err != nil {
return err
}
if len(devs) == 0 {
return errors.New("device not found")
}
dev := devs[0]
if dev.Workflow == "" {
// no workflow, send DeviceConfigured
return svc.sendConfigured(deviceUDID)
}
return nil
}
func (svc service) sendConfigured(deviceUDID string) error {
cmdRequest := &mdm.CommandRequest{
UDID: deviceUDID,
RequestType: "DeviceConfigured",
}
_, err := svc.commands.NewCommand(cmdRequest)
if err != nil {
return err
}
return nil
}