Skip to content

Commit d7b3829

Browse files
authored
feat(devices): add network settings management for AMT devices (#3370)
Add a Network Settings tab to the device view for managing wired and wireless network configuration directly on a device. Wired: - View link/IP details and IEEE 802.1x status - Configure DHCP or static IP, with IP synchronization Wireless: - View link/IP details and toggle Wi-Fi state - Manage local and UEFI profile synchronization - Create, edit and delete wireless profiles (sorted by priority) - Support PSK and IEEE 802.1x auth; for 802.1x, PEAP uses a password and EAP-TLS uploads client certificate, private key and optional CA certificate (uploaded as base64 DER, matching the backend) Add the corresponding DevicesService endpoints, request/response models. Includes unit tests for the new service methods and component. Resolves: #3353 created network specific enabled/disabled labels fix fix
1 parent 1977bef commit d7b3829

27 files changed

Lines changed: 3602 additions & 472 deletions

src/app/devices/devices.service.spec.ts

Lines changed: 172 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ import {
1616
IPSAlarmClockOccurrence,
1717
IPSAlarmClockOccurrenceInput,
1818
BootDetails,
19-
DisplaySelectionResponse
19+
DisplaySelectionResponse,
20+
WirelessProfileSyncResponse,
21+
WirelessProfileSyncRequest
2022
} from '../../models/models'
2123
import { provideTranslateService } from '@ngx-translate/core'
2224

@@ -1125,6 +1127,175 @@ describe('DevicesService', () => {
11251127
})
11261128
})
11271129

1130+
describe('getWiredNetworkSettings', () => {
1131+
it('should fetch wired network settings for a device', () => {
1132+
const mockResponse = { dhcpEnabled: true } as any
1133+
1134+
service.getWiredNetworkSettings('guid1').subscribe((response) => {
1135+
expect(response).toEqual(mockResponse)
1136+
})
1137+
1138+
const req = httpMock.expectOne(`${mockEnvironment.mpsServer}/api/v1/amt/networkSettings/wired/guid1`)
1139+
expect(req.request.method).toBe('GET')
1140+
req.flush(mockResponse)
1141+
})
1142+
})
1143+
1144+
describe('patchWiredNetworkSettings', () => {
1145+
it('should patch wired network settings for a device', () => {
1146+
const payload = {
1147+
dhcpEnabled: false,
1148+
ipSyncEnabled: false,
1149+
ipAddress: '192.168.1.20',
1150+
subnetMask: '255.255.255.0',
1151+
defaultGateway: '192.168.1.1',
1152+
primaryDNS: '8.8.8.8'
1153+
}
1154+
1155+
service.patchWiredNetworkSettings('guid1', payload).subscribe()
1156+
1157+
const req = httpMock.expectOne(`${mockEnvironment.mpsServer}/api/v1/amt/networkSettings/wired/guid1`)
1158+
expect(req.request.method).toBe('PATCH')
1159+
expect(req.request.body).toEqual(payload)
1160+
req.flush(null)
1161+
})
1162+
})
1163+
1164+
describe('wireless network configuration endpoints', () => {
1165+
it('should get wireless state', () => {
1166+
const mockResponse = { state: 'WifiEnabledS0SxAC' }
1167+
1168+
service.getWirelessState('guid1').subscribe((response) => {
1169+
expect(response).toEqual(mockResponse as any)
1170+
})
1171+
1172+
const req = httpMock.expectOne(`${mockEnvironment.mpsServer}/api/v1/amt/networkSettings/wireless/state/guid1`)
1173+
expect(req.request.method).toBe('GET')
1174+
req.flush(mockResponse)
1175+
})
1176+
1177+
it('should request wireless state change', () => {
1178+
const payload = { state: 'WifiDisabled' }
1179+
1180+
service.requestWirelessStateChange('guid1', payload as any).subscribe((response) => {
1181+
expect(response).toEqual(payload as any)
1182+
})
1183+
1184+
const req = httpMock.expectOne(`${mockEnvironment.mpsServer}/api/v1/amt/networkSettings/wireless/state/guid1`)
1185+
expect(req.request.method).toBe('POST')
1186+
expect(req.request.body).toEqual(payload)
1187+
req.flush(payload)
1188+
})
1189+
1190+
it('should get profile sync setting', () => {
1191+
const mockResponse: WirelessProfileSyncResponse = {
1192+
localProfileSync: true,
1193+
uefiProfileSync: false,
1194+
uefiProfileSyncSupported: true
1195+
}
1196+
1197+
service.getWirelessProfileSync('guid1').subscribe((response) => {
1198+
expect(response).toEqual(mockResponse)
1199+
})
1200+
1201+
const req = httpMock.expectOne(
1202+
`${mockEnvironment.mpsServer}/api/v1/amt/networkSettings/wireless/profileSync/guid1`
1203+
)
1204+
expect(req.request.method).toBe('GET')
1205+
req.flush(mockResponse)
1206+
})
1207+
1208+
it('should update profile sync setting', () => {
1209+
const payload: WirelessProfileSyncRequest = {
1210+
localProfileSync: true,
1211+
uefiProfileSync: false
1212+
}
1213+
1214+
const mockResponse: WirelessProfileSyncResponse = {
1215+
localProfileSync: true,
1216+
uefiProfileSync: false,
1217+
uefiProfileSyncSupported: true
1218+
}
1219+
1220+
service.setWirelessProfileSync('guid1', payload).subscribe((response) => {
1221+
expect(response).toEqual(mockResponse)
1222+
})
1223+
1224+
const req = httpMock.expectOne(
1225+
`${mockEnvironment.mpsServer}/api/v1/amt/networkSettings/wireless/profileSync/guid1`
1226+
)
1227+
expect(req.request.method).toBe('POST')
1228+
expect(req.request.body).toEqual(payload)
1229+
req.flush(mockResponse)
1230+
})
1231+
1232+
it('should get wireless profiles', () => {
1233+
const mockResponse = [
1234+
{
1235+
profileName: 'office',
1236+
ssid: 'CorpNet',
1237+
authenticationMethod: 'WPA2PSK',
1238+
encryptionMethod: 'CCMP',
1239+
priority: 1
1240+
}
1241+
]
1242+
1243+
service.getWirelessProfiles('guid1').subscribe((response) => {
1244+
expect(response).toEqual(mockResponse as any)
1245+
})
1246+
1247+
const req = httpMock.expectOne(`${mockEnvironment.mpsServer}/api/v1/amt/networkSettings/wireless/profile/guid1`)
1248+
expect(req.request.method).toBe('GET')
1249+
req.flush(mockResponse)
1250+
})
1251+
1252+
it('should add wireless profile', () => {
1253+
const payload = {
1254+
profileName: 'office',
1255+
ssid: 'CorpNet',
1256+
authenticationMethod: 'WPA2PSK',
1257+
encryptionMethod: 'CCMP',
1258+
priority: 1,
1259+
password: 'password123'
1260+
}
1261+
1262+
service.addWirelessProfile('guid1', payload).subscribe()
1263+
1264+
const req = httpMock.expectOne(`${mockEnvironment.mpsServer}/api/v1/amt/networkSettings/wireless/profile/guid1`)
1265+
expect(req.request.method).toBe('POST')
1266+
expect(req.request.body).toEqual(payload)
1267+
req.flush(null)
1268+
})
1269+
1270+
it('should update wireless profile', () => {
1271+
const payload = {
1272+
profileName: 'office',
1273+
ssid: 'CorpNet-2',
1274+
authenticationMethod: 'WPA2PSK',
1275+
encryptionMethod: 'CCMP',
1276+
priority: 2,
1277+
password: 'password123'
1278+
}
1279+
1280+
service.updateWirelessProfile('guid1', payload).subscribe()
1281+
1282+
const req = httpMock.expectOne(`${mockEnvironment.mpsServer}/api/v1/amt/networkSettings/wireless/profile/guid1`)
1283+
expect(req.request.method).toBe('PATCH')
1284+
expect(req.request.body).toEqual(payload)
1285+
req.flush(null)
1286+
})
1287+
1288+
it('should delete wireless profile', () => {
1289+
service.deleteWirelessProfile('guid1', 'office profile').subscribe()
1290+
1291+
const req = httpMock.expectOne(
1292+
`${mockEnvironment.mpsServer}/api/v1/amt/networkSettings/wireless/profile/guid1/${encodeURIComponent('office profile')}`
1293+
)
1294+
expect(req.request.method).toBe('DELETE')
1295+
req.flush(null)
1296+
})
1297+
})
1298+
11281299
describe('getDeviceCertificate', () => {
11291300
it('should fetch device certificate', () => {
11301301
const mockResponse = { certificate: 'device-cert' }

src/app/devices/devices.service.ts

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,14 @@ import {
2626
IPSAlarmClockOccurrence,
2727
Certificates,
2828
NetworkConfig,
29+
WiredNetworkSettings,
30+
WiredNetworkConfigRequest,
31+
WirelessStateResponse,
32+
WirelessStateChangeRequest,
33+
WirelessProfileSyncRequest,
34+
WirelessProfileSyncResponse,
35+
DeviceWirelessProfileRequest,
36+
DeviceWirelessProfileResponse,
2937
TLSSettings,
3038
CertInfo,
3139
BootDetails,
@@ -589,6 +597,117 @@ export class DevicesService {
589597
})
590598
)
591599
}
600+
601+
getWiredNetworkSettings(guid: string): Observable<WiredNetworkSettings> {
602+
return this.http
603+
.get<WiredNetworkSettings>(`${environment.mpsServer}/api/v1/amt/networkSettings/wired/${guid}`)
604+
.pipe(
605+
catchError((err) => {
606+
throw err
607+
})
608+
)
609+
}
610+
611+
patchWiredNetworkSettings(guid: string, payload: WiredNetworkConfigRequest): Observable<void> {
612+
return this.http.patch<void>(`${environment.mpsServer}/api/v1/amt/networkSettings/wired/${guid}`, payload).pipe(
613+
catchError((err) => {
614+
throw err
615+
})
616+
)
617+
}
618+
619+
getWirelessState(guid: string): Observable<WirelessStateResponse> {
620+
return this.http
621+
.get<WirelessStateResponse>(`${environment.mpsServer}/api/v1/amt/networkSettings/wireless/state/${guid}`)
622+
.pipe(
623+
catchError((err) => {
624+
throw err
625+
})
626+
)
627+
}
628+
629+
requestWirelessStateChange(guid: string, payload: WirelessStateChangeRequest): Observable<WirelessStateResponse> {
630+
return this.http
631+
.post<WirelessStateResponse>(
632+
`${environment.mpsServer}/api/v1/amt/networkSettings/wireless/state/${guid}`,
633+
payload
634+
)
635+
.pipe(
636+
catchError((err) => {
637+
throw err
638+
})
639+
)
640+
}
641+
642+
getWirelessProfileSync(guid: string): Observable<WirelessProfileSyncResponse> {
643+
return this.http
644+
.get<WirelessProfileSyncResponse>(
645+
`${environment.mpsServer}/api/v1/amt/networkSettings/wireless/profileSync/${guid}`
646+
)
647+
.pipe(
648+
catchError((err) => {
649+
throw err
650+
})
651+
)
652+
}
653+
654+
setWirelessProfileSync(guid: string, payload: WirelessProfileSyncRequest): Observable<WirelessProfileSyncResponse> {
655+
return this.http
656+
.post<WirelessProfileSyncResponse>(
657+
`${environment.mpsServer}/api/v1/amt/networkSettings/wireless/profileSync/${guid}`,
658+
payload
659+
)
660+
.pipe(
661+
catchError((err) => {
662+
throw err
663+
})
664+
)
665+
}
666+
667+
getWirelessProfiles(guid: string): Observable<DeviceWirelessProfileResponse[]> {
668+
return this.http
669+
.get<
670+
DeviceWirelessProfileResponse[]
671+
>(`${environment.mpsServer}/api/v1/amt/networkSettings/wireless/profile/${guid}`)
672+
.pipe(
673+
catchError((err) => {
674+
throw err
675+
})
676+
)
677+
}
678+
679+
addWirelessProfile(guid: string, payload: DeviceWirelessProfileRequest): Observable<void> {
680+
return this.http
681+
.post<void>(`${environment.mpsServer}/api/v1/amt/networkSettings/wireless/profile/${guid}`, payload)
682+
.pipe(
683+
catchError((err) => {
684+
throw err
685+
})
686+
)
687+
}
688+
689+
updateWirelessProfile(guid: string, payload: DeviceWirelessProfileRequest): Observable<void> {
690+
return this.http
691+
.patch<void>(`${environment.mpsServer}/api/v1/amt/networkSettings/wireless/profile/${guid}`, payload)
692+
.pipe(
693+
catchError((err) => {
694+
throw err
695+
})
696+
)
697+
}
698+
699+
deleteWirelessProfile(guid: string, profileName: string): Observable<void> {
700+
return this.http
701+
.delete<void>(
702+
`${environment.mpsServer}/api/v1/amt/networkSettings/wireless/profile/${guid}/${encodeURIComponent(profileName)}`
703+
)
704+
.pipe(
705+
catchError((err) => {
706+
throw err
707+
})
708+
)
709+
}
710+
592711
getTLSSettings(guid: string): Observable<TLSSettings[]> {
593712
return this.http.get<any>(`${environment.mpsServer}/api/v1/amt/tls/${guid}`).pipe(
594713
catchError((err) => {

0 commit comments

Comments
 (0)