Skip to content

Commit

Permalink
Add pairing endpoint to REST API (#208)
Browse files Browse the repository at this point in the history
* Added a new endpoint to REST API that allows to pair (un)supervised devices  
* For supervised devices it needs p12 file in form-data and `Supervision-Password` header with the password for the p12 file
  • Loading branch information
shamanec authored Nov 29, 2022
1 parent 8660f03 commit 22eff63
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 0 deletions.
67 changes: 67 additions & 0 deletions restapi/api/device_endpoints.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package api

import (
"bytes"
"net/http"
"sync"

Expand All @@ -21,6 +22,7 @@ import (
// @Produce json
// @Param udid path string true "device udid"
// @Success 200 {object} map[string]interface{}
// @Param udid path string true "Device UDID"
// @Router /device/{udid}/info [get]
func Info(c *gin.Context) {
device := c.MustGet(IOS_KEY).(ios.DeviceEntry)
Expand Down Expand Up @@ -58,6 +60,7 @@ func Info(c *gin.Context) {
// @Produce png
// @Param udid path string true "device udid"
// @Success 200 {object} []byte
// @Param udid path string true "Device UDID"
// @Router /device/{udid}/screenshot [get]
func Screenshot(c *gin.Context) {
device := c.MustGet(IOS_KEY).(ios.DeviceEntry)
Expand All @@ -79,6 +82,7 @@ func Screenshot(c *gin.Context) {
// @Success 200 {object} GenericResponse
// @Failure 422 {object} GenericResponse
// @Failure 500 {object} GenericResponse
// @Param udid path string true "Device UDID"
// @Router /device/{udid}/setlocation [post]
func SetLocation(c *gin.Context) {
device := c.MustGet(IOS_KEY).(ios.DeviceEntry)
Expand Down Expand Up @@ -110,6 +114,7 @@ func SetLocation(c *gin.Context) {
// @Produce json
// @Success 200
// @Failure 500 {object} GenericResponse
// @Param udid path string true "Device UDID"
// @Router /device/{udid}/resetlocation [post]
func ResetLocation(c *gin.Context) {
device := c.MustGet(IOS_KEY).(ios.DeviceEntry)
Expand All @@ -130,6 +135,7 @@ func ResetLocation(c *gin.Context) {
// @Success 200 {object} map[string]interface{}
// @Failure 500 {object} GenericResponse
// @Failure 404 {object} GenericResponse
// @Param udid path string true "Device UDID"
// @Router /device/{udid}/profiles [get]
func GetProfiles(c *gin.Context) {

Expand Down Expand Up @@ -173,6 +179,7 @@ type deviceCondition struct {
// @Produce json
// @Success 200 {object} []instruments.ProfileType
// @Failure 500 {object} GenericResponse
// @Param udid path string true "Device UDID"
// @Router /device/{udid}/conditions [get]
func GetSupportedConditions(c *gin.Context) {
device := c.MustGet(IOS_KEY).(ios.DeviceEntry)
Expand All @@ -197,6 +204,7 @@ func GetSupportedConditions(c *gin.Context) {
// @Description Enable condition on a device by provided profileTypeID and profileID
// @Tags general_device_specific
// @Produce json
// @Param udid path string true "Device UDID"
// @Param profileTypeID query string true "Identifier of the profile type, eg. SlowNetworkCondition"
// @Param profileID query string true "Identifier of the sub-profile, eg. SlowNetwork100PctLoss"
// @Success 200 {object} GenericResponse
Expand Down Expand Up @@ -268,6 +276,7 @@ func EnableDeviceCondition(c *gin.Context) {
// @Produce json
// @Success 200 {object} GenericResponse
// @Failure 500 {object} GenericResponse
// @Param udid path string true "Device UDID"
// @Router /device/{udid}/disable-condition [post]
func DisableDeviceCondition(c *gin.Context) {
device := c.MustGet(IOS_KEY).(ios.DeviceEntry)
Expand All @@ -293,3 +302,61 @@ func DisableDeviceCondition(c *gin.Context) {

c.JSON(http.StatusOK, GenericResponse{Message: "Device condition disabled"})
}

//========================================
// DEVICE PAIRING
//========================================
// Pairs a device
// @Summary Pair a device with/without supervision
// @Description Pair a device with/without supervision
// @Tags general_device_specific
// @Produce json
// @Success 200 {object} GenericResponse
// @Failure 500 {object} GenericResponse
// @Failure 422 {object} GenericResponse
// @Param udid path string true "Device UDID"
// @Param supervised query string true "Set if device is supervised - true/false"
// @Param p12file formData file false "Supervision *.p12 file"
// @Param supervision_password formData string false "Supervision password"
// @Router /device/{udid}/pair [post]
func PairDevice(c *gin.Context) {
device := c.MustGet(IOS_KEY).(ios.DeviceEntry)

supervised := c.Query("supervised")
if supervised == "" {
c.JSON(http.StatusUnprocessableEntity, GenericResponse{Error: "supervised query param is missing (true/false)"})
return
}

if supervised == "false" {
err := ios.Pair(device)
if err != nil {
c.JSON(http.StatusInternalServerError, GenericResponse{Error: err.Error()})
return
}
c.JSON(http.StatusOK, GenericResponse{Message: "Device paired"})
return
}

file, _, err := c.Request.FormFile("p12file")
if err != nil {
c.JSON(http.StatusInternalServerError, GenericResponse{Error: "Could not parse p12 file from form-data or no file provided, err:" + err.Error()})
return
}
p12fileBuf := new(bytes.Buffer)
p12fileBuf.ReadFrom(file)

supervision_password := c.Request.Header.Get("Supervision-Password")
if supervision_password == "" {
c.JSON(http.StatusUnprocessableEntity, GenericResponse{Error: "you must provide non-empty `Supervision-Password` header with the request"})
return
}

err = ios.PairSupervised(device, p12fileBuf.Bytes(), supervision_password)
if err != nil {
c.JSON(http.StatusInternalServerError, GenericResponse{Error: err.Error()})
return
}

c.JSON(http.StatusOK, GenericResponse{Message: "Device paired"})
}
1 change: 1 addition & 0 deletions restapi/api/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ func registerRoutes(router *gin.RouterGroup) {
device.GET("/conditions", GetSupportedConditions)
device.PUT("/enable-condition", EnableDeviceCondition)
device.POST("/disable-condition", DisableDeviceCondition)
device.POST("/pair", PairDevice)

device.POST("/reservations", ReserveDevice)
device.GET("/profiles", GetProfiles)
Expand Down

0 comments on commit 22eff63

Please sign in to comment.