diff --git a/src/AzureIoTHub.Portal/Server/Controllers/CommandsController.cs b/src/AzureIoTHub.Portal/Server/Controllers/CommandsController.cs index 1dad2f86b..07f026856 100644 --- a/src/AzureIoTHub.Portal/Server/Controllers/CommandsController.cs +++ b/src/AzureIoTHub.Portal/Server/Controllers/CommandsController.cs @@ -33,23 +33,16 @@ public CommandsController( [HttpPost("{modelId}")] public async Task Post(string modelId, DeviceModelCommand command) { - try + TableEntity entity = new TableEntity() { - TableEntity entity = new TableEntity() - { - PartitionKey = modelId, - RowKey = command.Name - }; - this.deviceModelCommandMapper.UpdateTableEntity(entity, command); - await this.tableClientFactory - .GetDeviceCommands() - .AddEntityAsync(entity); - return this.Ok("Command successfully added"); - } - catch (Exception e) - { - return this.BadRequest(e.Message); - } + PartitionKey = modelId, + RowKey = command.Name + }; + this.deviceModelCommandMapper.UpdateTableEntity(entity, command); + await this.tableClientFactory + .GetDeviceCommands() + .AddEntityAsync(entity); + return this.Ok("Command successfully added"); } /// diff --git a/src/AzureIoTHub.Portal/Server/Controllers/ConfigsController.cs b/src/AzureIoTHub.Portal/Server/Controllers/ConfigsController.cs index dd3ba149c..19ef862a9 100644 --- a/src/AzureIoTHub.Portal/Server/Controllers/ConfigsController.cs +++ b/src/AzureIoTHub.Portal/Server/Controllers/ConfigsController.cs @@ -3,7 +3,9 @@ namespace AzureIoTHub.Portal.Server.Controllers { + using System; using System.Collections.Generic; + using System.Linq; using System.Threading.Tasks; using AzureIoTHub.Portal.Server.Helpers; using AzureIoTHub.Portal.Server.Services; @@ -17,18 +19,10 @@ namespace AzureIoTHub.Portal.Server.Controllers [Route("api/[controller]")] public class ConfigsController : ControllerBase { - private readonly ILogger logger; - - private readonly RegistryManager registryManager; private readonly ConfigsServices configService; - public ConfigsController( - ILogger logger, - ConfigsServices configService, - RegistryManager registryManager) + public ConfigsController(ConfigsServices configService) { - this.logger = logger; - this.registryManager = registryManager; this.configService = configService; } @@ -42,26 +36,21 @@ public async Task> Get() // Retrieve every Configurations, regardless of the parameter given... Why? // TODO : Check & fix this // List configList = await this.registryManager.GetConfigurationsAsync(0) as List; - List configList = await this.configService.GetAllConfigs() as List; + var configList = await this.configService.GetAllConfigs(); var results = new List(); // Azure Configurations may have different types: "Configuration", "Deployment" or "LayeredDeployment" foreach (Configuration config in configList) { - List moduleList = new (); + var moduleList = new List(); // Only deployments have modules. If it doesn't, it's a configuration and we don't want to keep it. if (config.Content.ModulesContent != null) { - // Retrieve the name of each module of this deployment - foreach (var module in config.Content.ModulesContent) + moduleList.AddRange(config.Content.ModulesContent.Select(x => new GatewayModule { - var newModule = new GatewayModule - { - ModuleName = module.Key - }; - moduleList.Add(newModule); - } + ModuleName = x.Key + })); ConfigListItem result = ConfigHelper.CreateConfigListItem(config, moduleList); results.Add(result); @@ -81,40 +70,38 @@ public async Task> Get() public async Task Get(string configurationID) { var config = await this.configService.GetConfigItem(configurationID); - List moduleList = new (); - if (config.Content.ModulesContent != null) + var moduleList = new List(); + + // Details of every modules are stored within the EdgeAgent module data + if (config.Content.ModulesContent != null + && config.Content.ModulesContent.TryGetValue("$edgeAgent", out IDictionary edgeAgentModule) + && edgeAgentModule.TryGetValue("properties.desired", out object edgeAgentDesiredProperties)) { - // Details of every modules are stored within the EdgeAgent module data - if (config.Content.ModulesContent.ContainsKey("$edgeAgent")) + // Converts the object to a JObject to access its properties more easily + JObject modObject = edgeAgentDesiredProperties as JObject; + + if (modObject == null) { - if (config.Content.ModulesContent["$edgeAgent"].ContainsKey("properties.desired")) - { - // Converts the object to a JObject to access its properties more easily - JObject modObject = config.Content.ModulesContent["$edgeAgent"]["properties.desired"] as JObject; + throw new InvalidOperationException("Could not parse properties.desired."); + } - // Adds regular modules to the list of modules - if (modObject.ContainsKey("modules")) - { - // Converts it to a JObject to be able to iterate through it - JObject modules = modObject["modules"] as JObject; - foreach (var m in modules) - { - GatewayModule newModule = ConfigHelper.CreateGatewayModule(config, m); - moduleList.Add(newModule); - } - } + // Adds regular modules to the list of modules + if (modObject.TryGetValue("modules", out JToken modules)) + { + foreach (var m in modules.Values()) + { + GatewayModule newModule = ConfigHelper.CreateGatewayModule(config, m); + moduleList.Add(newModule); + } + } - // Adds system modules to the list of modules - if (modObject.ContainsKey("systemModules")) - { - // Converts it to a JObject to be able to iterate through it - JObject systemModules = modObject["systemModules"] as JObject; - foreach (var sm in systemModules) - { - GatewayModule newModule = ConfigHelper.CreateGatewayModule(config, sm); - moduleList.Add(newModule); - } - } + // Adds system modules to the list of modules + if (modObject.TryGetValue("systemModules", out JToken systemModulesToken)) + { + foreach (var sm in systemModulesToken.Values()) + { + GatewayModule newModule = ConfigHelper.CreateGatewayModule(config, sm); + moduleList.Add(newModule); } } } diff --git a/src/AzureIoTHub.Portal/Server/Controllers/DeviceModelsController.cs b/src/AzureIoTHub.Portal/Server/Controllers/DeviceModelsController.cs index 0cff3027d..39b959955 100644 --- a/src/AzureIoTHub.Portal/Server/Controllers/DeviceModelsController.cs +++ b/src/AzureIoTHub.Portal/Server/Controllers/DeviceModelsController.cs @@ -148,24 +148,17 @@ public async Task Delete(string deviceModelID) .GetDeviceCommands() .Query(t => t.PartitionKey == deviceModel.ModelId); - foreach (var twin in deviceList) + if (deviceList.Any(x => DeviceHelper.RetrieveTagValue(x, "modelId") == deviceModel.ModelId)) { - if (DeviceHelper.RetrieveTagValue(twin, "modelId") == deviceModel.ModelId) - { - return this.Unauthorized("This model is already in use by a device and cannot be deleted."); - } + return this.Unauthorized("This model is already in use by a device and cannot be deleted."); } var commands = queryCommand.Select(item => this.deviceModelCommandMapper.GetDeviceModelCommand(item)).ToList(); - // if we have command - if (commands.Count > 0) + foreach (var item in commands) { - foreach (var item in commands) - { - _ = await this.tableClientFactory - .GetDeviceCommands().DeleteEntityAsync(deviceModelID, item.Name); - } + _ = await this.tableClientFactory + .GetDeviceCommands().DeleteEntityAsync(deviceModelID, item.Name); } // Image deletion @@ -192,12 +185,9 @@ await this.tableClientFactory await foreach (var page in commandsPage) { - foreach (var item in page.Values) + foreach (var item in page.Values.Where(x => !deviceModelObject.Commands.Any(c => c.Name == x.RowKey))) { - if (!deviceModelObject.Commands.Any(c => c.Name == item.RowKey)) - { - await commandsTable.DeleteEntityAsync(item.PartitionKey, item.RowKey); - } + await commandsTable.DeleteEntityAsync(item.PartitionKey, item.RowKey); } } diff --git a/src/AzureIoTHub.Portal/Server/Controllers/DevicesController.cs b/src/AzureIoTHub.Portal/Server/Controllers/DevicesController.cs index e566721e0..0f320093b 100644 --- a/src/AzureIoTHub.Portal/Server/Controllers/DevicesController.cs +++ b/src/AzureIoTHub.Portal/Server/Controllers/DevicesController.cs @@ -121,29 +121,21 @@ public async Task CreateDeviceAsync(DeviceDetails device) [HttpPut] public async Task UpdateDeviceAsync(DeviceDetails device) { - try - { - // Device status (enabled/disabled) has to be dealt with afterwards - Device currentDevice = await this.devicesService.GetDevice(device.DeviceID); - currentDevice.Status = device.IsEnabled ? DeviceStatus.Enabled : DeviceStatus.Disabled; + // Device status (enabled/disabled) has to be dealt with afterwards + Device currentDevice = await this.devicesService.GetDevice(device.DeviceID); + currentDevice.Status = device.IsEnabled ? DeviceStatus.Enabled : DeviceStatus.Disabled; - _ = await this.devicesService.UpdateDevice(currentDevice); + _ = await this.devicesService.UpdateDevice(currentDevice); - // Get the current twin from the hub, based on the device ID - Twin currentTwin = await this.devicesService.GetDeviceTwin(device.DeviceID); + // Get the current twin from the hub, based on the device ID + Twin currentTwin = await this.devicesService.GetDeviceTwin(device.DeviceID); - // Update the twin properties - this.deviceTwinMapper.UpdateTwin(currentTwin, device); + // Update the twin properties + this.deviceTwinMapper.UpdateTwin(currentTwin, device); - _ = await this.devicesService.UpdateDeviceTwin(device.DeviceID, currentTwin); + _ = await this.devicesService.UpdateDeviceTwin(device.DeviceID, currentTwin); - return this.Ok(); - } - catch (Exception e) - { - this.logger.LogError($"{device.DeviceID} - Update device failed", e); - return this.BadRequest(); - } + return this.Ok(); } /// @@ -154,16 +146,8 @@ public async Task UpdateDeviceAsync(DeviceDetails device) [HttpDelete("{deviceID}")] public async Task Delete(string deviceID) { - try - { - await this.devicesService.DeleteDevice(deviceID); - return this.Ok(); - } - catch (Exception e) - { - this.logger.LogError($"{deviceID} - Device deletion failed", e); - return this.BadRequest(); - } + await this.devicesService.DeleteDevice(deviceID); + return this.Ok(); } /// @@ -202,10 +186,6 @@ public async Task ExecuteCommand(string deviceId, string commandI return this.BadRequest("Something went wrong when executing the command."); } - catch (Exception e) - { - return this.BadRequest(e.Message); - } } } } diff --git a/src/AzureIoTHub.Portal/Server/Controllers/GatewaysController.cs b/src/AzureIoTHub.Portal/Server/Controllers/GatewaysController.cs index 2b9552614..ef5ef8d18 100644 --- a/src/AzureIoTHub.Portal/Server/Controllers/GatewaysController.cs +++ b/src/AzureIoTHub.Portal/Server/Controllers/GatewaysController.cs @@ -20,6 +20,7 @@ namespace AzureIoTHub.Portal.Server.Controllers using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using Newtonsoft.Json; + using Newtonsoft.Json.Linq; [ApiController] [Route("api/[controller]")] @@ -56,36 +57,23 @@ public GatewaysController( [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(List))] public async Task Get() { - try - { - // don't contain properties - IEnumerable devicesWithoutProperties = await this.devicesService.GetAllEdgeDeviceWithTags(); - // don't contain connected device - IEnumerable edgeDevices = await this.devicesService.GetAllEdgeDevice(); + // don't contain properties + IEnumerable devicesWithoutProperties = await this.devicesService.GetAllEdgeDeviceWithTags(); + // don't contain connected device + IEnumerable edgeDevices = await this.devicesService.GetAllEdgeDevice(); - List newGatewayList = new (); - int index = 0; + List newGatewayList = new (); + int index = 0; - foreach (Twin deviceTwin in edgeDevices) - { - GatewayListItem gateway = new () - { - DeviceId = deviceTwin.DeviceId, - Status = deviceTwin.Status.Value.ToString(), - Type = DeviceHelper.RetrieveTagValue(devicesWithoutProperties.ElementAt(index), "purpose"), - NbDevices = DeviceHelper.RetrieveConnectedDeviceCount(deviceTwin) - }; - - newGatewayList.Add(gateway); - index++; - } - - return this.Ok(newGatewayList); - } - catch (Exception e) + newGatewayList.AddRange(edgeDevices.Select(deviceTwin => new GatewayListItem { - return this.StatusCode(StatusCodes.Status400BadRequest, e.Message); - } + DeviceId = deviceTwin.DeviceId, + Status = deviceTwin.Status?.ToString(), + Type = DeviceHelper.RetrieveTagValue(devicesWithoutProperties.ElementAt(index++), "purpose"), + NbDevices = DeviceHelper.RetrieveConnectedDeviceCount(deviceTwin) + })); + + return this.Ok(newGatewayList); } /// @@ -106,10 +94,10 @@ public async Task Get(string deviceId) Gateway gateway = new () { DeviceId = deviceTwin.DeviceId, - Status = deviceTwin.Status.Value.ToString(), + Status = deviceTwin.Status?.ToString(), EndPoint = this.configuration["IoTDPS:ServiceEndpoint"], Scope = deviceTwin.DeviceScope, - Connection_state = deviceTwin.ConnectionState.Value.ToString(), + Connection_state = deviceTwin.ConnectionState?.ToString(), // we retrieve the symmetric Key // SymmetricKey = DeviceHelper.RetrieveSymmetricKey(deviceTwin.DeviceId, this.devicesService.GetDpsAttestionMechanism().Result), // We retrieve the values of tags @@ -131,23 +119,12 @@ public async Task Get(string deviceId) { return this.StatusCode(StatusCodes.Status404NotFound, e.Message); } - catch (Exception e) - { - return this.StatusCode(StatusCodes.Status500InternalServerError, e.Message); - } } [HttpGet("{deviceId}/{deviceType}/ConnectionString")] public async Task GetSymmetricKey(string deviceId, string deviceType = "unknown") { - try - { - return this.Ok(await this.connectionStringManager.GetSymmetricKey(deviceId, deviceType)); - } - catch (Exception e) - { - return this.BadRequest(e.Message); - } + return this.Ok(await this.connectionStringManager.GetSymmetricKey(deviceId, deviceType)); } /// @@ -175,10 +152,6 @@ public async Task CreateGatewayAsync(Gateway gateway) this.logger.LogInformation(e.Message); return this.StatusCode(StatusCodes.Status400BadRequest, e.Message); } - catch (Exception e) - { - return this.StatusCode(StatusCodes.Status500InternalServerError, e.Message); - } } /// @@ -189,28 +162,21 @@ public async Task CreateGatewayAsync(Gateway gateway) [HttpPut("{gateway}")] public async Task UpdateDeviceAsync(Gateway gateway) { - try - { - Device device = await this.devicesService.GetDevice(gateway.DeviceId); + Device device = await this.devicesService.GetDevice(gateway.DeviceId); - if (gateway.Status == DeviceStatus.Enabled.ToString()) - device.Status = DeviceStatus.Enabled; - else - device.Status = DeviceStatus.Disabled; + if (Enum.TryParse(gateway.Status, out DeviceStatus status)) + { + device.Status = status; + } - device = await this.devicesService.UpdateDevice(device); + device = await this.devicesService.UpdateDevice(device); - Twin deviceTwin = await this.devicesService.GetDeviceTwin(gateway.DeviceId); - deviceTwin.Tags["env"] = gateway.Environment; - deviceTwin = await this.devicesService.UpdateDeviceTwin(gateway.DeviceId, deviceTwin); + Twin deviceTwin = await this.devicesService.GetDeviceTwin(gateway.DeviceId); + deviceTwin.Tags["env"] = gateway.Environment; + deviceTwin = await this.devicesService.UpdateDeviceTwin(gateway.DeviceId, deviceTwin); - this.logger.LogInformation($"iot hub device was updated {device.Id}"); - return this.Ok(deviceTwin); - } - catch (Exception e) - { - return this.StatusCode(StatusCodes.Status400BadRequest, e.Message); - } + this.logger.LogInformation($"iot hub device was updated {device.Id}"); + return this.Ok(deviceTwin); } /// @@ -221,43 +187,34 @@ public async Task UpdateDeviceAsync(Gateway gateway) [HttpDelete("{deviceId}")] public async Task DeleteDeviceAsync(string deviceId) { - try - { - await this.devicesService.DeleteDevice(deviceId); - this.logger.LogInformation($"iot hub device was delete {deviceId}"); + await this.devicesService.DeleteDevice(deviceId); + this.logger.LogInformation($"iot hub device was delete {deviceId}"); - return this.Ok($"iot hub device was delete {deviceId}"); - } - catch (Exception e) - { - return this.StatusCode(StatusCodes.Status400BadRequest, e.Message); - } + return this.Ok($"iot hub device was delete {deviceId}"); } [HttpPost("{deviceId}/{moduleId}/{methodName}")] public async Task ExecuteMethode(GatewayModule module, string deviceId, string methodName) { - try - { - CloudToDeviceMethod method = new (methodName); - string payload = string.Empty; + CloudToDeviceMethod method = new (methodName); + string payload = string.Empty; - if (methodName == "RestartModule") + if (methodName == "RestartModule") + { + payload = JsonConvert.SerializeObject(new { - payload = JsonConvert.SerializeObject(new - { - id = module.ModuleName, - schemaVersion = module.Version - }); - } + id = module.ModuleName, + schemaVersion = module.Version + }); + } - if (methodName == "GetModuleLogs") + if (methodName == "GetModuleLogs") + { + payload = JsonConvert.SerializeObject(new { - payload = JsonConvert.SerializeObject(new + schemaVersion = module.Version, + items = new[] { - schemaVersion = module.Version, - items = new[] - { new { id = module.ModuleName, @@ -266,30 +223,22 @@ public async Task ExecuteMethode(GatewayModule module, string deviceI tail = 10 } } - }, - encoding = "none", - contentType = "json" - }); - } + }, + encoding = "none", + contentType = "json" + }); + } - method.SetPayloadJson(payload); + method.SetPayloadJson(payload); - CloudToDeviceMethodResult result = await this.devicesService.ExecuteC2DMethod(deviceId, method); - this.logger.LogInformation($"iot hub device : {deviceId} module : {module.ModuleName} execute methode {methodName}."); + CloudToDeviceMethodResult result = await this.devicesService.ExecuteC2DMethod(deviceId, method); + this.logger.LogInformation($"iot hub device : {deviceId} module : {module.ModuleName} execute methode {methodName}."); - return new C2Dresult() - { - Payload = result.GetPayloadAsJson(), - Status = result.Status - }; - } - catch (Exception e) + return new C2Dresult() { - return new C2Dresult() - { - Payload = e.Message - }; - } + Payload = result.GetPayloadAsJson(), + Status = result.Status + }; } /// @@ -301,19 +250,15 @@ public async Task ExecuteMethode(GatewayModule module, string deviceI private async Task RetrieveNbConnectedDevice(string deviceId) { IQuery query = this.registryManager.CreateQuery($"SELECT * FROM devices.modules WHERE devices.modules.moduleId = '$edgeHub' AND deviceId in ['{deviceId}']", 1); - IEnumerable deviceWithClient = await query.GetNextAsTwinAsync(); - int count = 0; - // récupération des informations sur les clients connecté à la gateway - foreach (Twin item in deviceWithClient) + Twin deviceWithClient = (await query.GetNextAsTwinAsync()).SingleOrDefault(); + var reportedProperties = JObject.Parse(deviceWithClient.Properties.Reported.ToJson()); + + if (reportedProperties.TryGetValue("clients", out JToken clients)) { - if (item.Properties.Reported.Contains("clients") && item.DeviceId == deviceId) - { - count = item.Properties.Reported["clients"].Count; - break; - } + return clients.Count(); } - return count; + return 0; } /// @@ -324,19 +269,17 @@ private async Task RetrieveNbConnectedDevice(string deviceId) private async Task RetrieveLastConfiguration(Twin twin) { ConfigItem item = new (); - if (twin.Configurations != null) + + if (twin.Configurations != null && twin.Configurations.Count > 0) { - if (twin.Configurations.Count > 0) + foreach (var config in twin.Configurations) { - foreach (var config in twin.Configurations) + Configuration confObj = await this.registryManager.GetConfigurationAsync(config.Key); + if (item.DateCreation < confObj.CreatedTimeUtc && config.Value.Status == ConfigurationStatus.Applied) { - Configuration confObj = await this.registryManager.GetConfigurationAsync(config.Key); - if (item.DateCreation < confObj.CreatedTimeUtc && config.Value.Status == ConfigurationStatus.Applied) - { - item.Name = config.Key; - item.DateCreation = confObj.CreatedTimeUtc; - item.Status = ConfigurationStatus.Applied.ToString(); - } + item.Name = config.Key; + item.DateCreation = confObj.CreatedTimeUtc; + item.Status = ConfigurationStatus.Applied.ToString(); } } } diff --git a/src/AzureIoTHub.Portal/Server/Filters/ApiRequiredScopeFilter.cs b/src/AzureIoTHub.Portal/Server/Filters/ApiRequiredScopeFilter.cs index ae61c2c41..6722b97e1 100644 --- a/src/AzureIoTHub.Portal/Server/Filters/ApiRequiredScopeFilter.cs +++ b/src/AzureIoTHub.Portal/Server/Filters/ApiRequiredScopeFilter.cs @@ -11,7 +11,7 @@ namespace AzureIoTHub.Portal.Server.Filters internal class ApiRequiredScopeFilter : ActionFilterAttribute { - private ConfigHandler configuration; + private readonly ConfigHandler configuration; internal ApiRequiredScopeFilter(ConfigHandler configuration) { diff --git a/src/AzureIoTHub.Portal/Server/Helpers/ConfigHelper.cs b/src/AzureIoTHub.Portal/Server/Helpers/ConfigHelper.cs index 01993fa25..b05e5db04 100644 --- a/src/AzureIoTHub.Portal/Server/Helpers/ConfigHelper.cs +++ b/src/AzureIoTHub.Portal/Server/Helpers/ConfigHelper.cs @@ -20,10 +20,12 @@ public static class ConfigHelper /// Corresponding metric value, or -1 if it doesn't exist. public static long RetrieveMetricValue(Configuration item, string metricName) { - if (item.SystemMetrics.Results.Keys.Contains(metricName)) - return item.SystemMetrics.Results[metricName]; - else - return -1; + if (item.SystemMetrics.Results.TryGetValue(metricName, out long result)) + { + return result; + } + + return -1; } /// @@ -54,13 +56,13 @@ public static ConfigListItem CreateConfigListItem(Configuration config, ListConfiguration object from Azure IoT Hub. /// Dictionnary containing the module's name and its properties. /// A module with all its details as a GatewayModule object. - public static GatewayModule CreateGatewayModule(Configuration config, KeyValuePair module) + public static GatewayModule CreateGatewayModule(Configuration config, JProperty module) { return new GatewayModule { - ModuleName = module.Key, - Version = (string)module.Value["settings"]["image"], - Status = (string)module.Value["status"], + ModuleName = module.Name, + Version = module.Value["settings"]["image"]?.Value(), + Status = module.Value["status"]?.Value(), EnvironmentVariables = GetEnvironmentVariables(module), ModuleIdentityTwinSettings = GetModuleIdentityTwinSettings(config, module) }; @@ -72,21 +74,16 @@ public static GatewayModule CreateGatewayModule(Configuration config, KeyValuePa /// Configuration object from Azure IoT Hub. /// Dictionnary containing the module's name and its properties. /// A dictionnary containing the settings and their corresponding values. - private static Dictionary GetModuleIdentityTwinSettings(Configuration config, KeyValuePair module) + private static Dictionary GetModuleIdentityTwinSettings(Configuration config, JToken module) { var twinSettings = new Dictionary(); - if (config.Content.ModulesContent != null) + if (config.Content.ModulesContent != null + && config.Content.ModulesContent.TryGetValue(module.Path, out IDictionary modulesContent)) { - // Only exists if the module contains an identity twin - if (config.Content.ModulesContent.ContainsKey(module.Key)) + foreach (var setting in modulesContent) { - // Gets the settings of the specific module based on its name (module.Key) - var myModuleTwin = config.Content.ModulesContent[module.Key]; - foreach (var setting in myModuleTwin) - { - twinSettings.Add(setting.Key, setting.Value.ToString()); - } + twinSettings.Add(setting.Key, setting.Value.ToString()); } } @@ -98,27 +95,24 @@ private static Dictionary GetModuleIdentityTwinSettings(Configur /// /// Dictionnary containing the module's name and its properties. /// A dictionnary containing the environment variables and their corresponding values. - private static Dictionary GetEnvironmentVariables(KeyValuePair module) + private static Dictionary GetEnvironmentVariables(JProperty module) { var envVariables = new Dictionary(); - // Converts the object to a JObject to access its properties more easily - JObject moduleProperties = module.Value as JObject; + var moduleProperties = module.Value as JObject; if (moduleProperties == null) { - throw new InvalidOperationException("Unable to parse module environment variables!"); + throw new InvalidOperationException($"Unable to parse {module.Name} module properties."); } // Only exists if the module contains environment variables - if (!moduleProperties.ContainsKey("env")) - { - return envVariables; - } - - foreach (JProperty val in moduleProperties["env"]) + if (moduleProperties.TryGetValue("env", out JToken environmentVariables)) { - envVariables.Add(val.Name, val["value"]?.ToString()); + foreach (JProperty val in environmentVariables) + { + envVariables.Add(val.Name, val.Value["value"].Value()); + } } return envVariables; diff --git a/src/AzureIoTHub.Portal/Server/Helpers/DeviceHelper.cs b/src/AzureIoTHub.Portal/Server/Helpers/DeviceHelper.cs index 1ecd0cb38..d4b1ace9b 100644 --- a/src/AzureIoTHub.Portal/Server/Helpers/DeviceHelper.cs +++ b/src/AzureIoTHub.Portal/Server/Helpers/DeviceHelper.cs @@ -11,6 +11,7 @@ namespace AzureIoTHub.Portal.Server.Helpers using AzureIoTHub.Portal.Shared.Models; using Microsoft.Azure.Devices.Provisioning.Service; using Microsoft.Azure.Devices.Shared; + using Newtonsoft.Json.Linq; public static class DeviceHelper { @@ -23,7 +24,13 @@ public static class DeviceHelper public static string RetrieveSymmetricKey(string deviceId, AttestationMechanism attestationMechanism) { // then we get the symmetricKey - SymmetricKeyAttestation symmetricKey = attestationMechanism.GetAttestation() as SymmetricKeyAttestation; + var symmetricKey = attestationMechanism.GetAttestation() as SymmetricKeyAttestation; + + if (symmetricKey == null) + { + throw new InvalidOperationException($"Cannot get symmetric key for {attestationMechanism.Type} attestation mechanism type."); + } + using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(symmetricKey.PrimaryKey)); return Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(deviceId))); @@ -63,23 +70,19 @@ public static void SetTagValue(Twin item, string tagName, string value) /// Checks if the specific property exists within the device twin, /// Returns the corresponding value if so, else returns null. /// - /// Device twin. + /// Device twin. /// Property to retrieve. /// Corresponding property value, or null if it doesn't exist. - public static string RetrieveDesiredPropertyValue(Twin item, string propertyName) + public static string RetrieveDesiredPropertyValue(Twin twin, string propertyName) { - if (item.Properties.Desired.Contains(propertyName)) - return item.Properties.Desired[propertyName]; - else - return null; + return twin.Properties.Desired.Contains(propertyName) ? + twin.Properties.Desired[propertyName] : null; } public static string RetrieveReportedPropertyValue(Twin twin, string propertyName) { - if (twin.Properties.Reported.Contains(propertyName)) - return twin.Properties.Reported[propertyName]; - else - return null; + return twin.Properties.Reported.Contains(propertyName) ? + twin.Properties.Reported[propertyName] : null; } /// @@ -90,12 +93,8 @@ public static string RetrieveReportedPropertyValue(Twin twin, string propertyNam /// the number of connected device. public static int RetrieveConnectedDeviceCount(Twin twin) { - if (twin.Properties.Reported.Contains("clients")) - { - return twin.Properties.Reported["clients"].Count; - } - - return 0; + return twin.Properties.Reported.Contains("clients") ? + twin.Properties.Reported["clients"].Count : 0; } /// @@ -107,10 +106,8 @@ public static int RetrieveConnectedDeviceCount(Twin twin) /// int. public static int RetrieveNbModuleCount(Twin twin, string deviceId) { - if (twin.Properties.Desired.Contains("modules") && twin.DeviceId == deviceId) - return twin.Properties.Desired["modules"].Count; - else - return 0; + return twin.Properties.Desired.Contains("modules") && twin.DeviceId == deviceId + ? twin.Properties.Desired["modules"].Count : 0; } /// @@ -122,15 +119,13 @@ public static int RetrieveNbModuleCount(Twin twin, string deviceId) /// string. public static string RetrieveRuntimeResponse(Twin twin, string deviceId) { - if (twin.Properties.Reported.Contains("systemModules") && twin.DeviceId == deviceId) + var reportedProperties = JObject.Parse(twin.Properties.Reported.ToJson()); + + if (reportedProperties.TryGetValue("systemModules", out JToken systemModules) + && systemModules.Value().TryGetValue("edgeAgent", out JToken edgeAgentModule) + && edgeAgentModule.Value().TryGetValue("runtimeStatus", out JToken runtimeStatus)) { - foreach (var element in twin.Properties.Reported["systemModules"]) - { - if (element.Key == "edgeAgent") - { - return element.Value["runtimeStatus"]; - } - } + return runtimeStatus.Value(); } return string.Empty; diff --git a/src/AzureIoTHub.Portal/Server/Managers/ConnectionStringManager.cs b/src/AzureIoTHub.Portal/Server/Managers/ConnectionStringManager.cs index 47852c73e..dbf49599a 100644 --- a/src/AzureIoTHub.Portal/Server/Managers/ConnectionStringManager.cs +++ b/src/AzureIoTHub.Portal/Server/Managers/ConnectionStringManager.cs @@ -3,6 +3,7 @@ namespace AzureIoTHub.Portal.Server.Managers { + using System; using System.Threading.Tasks; using AzureIoTHub.Portal.Server.Helpers; using Microsoft.Azure.Devices.Provisioning.Service; @@ -34,11 +35,7 @@ public async Task GetSymmetricKey(string deviceId, string deviceType) return DeviceHelper.RetrieveSymmetricKey(deviceId, attestationMechanism); } - throw new System.Exception(e.Message); - } - catch (System.Exception e) - { - throw new System.Exception(e.Message); + throw new InvalidOperationException("Failed to get symmetricKey.", e); } } } diff --git a/src/AzureIoTHub.Portal/Server/Managers/DeviceProvisioningServiceManager.cs b/src/AzureIoTHub.Portal/Server/Managers/DeviceProvisioningServiceManager.cs index 6de795058..b9065c78f 100644 --- a/src/AzureIoTHub.Portal/Server/Managers/DeviceProvisioningServiceManager.cs +++ b/src/AzureIoTHub.Portal/Server/Managers/DeviceProvisioningServiceManager.cs @@ -67,14 +67,9 @@ public async Task CreateEnrollmentGroupAsync(string deviceType) /// AttestationMechanism. public async Task GetAttestationMechanism(string deviceType) { - if (deviceType == "LoRa Device") - { - return await this.dps.GetEnrollmentGroupAttestationAsync(this.config.DPSLoRaEnrollmentGroup); - } - else - { - return await this.dps.GetEnrollmentGroupAttestationAsync(this.config.DPSDefaultEnrollmentGroup); - } + return deviceType == "LoRa Device" ? + await this.dps.GetEnrollmentGroupAttestationAsync(this.config.DPSLoRaEnrollmentGroup) : + await this.dps.GetEnrollmentGroupAttestationAsync(this.config.DPSDefaultEnrollmentGroup); } private static string GenerateKey()