Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -913,6 +913,103 @@
}
},
"response": []
},
{
"name": "Get Wireless Profiles",
"event": [
{
"listen": "test",
"script": {
"exec": [
"pm.test(\"Status code is 404\", function () {\r",
" pm.response.to.have.status(404);\r",
"});\r",
"\r",
"pm.test(\"Device should not be found\", function () {\r",
" var jsonData = pm.response.json();\r",
" pm.expect(jsonData.error).to.eq(\"Error not found\")\r",
"});\r",
""
],
"type": "text/javascript",
"packages": {}
}
}
],
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{protocol}}://{{host}}/api/v1/amt/networkSettings/wireless/profile/{{deviceId}}",
"protocol": "{{protocol}}",
"host": [
"{{host}}"
],
"path": [
"api",
"v1",
"amt",
"networkSettings",
"wireless",
"profile",
"{{deviceId}}"
]
}
},
"response": []
},
{
"name": "Apply Wireless Profiles",
"event": [
{
"listen": "test",
"script": {
"exec": [
"pm.test(\"Status code is 404\", function () {\r",
" pm.response.to.have.status(404);\r",
"});\r",
"\r",
"pm.test(\"Device should not be found\", function () {\r",
" var jsonData = pm.response.json();\r",
" pm.expect(jsonData.error).to.eq(\"Error not found\")\r",
"});\r",
""
],
"type": "text/javascript",
"packages": {}
}
}
],
"request": {
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{\r\n \"profiles\": [\r\n {\r\n \"profileName\": \"Home\",\r\n \"ssid\": \"HomeSSID\",\r\n \"password\": \"P@ssword123\",\r\n \"authenticationMethod\": \"WPA2PSK\",\r\n \"encryptionMethod\": \"CCMP\",\r\n \"priority\": 1\r\n }\r\n ]\r\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{protocol}}://{{host}}/api/v1/amt/networkSettings/wireless/profile/{{deviceId}}",
"protocol": "{{protocol}}",
"host": [
"{{host}}"
],
"path": [
"api",
"v1",
"amt",
"networkSettings",
"wireless",
"profile",
"{{deviceId}}"
]
}
},
"response": []
}
]
},
Expand Down
30 changes: 20 additions & 10 deletions internal/controller/httpapi/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,16 +62,7 @@ func NewRouter(handler *gin.Engine, l logger.Interface, t usecase.Usecases, cfg
protected = handler.Group("/api", login.JWTAuthMiddleware())
}

// Register custom validators once
if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
if err := v.RegisterValidation("alphanumhyphenunderscore", dto.ValidateAlphaNumHyphenUnderscore); err != nil {
l.Error("failed to register custom validation: " + err.Error())
}

if err := v.RegisterValidation("wifistate", dto.ValidateWirelessState); err != nil {
l.Error("failed to register custom validation: " + err.Error())
}
}
registerCustomValidators(l)

// Routers
h2 := protected.Group("/v1")
Expand All @@ -95,3 +86,22 @@ func NewRouter(handler *gin.Engine, l logger.Interface, t usecase.Usecases, cfg
v2.NewAmtRoutes(h3, t.Devices, l)
}
}

func registerCustomValidators(l logger.Interface) {
v, ok := binding.Validator.Engine().(*validator.Validate)
if !ok {
return
}

registerValidation := func(tag string, validationFunc validator.Func) {
if err := v.RegisterValidation(tag, validationFunc); err != nil {
l.Error("failed to register custom validation: " + err.Error())
}
}

registerValidation("alphanumhyphenunderscore", dto.ValidateAlphaNumHyphenUnderscore)
registerValidation("wifistate", dto.ValidateWirelessState)
registerValidation("wirelessprofile", dto.ValidateWirelessProfile)
registerValidation("wirelessprofilescount", dto.ValidateWirelessProfilesCount)
registerValidation("wirelessprofilesuniquepriorities", dto.ValidateWirelessProfilesUniquePriorities)
}
2 changes: 2 additions & 0 deletions internal/controller/httpapi/v1/devicemanagement.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ func NewAmtRoutes(handler *gin.RouterGroup, d devices.Feature, amt amtexplorer.F
h.GET("networkSettings/:guid", r.getNetworkSettings)
h.GET("networkSettings/wireless/state/:guid", r.getWirelessState)
h.POST("networkSettings/wireless/state/:guid", r.requestWirelessStateChange)
h.GET("networkSettings/wireless/profile/:guid", r.getWirelessProfiles)
h.POST("networkSettings/wireless/profile/:guid", r.applyWirelessProfiles)

h.GET("explorer", r.getCallList)
h.GET("explorer/:guid/:call", r.executeCall)
Expand Down
44 changes: 44 additions & 0 deletions internal/controller/httpapi/v1/wifiprofile.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package v1

import (
"net/http"

"github.com/gin-gonic/gin"

"github.com/device-management-toolkit/console/internal/entity/dto/v1"
)

func (r *deviceManagementRoutes) getWirelessProfiles(c *gin.Context) {
guid := c.Param("guid")

response, err := r.d.GetWirelessProfiles(c.Request.Context(), guid)
if err != nil {
r.l.Error(err, "http - v1 - getWirelessProfiles")
ErrorResponse(c, err)

return
}

c.JSON(http.StatusOK, response)
}

func (r *deviceManagementRoutes) applyWirelessProfiles(c *gin.Context) {
guid := c.Param("guid")

var req dto.WirelessProfilesApplyRequest
if err := c.ShouldBindJSON(&req); err != nil {
ErrorResponse(c, err)

return
}

response, err := r.d.ApplyWirelessProfiles(c.Request.Context(), guid, req)
if err != nil {
r.l.Error(err, "http - v1 - applyWirelessProfiles")
ErrorResponse(c, err)

return
}

c.JSON(http.StatusOK, response)
}
148 changes: 148 additions & 0 deletions internal/controller/httpapi/v1/wifiprofile_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
package v1

import (
"bytes"
"context"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"

"github.com/stretchr/testify/require"

"github.com/device-management-toolkit/go-wsman-messages/v2/pkg/config"

"github.com/device-management-toolkit/console/internal/entity/dto/v1"
"github.com/device-management-toolkit/console/internal/mocks"
)

type wiFiProfileRouteTest struct {
name string
method string
url string
mock func(*mocks.MockDeviceManagementFeature)
requestBody interface{}
rawBody string
response interface{}
expectedCode int
}

func TestWiFiProfileRoutes(t *testing.T) {
t.Parallel()

request := dto.WirelessProfilesApplyRequest{
Profiles: []config.WirelessProfile{{
ProfileName: "office",
SSID: "CorpNet",
Priority: 1,
AuthenticationMethod: "WPA2PSK",
EncryptionMethod: "CCMP",
Password: "password123",
}},
}
Comment thread
shaoboon marked this conversation as resolved.

expectedProfiles := []config.WirelessProfile{{
ProfileName: "office",
SSID: "CorpNet",
Priority: 1,
AuthenticationMethod: "WPA2PSK",
EncryptionMethod: "CCMP",
}}

tests := []wiFiProfileRouteTest{
{
name: "get wireless profiles",
method: http.MethodGet,
url: "/api/v1/amt/networkSettings/wireless/profile/device-guid",
mock: func(feature *mocks.MockDeviceManagementFeature) {
feature.EXPECT().GetWirelessProfiles(context.Background(), "device-guid").Return(expectedProfiles, nil)
},
response: expectedProfiles,
expectedCode: http.StatusOK,
},
{
name: "get wireless profiles - service failure",
method: http.MethodGet,
url: "/api/v1/amt/networkSettings/wireless/profile/device-guid",
mock: func(feature *mocks.MockDeviceManagementFeature) {
feature.EXPECT().GetWirelessProfiles(context.Background(), "device-guid").Return(nil, ErrGeneral)
},
expectedCode: http.StatusInternalServerError,
},
{
name: "apply wireless profiles",
method: http.MethodPost,
url: "/api/v1/amt/networkSettings/wireless/profile/device-guid",
requestBody: request,
mock: func(feature *mocks.MockDeviceManagementFeature) {
feature.EXPECT().ApplyWirelessProfiles(context.Background(), "device-guid", request).Return(expectedProfiles, nil)
},
response: expectedProfiles,
expectedCode: http.StatusOK,
},
{
name: "apply wireless profiles - bind failure",
method: http.MethodPost,
url: "/api/v1/amt/networkSettings/wireless/profile/device-guid",
rawBody: `{"profiles":`,
expectedCode: http.StatusInternalServerError,
},
{
name: "apply wireless profiles - service failure",
method: http.MethodPost,
url: "/api/v1/amt/networkSettings/wireless/profile/device-guid",
requestBody: request,
mock: func(feature *mocks.MockDeviceManagementFeature) {
feature.EXPECT().ApplyWirelessProfiles(context.Background(), "device-guid", request).Return(nil, ErrGeneral)
},
expectedCode: http.StatusInternalServerError,
},
}

for _, tc := range tests {
tc := tc

t.Run(tc.name, func(t *testing.T) {
t.Parallel()

feature, engine := deviceManagementTest(t)

if tc.mock != nil {
tc.mock(feature)
}

var req *http.Request

var err error

switch tc.method {
case http.MethodPost, http.MethodPatch:
if tc.rawBody != "" {
req, err = http.NewRequestWithContext(context.Background(), tc.method, tc.url, bytes.NewBufferString(tc.rawBody))
} else {
payload, marshalErr := json.Marshal(tc.requestBody)
require.NoError(t, marshalErr)

req, err = http.NewRequestWithContext(context.Background(), tc.method, tc.url, bytes.NewBuffer(payload))
}

req.Header.Set("Content-Type", "application/json")
default:
req, err = http.NewRequestWithContext(context.Background(), tc.method, tc.url, http.NoBody)
}

require.NoError(t, err)

w := httptest.NewRecorder()
engine.ServeHTTP(w, req)

require.Equal(t, tc.expectedCode, w.Code)

if tc.expectedCode == http.StatusOK {
jsonBytes, marshalErr := json.Marshal(tc.response)
require.NoError(t, marshalErr)
require.Equal(t, string(jsonBytes), w.Body.String())
}
})
}
}
2 changes: 1 addition & 1 deletion internal/controller/httpapi/v1/wifistate.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (

"github.com/device-management-toolkit/go-wsman-messages/v2/pkg/wsman/cim/wifi"

dto "github.com/device-management-toolkit/console/internal/entity/dto/v1"
"github.com/device-management-toolkit/console/internal/entity/dto/v1"
"github.com/device-management-toolkit/console/internal/usecase/devices/wsman"
"github.com/device-management-toolkit/console/pkg/consoleerrors"
)
Expand Down
2 changes: 1 addition & 1 deletion internal/controller/httpapi/v1/wifistate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (

"github.com/gin-gonic/gin"
"github.com/stretchr/testify/require"
gomock "go.uber.org/mock/gomock"
"go.uber.org/mock/gomock"

"github.com/device-management-toolkit/go-wsman-messages/v2/pkg/wsman/cim/wifi"

Expand Down
Loading
Loading