diff --git a/src/AzureIoTHub.Portal.Client/Pages/EdgeDevices/EdgeDeviceListPage.razor b/src/AzureIoTHub.Portal.Client/Pages/EdgeDevices/EdgeDeviceListPage.razor index dc35333dc..15148b0c0 100644 --- a/src/AzureIoTHub.Portal.Client/Pages/EdgeDevices/EdgeDeviceListPage.razor +++ b/src/AzureIoTHub.Portal.Client/Pages/EdgeDevices/EdgeDeviceListPage.razor @@ -122,7 +122,7 @@ - + @@ -269,23 +269,14 @@ internal async Task ChangeModel(IoTEdgeModelListItem edgeModel) { - try - { - this._edgeModel = edgeModel; - if (edgeModel == null || string.IsNullOrWhiteSpace(edgeModel.ModelId)) - { - return; - } + this._edgeModel = edgeModel; - } - catch (ProblemDetailsException exception) + if (edgeModel == null || string.IsNullOrWhiteSpace(edgeModel.ModelId)) { - Error?.ProcessProblemDetails(exception); - } - finally - { - await InvokeAsync(StateHasChanged); + return; } + + await InvokeAsync(StateHasChanged); } } diff --git a/src/AzureIoTHub.Portal.Infrastructure/AzureIoTHub.Portal.Infrastructure.csproj b/src/AzureIoTHub.Portal.Infrastructure/AzureIoTHub.Portal.Infrastructure.csproj index 76a4ca56c..49df17ec8 100644 --- a/src/AzureIoTHub.Portal.Infrastructure/AzureIoTHub.Portal.Infrastructure.csproj +++ b/src/AzureIoTHub.Portal.Infrastructure/AzureIoTHub.Portal.Infrastructure.csproj @@ -8,6 +8,7 @@ + diff --git a/src/AzureIoTHub.Portal.Infrastructure/PortalDbContext.cs b/src/AzureIoTHub.Portal.Infrastructure/PortalDbContext.cs index daed92731..d3823f5b9 100644 --- a/src/AzureIoTHub.Portal.Infrastructure/PortalDbContext.cs +++ b/src/AzureIoTHub.Portal.Infrastructure/PortalDbContext.cs @@ -4,6 +4,7 @@ namespace AzureIoTHub.Portal.Infrastructure { using AzureIoTHub.Portal.Domain.Entities; + using EntityFramework.Exceptions.PostgreSQL; using Microsoft.EntityFrameworkCore; @@ -32,5 +33,11 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + _ = optionsBuilder.UseExceptionProcessor(); + base.OnConfiguring(optionsBuilder); + } } } diff --git a/src/AzureIoTHub.Portal.Server/AzureIoTHub.Portal.Server.csproj b/src/AzureIoTHub.Portal.Server/AzureIoTHub.Portal.Server.csproj index bc2b1cfe1..bf8b87393 100644 --- a/src/AzureIoTHub.Portal.Server/AzureIoTHub.Portal.Server.csproj +++ b/src/AzureIoTHub.Portal.Server/AzureIoTHub.Portal.Server.csproj @@ -27,6 +27,7 @@ + diff --git a/src/AzureIoTHub.Portal.Server/Services/DeviceModelPropertiesService.cs b/src/AzureIoTHub.Portal.Server/Services/DeviceModelPropertiesService.cs index 84040ac46..d41ec4343 100644 --- a/src/AzureIoTHub.Portal.Server/Services/DeviceModelPropertiesService.cs +++ b/src/AzureIoTHub.Portal.Server/Services/DeviceModelPropertiesService.cs @@ -9,7 +9,6 @@ namespace AzureIoTHub.Portal.Server.Services using AzureIoTHub.Portal.Domain.Entities; using Domain.Exceptions; using Domain.Repositories; - using Microsoft.EntityFrameworkCore; public class DeviceModelPropertiesService : IDeviceModelPropertiesService { @@ -43,16 +42,9 @@ public async Task SavePropertiesForModel(string modelId, IEnumerable AssertModelExists(string deviceModelId) diff --git a/src/AzureIoTHub.Portal.Server/Services/DeviceModelService.cs b/src/AzureIoTHub.Portal.Server/Services/DeviceModelService.cs index 8f1c04b09..1cc760e19 100644 --- a/src/AzureIoTHub.Portal.Server/Services/DeviceModelService.cs +++ b/src/AzureIoTHub.Portal.Server/Services/DeviceModelService.cs @@ -17,7 +17,6 @@ namespace AzureIoTHub.Portal.Server.Services using Microsoft.AspNetCore.Http; using Microsoft.Azure.Devices.Shared; using Helpers; - using Microsoft.EntityFrameworkCore; public class DeviceModelService : IDeviceModelService where TListItem : class, IDeviceModel @@ -81,83 +80,62 @@ public async Task GetDeviceModel(string deviceModelId) public async Task CreateDeviceModel(TModel deviceModel) { - try - { - var deviceModelEntity = this.mapper.Map(deviceModel); + var deviceModelEntity = this.mapper.Map(deviceModel); - await this.deviceModelRepository.InsertAsync(deviceModelEntity); - await this.unitOfWork.SaveAsync(); + await this.deviceModelRepository.InsertAsync(deviceModelEntity); + await this.unitOfWork.SaveAsync(); - await CreateDeviceModelConfiguration(deviceModel); - } - catch (DbUpdateException e) - { - throw new InternalServerErrorException($"Unable to create the device model {deviceModel.Name}", e); - } + await CreateDeviceModelConfiguration(deviceModel); } public async Task UpdateDeviceModel(TModel deviceModel) { - try - { - var deviceModelEntity = await this.deviceModelRepository.GetByIdAsync(deviceModel.ModelId); + var deviceModelEntity = await this.deviceModelRepository.GetByIdAsync(deviceModel.ModelId); - if (deviceModelEntity == null) - { - throw new ResourceNotFoundException($"The device model {deviceModel.ModelId} doesn't exist"); - } + if (deviceModelEntity == null) + { + throw new ResourceNotFoundException($"The device model {deviceModel.ModelId} doesn't exist"); + } - _ = this.mapper.Map(deviceModel, deviceModelEntity); + _ = this.mapper.Map(deviceModel, deviceModelEntity); - this.deviceModelRepository.Update(deviceModelEntity); - await this.unitOfWork.SaveAsync(); + this.deviceModelRepository.Update(deviceModelEntity); + await this.unitOfWork.SaveAsync(); - await CreateDeviceModelConfiguration(deviceModel); - } - catch (DbUpdateException e) - { - throw new InternalServerErrorException($"Unable to update the device model {deviceModel.Name}", e); - } + await CreateDeviceModelConfiguration(deviceModel); } public async Task DeleteDeviceModel(string deviceModelId) { - try - { - var deviceModelEntity = await this.deviceModelRepository.GetByIdAsync(deviceModelId); + var deviceModelEntity = await this.deviceModelRepository.GetByIdAsync(deviceModelId); - if (deviceModelEntity == null) - { - return; - } + if (deviceModelEntity == null) + { + return; + } - var devices = await this.externalDeviceService.GetAllDevice(); + var devices = await this.externalDeviceService.GetAllDevice(); - if (devices.Items.Any(x => DeviceHelper.RetrieveTagValue(x, "modelId") == deviceModelId)) - { - throw new ResourceAlreadyExistsException( - $"The device model {deviceModelId} is already in use by a device and cannot be deleted"); - } + if (devices.Items.Any(x => DeviceHelper.RetrieveTagValue(x, "modelId") == deviceModelId)) + { + throw new ResourceAlreadyExistsException( + $"The device model {deviceModelId} is already in use by a device and cannot be deleted"); + } - var deviceModelCommands = this.deviceModelCommandRepository.GetAll().Where(command => + var deviceModelCommands = this.deviceModelCommandRepository.GetAll().Where(command => command.DeviceModelId.Equals(deviceModelId, StringComparison.Ordinal)).ToList(); - foreach (var deviceModelCommand in deviceModelCommands) - { - this.deviceModelCommandRepository.Delete(deviceModelCommand.Id); - } + foreach (var deviceModelCommand in deviceModelCommands) + { + this.deviceModelCommandRepository.Delete(deviceModelCommand.Id); + } - // Image deletion - await this.deviceModelImageManager.DeleteDeviceModelImageAsync(deviceModelId); + // Image deletion + await this.deviceModelImageManager.DeleteDeviceModelImageAsync(deviceModelId); - this.deviceModelRepository.Delete(deviceModelId); + this.deviceModelRepository.Delete(deviceModelId); - await this.unitOfWork.SaveAsync(); - } - catch (DbUpdateException e) - { - throw new InternalServerErrorException($"Unable to delete the device model {deviceModelId}", e); - } + await this.unitOfWork.SaveAsync(); } public Task GetDeviceModelAvatar(string deviceModelId) diff --git a/src/AzureIoTHub.Portal.Server/Services/DeviceService.cs b/src/AzureIoTHub.Portal.Server/Services/DeviceService.cs index 6a1defc9d..30a2b0b85 100644 --- a/src/AzureIoTHub.Portal.Server/Services/DeviceService.cs +++ b/src/AzureIoTHub.Portal.Server/Services/DeviceService.cs @@ -11,7 +11,6 @@ namespace AzureIoTHub.Portal.Server.Services using Managers; using Infrastructure; using AzureIoTHub.Portal.Domain.Entities; - using Microsoft.EntityFrameworkCore; using Domain; using Mappers; @@ -61,74 +60,53 @@ public override async Task GetDevice(string deviceId) protected override async Task CreateDeviceInDatabase(DeviceDetails device) { - try - { - var deviceEntity = this.mapper.Map(device); + var deviceEntity = this.mapper.Map(device); - await this.deviceRepository.InsertAsync(deviceEntity); - await this.unitOfWork.SaveAsync(); + await this.deviceRepository.InsertAsync(deviceEntity); + await this.unitOfWork.SaveAsync(); - return device; - } - catch (DbUpdateException e) - { - throw new InternalServerErrorException($"Unable to create the device {device.DeviceName}", e); - } + return device; } protected override async Task UpdateDeviceInDatabase(DeviceDetails device) { - try - { - var deviceEntity = await this.deviceRepository.GetByIdAsync(device.DeviceID); + var deviceEntity = await this.deviceRepository.GetByIdAsync(device.DeviceID); - if (deviceEntity == null) - { - throw new ResourceNotFoundException($"The device {device.DeviceID} doesn't exist"); - } + if (deviceEntity == null) + { + throw new ResourceNotFoundException($"The device {device.DeviceID} doesn't exist"); + } - foreach (var deviceTagEntity in deviceEntity.Tags) - { - this.deviceTagValueRepository.Delete(deviceTagEntity.Id); - } + foreach (var deviceTagEntity in deviceEntity.Tags) + { + this.deviceTagValueRepository.Delete(deviceTagEntity.Id); + } - _ = this.mapper.Map(device, deviceEntity); + _ = this.mapper.Map(device, deviceEntity); - this.deviceRepository.Update(deviceEntity); - await this.unitOfWork.SaveAsync(); + this.deviceRepository.Update(deviceEntity); + await this.unitOfWork.SaveAsync(); - return device; - } - catch (DbUpdateException e) - { - throw new InternalServerErrorException($"Unable to update the device {device.DeviceName}", e); - } + return device; } protected override async Task DeleteDeviceInDatabase(string deviceId) { - try - { - var deviceEntity = await this.deviceRepository.GetByIdAsync(deviceId); - - if (deviceEntity == null) - { - return; - } - - foreach (var deviceTagEntity in deviceEntity.Tags) - { - this.deviceTagValueRepository.Delete(deviceTagEntity.Id); - } - - this.deviceRepository.Delete(deviceId); + var deviceEntity = await this.deviceRepository.GetByIdAsync(deviceId); - await this.unitOfWork.SaveAsync(); + if (deviceEntity == null) + { + return; } - catch (DbUpdateException e) + + foreach (var deviceTagEntity in deviceEntity.Tags) { - throw new InternalServerErrorException($"Unable to delete the device {deviceId}", e); + this.deviceTagValueRepository.Delete(deviceTagEntity.Id); } + + this.deviceRepository.Delete(deviceId); + + await this.unitOfWork.SaveAsync(); } } } diff --git a/src/AzureIoTHub.Portal.Server/Services/EdgeDevicesService.cs b/src/AzureIoTHub.Portal.Server/Services/EdgeDevicesService.cs index 839c33dea..7106bf89d 100644 --- a/src/AzureIoTHub.Portal.Server/Services/EdgeDevicesService.cs +++ b/src/AzureIoTHub.Portal.Server/Services/EdgeDevicesService.cs @@ -13,7 +13,6 @@ namespace AzureIoTHub.Portal.Server.Services using AzureIoTHub.Portal.Domain.Entities; using AzureIoTHub.Portal.Domain.Exceptions; using AzureIoTHub.Portal.Domain.Repositories; - using AzureIoTHub.Portal.Infrastructure; using AzureIoTHub.Portal.Infrastructure.Repositories; using AzureIoTHub.Portal.Models.v10; using AzureIoTHub.Portal.Server.Helpers; @@ -34,7 +33,6 @@ public class EdgeDevicesService : IEdgeDevicesService private readonly IDeviceTagService deviceTagService; - private readonly PortalDbContext portalDbContext; private readonly IMapper mapper; private readonly IUnitOfWork unitOfWork; private readonly IEdgeDeviceRepository edgeDeviceRepository; @@ -44,7 +42,6 @@ public class EdgeDevicesService : IEdgeDevicesService public EdgeDevicesService( IExternalDeviceService externalDevicesService, IDeviceTagService deviceTagService, - PortalDbContext portalDbContext, IMapper mapper, IUnitOfWork unitOfWork, IEdgeDeviceRepository edgeDeviceRepository, @@ -53,7 +50,6 @@ public EdgeDevicesService( { this.externalDevicesService = externalDevicesService; this.deviceTagService = deviceTagService; - this.portalDbContext = portalDbContext; this.mapper = mapper; this.unitOfWork = unitOfWork; this.edgeDeviceRepository = edgeDeviceRepository; @@ -169,19 +165,12 @@ public async Task CreateEdgeDevice(IoTEdgeDevice edgeDevice) private async Task CreateEdgeDeviceInDatabase(IoTEdgeDevice device) { - try - { - var edgeDeviceEntity = this.mapper.Map(device); + var edgeDeviceEntity = this.mapper.Map(device); - await this.edgeDeviceRepository.InsertAsync(edgeDeviceEntity); - await this.unitOfWork.SaveAsync(); + await this.edgeDeviceRepository.InsertAsync(edgeDeviceEntity); + await this.unitOfWork.SaveAsync(); - return device; - } - catch (DbUpdateException e) - { - throw new InternalServerErrorException($"Unable to create the device {device.DeviceName}", e); - } + return device; } /// @@ -211,31 +200,24 @@ public async Task UpdateEdgeDevice(IoTEdgeDevice edgeDevice) private async Task UpdateEdgeDeviceInDatabase(IoTEdgeDevice device) { - try - { - var edgeDeviceEntity = await this.edgeDeviceRepository.GetByIdAsync(device.DeviceId); + var edgeDeviceEntity = await this.edgeDeviceRepository.GetByIdAsync(device.DeviceId); - if (edgeDeviceEntity == null) - { - throw new ResourceNotFoundException($"The device {device.DeviceId} doesn't exist"); - } + if (edgeDeviceEntity == null) + { + throw new ResourceNotFoundException($"The device {device.DeviceId} doesn't exist"); + } - foreach (var deviceTagEntity in edgeDeviceEntity.Tags) - { - this.deviceTagValueRepository.Delete(deviceTagEntity.Id); - } + foreach (var deviceTagEntity in edgeDeviceEntity.Tags) + { + this.deviceTagValueRepository.Delete(deviceTagEntity.Id); + } - _ = this.mapper.Map(device, edgeDeviceEntity); + _ = this.mapper.Map(device, edgeDeviceEntity); - this.edgeDeviceRepository.Update(edgeDeviceEntity); - await this.unitOfWork.SaveAsync(); + this.edgeDeviceRepository.Update(edgeDeviceEntity); + await this.unitOfWork.SaveAsync(); - return device; - } - catch (DbUpdateException e) - { - throw new InternalServerErrorException($"Unable to create the device {device.DeviceName}", e); - } + return device; } public async Task DeleteEdgeDeviceAsync(string deviceId) @@ -247,28 +229,21 @@ public async Task DeleteEdgeDeviceAsync(string deviceId) public async Task DeleteEdgeDeviceInDatabase(string deviceId) { - try - { - var edgeDeviceEntity = await this.edgeDeviceRepository.GetByIdAsync(deviceId); - - if (edgeDeviceEntity == null) - { - return; - } - - foreach (var deviceTagEntity in edgeDeviceEntity.Tags) - { - this.deviceTagValueRepository.Delete(deviceTagEntity.Id); - } + var edgeDeviceEntity = await this.edgeDeviceRepository.GetByIdAsync(deviceId); - this.edgeDeviceRepository.Delete(deviceId); - - await this.unitOfWork.SaveAsync(); + if (edgeDeviceEntity == null) + { + return; } - catch (DbUpdateException e) + + foreach (var deviceTagEntity in edgeDeviceEntity.Tags) { - throw new InternalServerErrorException($"Unable to delete the device {deviceId}", e); + this.deviceTagValueRepository.Delete(deviceTagEntity.Id); } + + this.edgeDeviceRepository.Delete(deviceId); + + await this.unitOfWork.SaveAsync(); } /// diff --git a/src/AzureIoTHub.Portal.Server/Services/EdgeModelService.cs b/src/AzureIoTHub.Portal.Server/Services/EdgeModelService.cs index d7e11ee9d..1e0ffcf8d 100644 --- a/src/AzureIoTHub.Portal.Server/Services/EdgeModelService.cs +++ b/src/AzureIoTHub.Portal.Server/Services/EdgeModelService.cs @@ -14,7 +14,6 @@ namespace AzureIoTHub.Portal.Server.Services using AzureIoTHub.Portal.Domain.Repositories; using AzureIoTHub.Portal.Models.v10; using Microsoft.AspNetCore.Http; - using Microsoft.EntityFrameworkCore; using AzureIoTHub.Portal.Server.Managers; using AzureIoTHub.Portal.Shared.Models.v10; @@ -84,23 +83,16 @@ public IEnumerable GetEdgeModels() /// public async Task CreateEdgeModel(IoTEdgeModel edgeModel) { - try + var edgeModelEntity = await this.edgeModelRepository.GetByIdAsync(edgeModel?.ModelId); + if (edgeModelEntity == null) { - var edgeModelEntity = await this.edgeModelRepository.GetByIdAsync(edgeModel?.ModelId); - if (edgeModelEntity == null) - { - edgeModelEntity = this.mapper.Map(edgeModel); - await this.edgeModelRepository.InsertAsync(edgeModelEntity); - await this.unitOfWork.SaveAsync(); - } - else - { - throw new ResourceAlreadyExistsException($"The edge model with id {edgeModel?.ModelId} already exists"); - } + edgeModelEntity = this.mapper.Map(edgeModel); + await this.edgeModelRepository.InsertAsync(edgeModelEntity); + await this.unitOfWork.SaveAsync(); } - catch (DbUpdateException e) + else { - throw new InternalServerErrorException($"Unable to create the device model with id {edgeModel?.ModelId}", e); + throw new ResourceAlreadyExistsException($"The edge model with id {edgeModel?.ModelId} already exists"); } await SaveModuleCommands(edgeModel); @@ -124,24 +116,17 @@ public async Task SaveModuleCommands(IoTEdgeModel deviceModelObject) Name = cmd.Name, })).ToArray(); - try + var existingCommands = this.commandRepository.GetAll().Where(x => x.EdgeDeviceModelId == deviceModelObject.ModelId).ToList(); + foreach (var command in existingCommands) { - var existingCommands = this.commandRepository.GetAll().Where(x => x.EdgeDeviceModelId == deviceModelObject.ModelId).ToList(); - foreach (var command in existingCommands) - { - this.commandRepository.Delete(command.Id); - } - - foreach (var cmd in moduleCommands) - { - await this.commandRepository.InsertAsync(this.mapper.Map(cmd)); - } - await this.unitOfWork.SaveAsync(); + this.commandRepository.Delete(command.Id); } - catch (DbUpdateException e) + + foreach (var cmd in moduleCommands) { - throw new InternalServerErrorException("Unable to save commands", e); + await this.commandRepository.InsertAsync(this.mapper.Map(cmd)); } + await this.unitOfWork.SaveAsync(); } /// @@ -200,26 +185,19 @@ public async Task GetEdgeModel(string modelId) /// public async Task UpdateEdgeModel(IoTEdgeModel edgeModel) { - try + var edgeModelEntity = await this.edgeModelRepository.GetByIdAsync(edgeModel?.ModelId); + if (edgeModelEntity == null) { - var edgeModelEntity = await this.edgeModelRepository.GetByIdAsync(edgeModel?.ModelId); - if (edgeModelEntity == null) - { - throw new ResourceNotFoundException($"The edge model with id {edgeModel?.ModelId} doesn't exist"); - } + throw new ResourceNotFoundException($"The edge model with id {edgeModel?.ModelId} doesn't exist"); + } - _ = this.mapper.Map(edgeModel, edgeModelEntity); - this.edgeModelRepository.Update(edgeModelEntity); + _ = this.mapper.Map(edgeModel, edgeModelEntity); + this.edgeModelRepository.Update(edgeModelEntity); - await this.unitOfWork.SaveAsync(); + await this.unitOfWork.SaveAsync(); - await SaveModuleCommands(edgeModel); - await this.configService.RollOutEdgeModelConfiguration(edgeModel); - } - catch (DbUpdateException e) - { - throw new InternalServerErrorException($"Unable to create the device model with id {edgeModel?.ModelId}", e); - } + await SaveModuleCommands(edgeModel); + await this.configService.RollOutEdgeModelConfiguration(edgeModel); } /// @@ -232,29 +210,21 @@ public async Task DeleteEdgeModel(string edgeModelId) { if (!string.IsNullOrEmpty(edgeModelId)) { - try - { - this.edgeModelRepository.Delete(edgeModelId); - - var existingCommands = this.commandRepository.GetAll().Where(x => x.EdgeDeviceModelId == edgeModelId).ToList(); - foreach (var command in existingCommands) - { - this.commandRepository.Delete(command.Id); - } + this.edgeModelRepository.Delete(edgeModelId); - await this.unitOfWork.SaveAsync(); + var existingCommands = this.commandRepository.GetAll().Where(x => x.EdgeDeviceModelId == edgeModelId).ToList(); + foreach (var command in existingCommands) + { + this.commandRepository.Delete(command.Id); + } - var config = this.configService.GetIoTEdgeConfigurations().Result.FirstOrDefault(x => x.Id.StartsWith(edgeModelId, StringComparison.Ordinal)); + await this.unitOfWork.SaveAsync(); - if (config != null) - { - await this.configService.DeleteConfiguration(config.Id); - } - } + var config = this.configService.GetIoTEdgeConfigurations().Result.FirstOrDefault(x => x.Id.StartsWith(edgeModelId, StringComparison.Ordinal)); - catch (DbUpdateException e) + if (config != null) { - throw new InternalServerErrorException($"Unable to delete the edge model with {edgeModelId} model entity.", e); + await this.configService.DeleteConfiguration(config.Id); } } } diff --git a/src/AzureIoTHub.Portal.Server/Services/LoRaWANCommandService.cs b/src/AzureIoTHub.Portal.Server/Services/LoRaWANCommandService.cs index dedf0c40e..0ed3545bf 100644 --- a/src/AzureIoTHub.Portal.Server/Services/LoRaWANCommandService.cs +++ b/src/AzureIoTHub.Portal.Server/Services/LoRaWANCommandService.cs @@ -12,7 +12,6 @@ namespace AzureIoTHub.Portal.Server.Services using Domain.Exceptions; using Domain.Repositories; using Managers; - using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Models.v10.LoRaWAN; @@ -42,36 +41,29 @@ public LoRaWANCommandService(IMapper mapper, public async Task PostDeviceModelCommands(string id, DeviceModelCommandDto[] commands) { - try - { - var deviceModelEntity = await this.deviceModelRepository.GetByIdAsync(id); - - if (deviceModelEntity == null) - { - throw new ResourceNotFoundException($"The device model {id} doesn't exist"); - } - - var existingDeviceModelCommands = await GetDeviceModelCommandsFromModel(id); + var deviceModelEntity = await this.deviceModelRepository.GetByIdAsync(id); - foreach (var deviceModelCommand in existingDeviceModelCommands) - { - this.deviceModelCommandRepository.Delete(deviceModelCommand.Id); - } - - foreach (var deviceModelCommand in commands) - { - var deviceModelCommandEntity = this.mapper.Map(deviceModelCommand); - deviceModelCommandEntity.DeviceModelId = id; + if (deviceModelEntity == null) + { + throw new ResourceNotFoundException($"The device model {id} doesn't exist"); + } - await this.deviceModelCommandRepository.InsertAsync(deviceModelCommandEntity); - } + var existingDeviceModelCommands = await GetDeviceModelCommandsFromModel(id); - await this.unitOfWork.SaveAsync(); + foreach (var deviceModelCommand in existingDeviceModelCommands) + { + this.deviceModelCommandRepository.Delete(deviceModelCommand.Id); } - catch (DbUpdateException e) + + foreach (var deviceModelCommand in commands) { - throw new InternalServerErrorException($"Unable to create the commands for the model with id {id}", e); + var deviceModelCommandEntity = this.mapper.Map(deviceModelCommand); + deviceModelCommandEntity.DeviceModelId = id; + + await this.deviceModelCommandRepository.InsertAsync(deviceModelCommandEntity); } + + await this.unitOfWork.SaveAsync(); } public Task GetDeviceModelCommandsFromModel(string id) diff --git a/src/AzureIoTHub.Portal.Server/Services/LoRaWANConcentratorService.cs b/src/AzureIoTHub.Portal.Server/Services/LoRaWANConcentratorService.cs index f73ab56c7..95bd26cfe 100644 --- a/src/AzureIoTHub.Portal.Server/Services/LoRaWANConcentratorService.cs +++ b/src/AzureIoTHub.Portal.Server/Services/LoRaWANConcentratorService.cs @@ -12,7 +12,6 @@ namespace AzureIoTHub.Portal.Server.Services using Managers; using Mappers; using Microsoft.Azure.Devices; - using Microsoft.EntityFrameworkCore; using Models.v10.LoRaWAN; using Shared.Models.v1._0; @@ -122,62 +121,41 @@ public async Task DeleteDeviceAsync(string deviceId) private async Task CreateDeviceInDatabase(ConcentratorDto concentrator) { - try - { - var concentratorEntity = this.mapper.Map(concentrator); - await this.concentratorRepository.InsertAsync(concentratorEntity); - await this.unitOfWork.SaveAsync(); - return concentrator; - } - catch (DbUpdateException e) - { - throw new InternalServerErrorException($"Unable to create the concentrator {concentrator.DeviceName}", e); - } + var concentratorEntity = this.mapper.Map(concentrator); + await this.concentratorRepository.InsertAsync(concentratorEntity); + await this.unitOfWork.SaveAsync(); + return concentrator; } private async Task UpdateDeviceInDatabase(ConcentratorDto concentrator) { - try - { - var concentratorEntity = await this.concentratorRepository.GetByIdAsync(concentrator.DeviceId); + var concentratorEntity = await this.concentratorRepository.GetByIdAsync(concentrator.DeviceId); - if (concentratorEntity == null) - { - throw new ResourceNotFoundException($"The device {concentrator.DeviceId} doesn't exist"); - } + if (concentratorEntity == null) + { + throw new ResourceNotFoundException($"The device {concentrator.DeviceId} doesn't exist"); + } - _ = this.mapper.Map(concentrator, concentratorEntity); + _ = this.mapper.Map(concentrator, concentratorEntity); - this.concentratorRepository.Update(concentratorEntity); - await this.unitOfWork.SaveAsync(); + this.concentratorRepository.Update(concentratorEntity); + await this.unitOfWork.SaveAsync(); - return concentrator; - } - catch (DbUpdateException e) - { - throw new InternalServerErrorException($"Unable to update the concentrator {concentrator.DeviceName}", e); - } + return concentrator; } private async Task DeleteDeviceInDatabase(string deviceId) { - try - { - var concentratorEntity = await this.concentratorRepository.GetByIdAsync(deviceId); - - if (concentratorEntity == null) - { - return; - } - - this.concentratorRepository.Delete(deviceId); + var concentratorEntity = await this.concentratorRepository.GetByIdAsync(deviceId); - await this.unitOfWork.SaveAsync(); - } - catch (DbUpdateException e) + if (concentratorEntity == null) { - throw new InternalServerErrorException($"Unable to delete the concentrator {deviceId}", e); + return; } + + this.concentratorRepository.Delete(deviceId); + + await this.unitOfWork.SaveAsync(); } } } diff --git a/src/AzureIoTHub.Portal.Server/Services/LoRaWanDeviceService.cs b/src/AzureIoTHub.Portal.Server/Services/LoRaWanDeviceService.cs index 1e88beb37..c834f82f1 100644 --- a/src/AzureIoTHub.Portal.Server/Services/LoRaWanDeviceService.cs +++ b/src/AzureIoTHub.Portal.Server/Services/LoRaWanDeviceService.cs @@ -11,7 +11,6 @@ namespace AzureIoTHub.Portal.Server.Services using Managers; using Infrastructure; using Domain.Exceptions; - using Microsoft.EntityFrameworkCore; using Domain; using Models.v10; using Mappers; @@ -62,74 +61,53 @@ public override async Task GetDevice(string deviceId) protected override async Task CreateDeviceInDatabase(LoRaDeviceDetails device) { - try - { - var deviceEntity = this.mapper.Map(device); + var deviceEntity = this.mapper.Map(device); - await this.lorawanDeviceRepository.InsertAsync(deviceEntity); - await this.unitOfWork.SaveAsync(); + await this.lorawanDeviceRepository.InsertAsync(deviceEntity); + await this.unitOfWork.SaveAsync(); - return device; - } - catch (DbUpdateException e) - { - throw new InternalServerErrorException($"Unable to create the LoRaWAN device {device.DeviceName}", e); - } + return device; } protected override async Task UpdateDeviceInDatabase(LoRaDeviceDetails device) { - try - { - var deviceEntity = await this.lorawanDeviceRepository.GetByIdAsync(device.DeviceID); + var deviceEntity = await this.lorawanDeviceRepository.GetByIdAsync(device.DeviceID); - if (deviceEntity == null) - { - throw new ResourceNotFoundException($"The LoRaWAN device {device.DeviceID} doesn't exist"); - } + if (deviceEntity == null) + { + throw new ResourceNotFoundException($"The LoRaWAN device {device.DeviceID} doesn't exist"); + } - foreach (var deviceTagEntity in deviceEntity.Tags) - { - this.deviceTagValueRepository.Delete(deviceTagEntity.Id); - } + foreach (var deviceTagEntity in deviceEntity.Tags) + { + this.deviceTagValueRepository.Delete(deviceTagEntity.Id); + } - _ = this.mapper.Map(device, deviceEntity); + _ = this.mapper.Map(device, deviceEntity); - this.lorawanDeviceRepository.Update(deviceEntity); - await this.unitOfWork.SaveAsync(); + this.lorawanDeviceRepository.Update(deviceEntity); + await this.unitOfWork.SaveAsync(); - return device; - } - catch (DbUpdateException e) - { - throw new InternalServerErrorException($"Unable to update the LoRaWAN device {device.DeviceName}", e); - } + return device; } protected override async Task DeleteDeviceInDatabase(string deviceId) { - try - { - var deviceEntity = await this.lorawanDeviceRepository.GetByIdAsync(deviceId); - - if (deviceEntity == null) - { - return; - } - - foreach (var deviceTagEntity in deviceEntity.Tags) - { - this.deviceTagValueRepository.Delete(deviceTagEntity.Id); - } - - this.lorawanDeviceRepository.Delete(deviceId); + var deviceEntity = await this.lorawanDeviceRepository.GetByIdAsync(deviceId); - await this.unitOfWork.SaveAsync(); + if (deviceEntity == null) + { + return; } - catch (DbUpdateException e) + + foreach (var deviceTagEntity in deviceEntity.Tags) { - throw new InternalServerErrorException($"Unable to delete the LoRaWAN device {deviceId}", e); + this.deviceTagValueRepository.Delete(deviceTagEntity.Id); } + + this.lorawanDeviceRepository.Delete(deviceId); + + await this.unitOfWork.SaveAsync(); } } } diff --git a/src/AzureIoTHub.Portal.Server/Startup.cs b/src/AzureIoTHub.Portal.Server/Startup.cs index 3eb7cf7c4..a3159674e 100644 --- a/src/AzureIoTHub.Portal.Server/Startup.cs +++ b/src/AzureIoTHub.Portal.Server/Startup.cs @@ -13,6 +13,8 @@ namespace AzureIoTHub.Portal.Server using Domain; using Domain.Exceptions; using Domain.Repositories; + using EntityFramework.Exceptions.Common; + using EntityFramework.Exceptions.PostgreSQL; using Extensions; using Hellang.Middleware.ProblemDetails; using Hellang.Middleware.ProblemDetails.Mvc; @@ -210,6 +212,61 @@ public void ConfigureServices(IServiceCollection services) ["params"] = exception.ParamName } }); + + setup.Map(exception => new ProblemDetails + { + Title = "Unique Violation", + Detail = exception.Message, + Status = StatusCodes.Status500InternalServerError, + Extensions = + { + ["params"] = exception.Entries.ToString() + } + }); + + setup.Map(exception => new ProblemDetails + { + Title = "Not Null Violation", + Detail = exception.Message, + Status = StatusCodes.Status500InternalServerError, + Extensions = + { + ["params"] = exception.Entries.ToString(), + } + }); + + setup.Map(exception => new ProblemDetails + { + Title = "String Data Right Truncation", + Detail = exception.Message, + Status = StatusCodes.Status500InternalServerError, + Extensions = + { + ["params"] = exception.Entries.ToString() + } + }); + + setup.Map(exception => new ProblemDetails + { + Title = "Numeric Value Out Of Range", + Detail = exception.Message, + Status = StatusCodes.Status500InternalServerError, + Extensions = + { + ["params"] = exception.Entries.ToString() + } + }); + + setup.Map(exception => new ProblemDetails + { + Title = "Foreign Key Violation", + Detail = exception.Message, + Status = StatusCodes.Status500InternalServerError, + Extensions = + { + ["params"] = exception.Entries.ToString() + } + }); }); _ = services.AddControllers(); @@ -374,7 +431,11 @@ private static void ConfigureIdeasFeature(IServiceCollection services, ConfigHan private static void ConfigureDatabase(IServiceCollection services, ConfigHandler configuration) { _ = services - .AddDbContextPool(opts => opts.UseNpgsql(configuration.PostgreSQLConnectionString)); + .AddDbContextPool(opts => + { + _ = opts.UseNpgsql(configuration.PostgreSQLConnectionString); + _ = opts.UseExceptionProcessor(); + }); if (string.IsNullOrEmpty(configuration.PostgreSQLConnectionString)) return; diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/EdgeDevices/EdgeDeviceListPageTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/EdgeDevices/EdgeDeviceListPageTests.cs index b2f73950c..662b35533 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/EdgeDevices/EdgeDeviceListPageTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/EdgeDevices/EdgeDeviceListPageTests.cs @@ -20,22 +20,26 @@ namespace AzureIoTHub.Portal.Tests.Unit.Client.Pages.EdgeDevices using System.Threading.Tasks; using System.Linq; using MudBlazor; + using AutoFixture; [TestFixture] public class EdgeDeviceListPageTests : BlazorUnitTest { private Mock mockEdgeDeviceClientService; private Mock mockEdgeModelClientService; + private Mock mockDialogService; public override void Setup() { base.Setup(); + this.mockDialogService = MockRepository.Create(); this.mockEdgeDeviceClientService = MockRepository.Create(); this.mockEdgeModelClientService = MockRepository.Create(); _ = Services.AddSingleton(this.mockEdgeDeviceClientService.Object); _ = Services.AddSingleton(this.mockEdgeModelClientService.Object); + _ = Services.AddSingleton(this.mockDialogService.Object); _ = Services.AddSingleton(new PortalSettings { IsLoRaSupported = false }); _ = Services.AddSingleton(); } @@ -269,7 +273,23 @@ public void ClickOnRefreshShouldReloadEdgeDevices() public async Task FliterBySelectModelShould() { // Arrange + var modelList = new List() + { + new IoTEdgeModelListItem() + { + ModelId = Guid.NewGuid().ToString(), + Name = "model_01", + Description = Guid.NewGuid().ToString(), + }, + new IoTEdgeModelListItem() + { + ModelId = Guid.NewGuid().ToString(), + Name = "model_02", + Description = Guid.NewGuid().ToString(), + }, + }; var expectedUrl = "api/edge/devices?pageNumber=0&pageSize=10&searchText=&searchStatus=&orderBy=&modelId="; + var expectedUrlFilter = $"api/edge/devices?pageNumber=0&pageSize=10&searchText=&searchStatus=&orderBy=&modelId={modelList[0].ModelId}"; _ = this.mockEdgeDeviceClientService.Setup(service => service.GetDevices(expectedUrl)) .ReturnsAsync(new PaginationResult { @@ -288,21 +308,22 @@ public async Task FliterBySelectModelShould() } }); - _ = this.mockEdgeModelClientService.Setup(service => service.GetIoTEdgeModelList()) - .ReturnsAsync(new List() + _ = this.mockEdgeDeviceClientService.Setup(service => service.GetDevices(expectedUrlFilter)) + .ReturnsAsync(new PaginationResult { - new IoTEdgeModelListItem() - { - Name = "model_01", - Description = Guid.NewGuid().ToString(), - }, - new IoTEdgeModelListItem() + Items = new List { - Name = "model_02", - Description = Guid.NewGuid().ToString(), - }, + new IoTEdgeListItem() + { + DeviceId = Guid.NewGuid().ToString(), + DeviceName = Guid.NewGuid().ToString(), + } + } }); + _ = this.mockEdgeModelClientService.Setup(service => service.GetIoTEdgeModelList()) + .ReturnsAsync(modelList); + // Act var popoverProvider = RenderComponent(); var cut = RenderComponent(); @@ -313,9 +334,55 @@ public async Task FliterBySelectModelShould() var newModelList = await cut.Instance.Search("01"); + await cut.Instance.ChangeModel(modelList[0]); + + cut.WaitForElement("#searchFilterButton").Click(); + // Assert cut.WaitForAssertion(() => cut.Markup.Should().NotContain("Loading...")); Assert.AreEqual(1, newModelList.Count()); + _ = cut.FindAll("table tbody tr").Count.Should().Be(1); + cut.WaitForAssertion(() => MockRepository.VerifyAll()); + } + + [Test] + public void ClickOnDeleteShouldShowDeleteDialog() + { + // Arrange + var expectedUrl = "api/edge/devices?pageNumber=0&pageSize=10&searchText=&searchStatus=&orderBy=&modelId="; + var deviceList = new List + { + Fixture.Create() + }; + + _ = this.mockEdgeDeviceClientService.Setup(service => service.GetDevices(expectedUrl)) + .ReturnsAsync(new PaginationResult + { + Items = deviceList + }); + + _ = this.mockEdgeModelClientService.Setup(service => service.GetIoTEdgeModelList()) + .ReturnsAsync(new List() + { + new IoTEdgeModelListItem() + { + Name = Guid.NewGuid().ToString(), + Description = Guid.NewGuid().ToString(), + } + }); + + var mockDialogReference = new DialogReference(Guid.NewGuid(), this.mockDialogService.Object); + + _ = this.mockDialogService.Setup(c => c.Show(It.IsAny(), It.IsAny())) + .Returns(mockDialogReference); + + // Act + var cut = RenderComponent(); + + var deleteIcon = cut.WaitForElement($"#delete_{deviceList[0].DeviceId}"); + deleteIcon.Click(); + + // Assert cut.WaitForAssertion(() => MockRepository.VerifyAll()); } } diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/DeviceModelPropertiesServiceTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/DeviceModelPropertiesServiceTests.cs index 8c1498980..b9ad6bf24 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/DeviceModelPropertiesServiceTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/DeviceModelPropertiesServiceTests.cs @@ -12,6 +12,7 @@ namespace AzureIoTHub.Portal.Tests.Unit.Server.Services using AzureIoTHub.Portal.Domain.Exceptions; using AzureIoTHub.Portal.Domain.Repositories; using AzureIoTHub.Portal.Server.Services; + using EntityFramework.Exceptions.Common; using Microsoft.EntityFrameworkCore; using Moq; using NUnit.Framework; @@ -123,10 +124,10 @@ public void WhenExceptionOccuresSavePropertiesForModelShouldThrowInternalServerE .Returns(Task.CompletedTask); _ = this.mockUnitOfWork.Setup(c => c.SaveAsync()) - .Throws(); + .Throws(); // Act - _ = Assert.ThrowsAsync(async () => await instance.SavePropertiesForModel(entity.Id, Array.Empty())); + _ = Assert.ThrowsAsync(async () => await instance.SavePropertiesForModel(entity.Id, Array.Empty())); } private DeviceModel SetupMockEntity() diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/DeviceModelServiceTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/DeviceModelServiceTests.cs index 7e7d1c74a..12d886eee 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/DeviceModelServiceTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/DeviceModelServiceTests.cs @@ -12,6 +12,7 @@ namespace AzureIoTHub.Portal.Tests.Unit.Server.Services using AutoMapper; using AzureIoTHub.Portal.Domain; using AzureIoTHub.Portal.Server.Services; + using EntityFramework.Exceptions.Common; using FluentAssertions; using Microsoft.AspNetCore.Http; using Microsoft.Azure.Devices.Provisioning.Service; @@ -167,7 +168,7 @@ public async Task CreateDeviceModelShouldCreateDeviceModel() } [Test] - public async Task CreateDeviceModelShouldThrowInternalServerErrorExceptionWhenDDbUpdateExceptionIsThrown() + public async Task CreateDeviceModelShouldThrowCannotInsertNullExceptionWhenDDbUpdateExceptionIsThrown() { // Arrange var deviceModelDto = Fixture.Create(); @@ -176,13 +177,13 @@ public async Task CreateDeviceModelShouldThrowInternalServerErrorExceptionWhenDD .Returns(Task.CompletedTask); _ = this.mockUnitOfWork.Setup(work => work.SaveAsync()) - .ThrowsAsync(new DbUpdateException()); + .ThrowsAsync(new CannotInsertNullException()); // Act var act = () => this.deviceModelService.CreateDeviceModel(deviceModelDto); // Assert - _ = await act.Should().ThrowAsync(); + _ = await act.Should().ThrowAsync(); MockRepository.VerifyAll(); } @@ -223,7 +224,7 @@ public async Task UpdateDeviceModelShouldUpdateDeviceModel() } [Test] - public async Task UpdateDeviceModelShouldThrowInternalServerErrorExceptionWhenDDbUpdateExceptionIsThrown() + public async Task UpdateDeviceModelShouldThrowMaxLengthExceededExceptionWhenDDbUpdateExceptionIsThrown() { // Arrange var deviceModelDto = Fixture.Create(); @@ -235,13 +236,13 @@ public async Task UpdateDeviceModelShouldThrowInternalServerErrorExceptionWhenDD .Verifiable(); _ = this.mockUnitOfWork.Setup(work => work.SaveAsync()) - .ThrowsAsync(new DbUpdateException()); + .ThrowsAsync(new MaxLengthExceededException()); // Act var act = () => this.deviceModelService.UpdateDeviceModel(deviceModelDto); // Assert - _ = await act.Should().ThrowAsync(); + _ = await act.Should().ThrowAsync(); MockRepository.VerifyAll(); } @@ -315,7 +316,7 @@ public async Task DeleteDeviceModelShouldDeleteDeviceModel() } [Test] - public async Task DeleteDeviceModelShouldThrowInternalServerErrorExceptionWhenDDbUpdateExceptionIsThrown() + public async Task DeleteDeviceModelShouldThrowAnErrorExceptionWhenDDbUpdateExceptionIsThrown() { // Arrange var deviceModelDto = Fixture.Create(); @@ -363,7 +364,7 @@ public async Task DeleteDeviceModelShouldThrowInternalServerErrorExceptionWhenDD var act = () => this.deviceModelService.DeleteDeviceModel(deviceModelDto.ModelId); // Assert - _ = await act.Should().ThrowAsync(); + _ = await act.Should().ThrowAsync(); MockRepository.VerifyAll(); } diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/DeviceServiceTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/DeviceServiceTests.cs index 762b276fa..44b16dc24 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/DeviceServiceTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/DeviceServiceTests.cs @@ -26,6 +26,7 @@ namespace AzureIoTHub.Portal.Tests.Unit.Server.Services using Microsoft.EntityFrameworkCore; using Portal.Domain.Entities; using AutoMapper; + using EntityFramework.Exceptions.Common; [TestFixture] public class DeviceServiceTests : BackendUnitTest @@ -267,13 +268,13 @@ public async Task CreateDevice_DbUpdateExceptionIsThrown_InternalServerErrorExce .Returns(Task.CompletedTask); _ = this.mockUnitOfWork.Setup(work => work.SaveAsync()) - .ThrowsAsync(new DbUpdateException()); + .ThrowsAsync(new UniqueConstraintException()); // Act var act = () => this.deviceService.CreateDevice(deviceDto); // Assert - _ = await act.Should().ThrowAsync(); + _ = await act.Should().ThrowAsync(); MockRepository.VerifyAll(); } @@ -368,7 +369,7 @@ public async Task UpdateDevice_DeviceNotExist_ResourceNotFoundExceptionIsThrown( } [Test] - public async Task UpdateDevice_DbUpdateExceptionIsRaised_InternalServerErrorExceptionIsThrown() + public async Task UpdateDevice_DbUpdateExceptionIsRaised_CannotInsertNullExceptionIsThrown() { // Arrange var deviceDto = new DeviceDetails @@ -402,13 +403,13 @@ public async Task UpdateDevice_DbUpdateExceptionIsRaised_InternalServerErrorExce .Verifiable(); _ = this.mockUnitOfWork.Setup(work => work.SaveAsync()) - .ThrowsAsync(new DbUpdateException()); + .ThrowsAsync(new CannotInsertNullException()); // Act var act = () => this.deviceService.UpdateDevice(deviceDto); // Assert - _ = await act.Should().ThrowAsync(); + _ = await act.Should().ThrowAsync(); MockRepository.VerifyAll(); } @@ -469,7 +470,7 @@ public async Task DeleteDevice_DeviceNotExist_NothingIsDone() } [Test] - public async Task DeleteDevice_DbUpdateExceptionIsRaised_InternalServerErrorExceptionIsThrown() + public async Task DeleteDevice_DbUpdateExceptionIsRaised_DbUpdateExceptionIsThrown() { // Arrange var deviceDto = new DeviceDetails @@ -496,7 +497,7 @@ public async Task DeleteDevice_DbUpdateExceptionIsRaised_InternalServerErrorExce var act = () => this.deviceService.DeleteDevice(deviceDto.DeviceID); // Assert - _ = await act.Should().ThrowAsync(); + _ = await act.Should().ThrowAsync(); MockRepository.VerifyAll(); } diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/EdgeDeviceServiceTest.cs b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/EdgeDeviceServiceTest.cs index 332184c41..79b9f2ccf 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/EdgeDeviceServiceTest.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/EdgeDeviceServiceTest.cs @@ -19,10 +19,10 @@ namespace AzureIoTHub.Portal.Tests.Unit.Server.Services using AzureIoTHub.Portal.Server.Services; using AzureIoTHub.Portal.Shared.Models.v1._0; using AzureIoTHub.Portal.Tests.Unit.UnitTests.Bases; + using EntityFramework.Exceptions.Common; using FluentAssertions; using Microsoft.Azure.Devices; using Microsoft.Azure.Devices.Shared; - using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Moq; using NUnit.Framework; @@ -246,6 +246,10 @@ public async Task CreateEdgeDeviceShouldReturnvalue() var edgeDevice = new IoTEdgeDevice() { DeviceId = "aaa", + Tags = new Dictionary() + { + { "test", "test" } + } }; _ = this.mockDeviceService.Setup(c => c.CreateDeviceWithTwin( @@ -272,7 +276,7 @@ public async Task CreateEdgeDeviceShouldReturnvalue() } [Test] - public async Task CreateEdgeDeviceDbUpdateExceptionIsThrownInternalServerErrorExceptionIsThrown() + public async Task CreateEdgeDeviceDbUpdateExceptionIsThrownMaxLengthExceededExceptionIsThrown() { // Arrange var mockResult = new BulkRegistryOperationResult @@ -296,13 +300,13 @@ public async Task CreateEdgeDeviceDbUpdateExceptionIsThrownInternalServerErrorEx .Returns(Task.CompletedTask); _ = this.mockUnitOfWork.Setup(work => work.SaveAsync()) - .ThrowsAsync(new DbUpdateException()); + .ThrowsAsync(new MaxLengthExceededException()); // Act var act = () => this.edgeDevicesService.CreateEdgeDevice(edgeDevice); // Assert - _ = await act.Should().ThrowAsync(); + _ = await act.Should().ThrowAsync(); MockRepository.VerifyAll(); } @@ -416,7 +420,7 @@ public async Task UpdateEdgeDeviceDeviceNotExistResourceNotFoundExceptionIsThrow } [Test] - public async Task UpdateEdgeDeviceDbUpdateExceptionIsThrownInternalServerErrorExceptionIsThrown() + public async Task UpdateEdgeDeviceDbUpdateExceptionIsThrownNumericOverflowExceptionIsThrown() { // Arrange var edgeDevice = new IoTEdgeDevice() @@ -463,13 +467,13 @@ public async Task UpdateEdgeDeviceDbUpdateExceptionIsThrownInternalServerErrorEx .Verifiable(); _ = this.mockUnitOfWork.Setup(work => work.SaveAsync()) - .ThrowsAsync(new DbUpdateException()); + .ThrowsAsync(new NumericOverflowException()); // Act var act = () => this.edgeDevicesService.UpdateEdgeDevice(edgeDevice); // Assert - _ = await act.Should().ThrowAsync(); + _ = await act.Should().ThrowAsync(); MockRepository.VerifyAll(); } @@ -539,7 +543,7 @@ public async Task DeleteEdgeDeviceDeviceNotExistNothingIsDone() } [Test] - public async Task DeleteEdgeDeviceDbUpdateExceptionIsRaisedInternalServerErrorExceptionIsThrown() + public async Task DeleteEdgeDeviceDbUpdateExceptionIsRaisedReferenceConstraintExceptionIsThrown() { // Arrange var deviceDto = new IoTEdgeDevice @@ -560,18 +564,18 @@ public async Task DeleteEdgeDeviceDbUpdateExceptionIsRaisedInternalServerErrorEx .Verifiable(); _ = this.mockUnitOfWork.Setup(work => work.SaveAsync()) - .ThrowsAsync(new DbUpdateException()); + .ThrowsAsync(new ReferenceConstraintException()); // Act var act = () => this.edgeDevicesService.DeleteEdgeDeviceAsync(deviceDto.DeviceId); // Assert - _ = await act.Should().ThrowAsync(); + _ = await act.Should().ThrowAsync(); MockRepository.VerifyAll(); } [TestCase("RestartModule", /*lang=json,strict*/ "{\"id\":\"aaa\",\"schemaVersion\":\"1.0\"}")] - public async Task ExecuteMethodShouldExecuteC2DMethod(string methodName, string expected) + public async Task ExecuteMethodRestartModuleShouldExecuteC2DMethod(string methodName, string expected) { // Arrange var edgeModule = new IoTEdgeModule @@ -599,6 +603,33 @@ public async Task ExecuteMethodShouldExecuteC2DMethod(string methodName, string MockRepository.VerifyAll(); } + [TestCase("test")] + public async Task ExecuteMethodTestShouldExecuteC2DMethod(string methodName) + { + // Arrange + var edgeModule = new IoTEdgeModule + { + ModuleName = "aaa", + }; + + var deviceId = Guid.NewGuid().ToString(); + + _ = this.mockDeviceService.Setup(c => c.ExecuteCustomCommandC2DMethod( + It.Is(x => x == deviceId), + It.Is(x => x.Equals(edgeModule.ModuleName, StringComparison.Ordinal)), + It.Is(x => x.MethodName == methodName))) + .ReturnsAsync(new CloudToDeviceMethodResult + { + Status = 200 + }); + + // Act + _ = await this.edgeDevicesService.ExecuteModuleMethod(deviceId, edgeModule.ModuleName, methodName); + + // Assert + MockRepository.VerifyAll(); + } + [TestCase("RestartModule")] public void WhenEdgeModuleIsNullExecuteMethodShouldThrowArgumentNullException(string methodName) { diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/EdgeModelServiceTest.cs b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/EdgeModelServiceTest.cs index 17d0be16e..b3d397de1 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/EdgeModelServiceTest.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/EdgeModelServiceTest.cs @@ -49,7 +49,6 @@ public void SetUp() this.mockEdgeDeviceModelCommandRepository = MockRepository.Create(); this.mockConfigService = MockRepository.Create(); this.mockDeviceModelImageManager = MockRepository.Create(); - //this.mockEdgeDeviceModelMapper = MockRepository.Create(); _ = ServiceCollection.AddSingleton(this.mockUnitOfWork.Object); _ = ServiceCollection.AddSingleton(this.mockEdgeDeviceModelRepository.Object); @@ -120,6 +119,14 @@ public async Task GetEdgeModelShouldReturnValueAsync() return command; }) .ToList(); + expectedCommands.Add(new EdgeDeviceModelCommand + { + EdgeDeviceModelId = expectedEdgeDeviceModel.ModelId, + Id = Guid.NewGuid().ToString(), + Name = Guid.NewGuid().ToString(), + ModuleName = Guid.NewGuid().ToString() + }); + var expectedEdgeDeviceModelEntity = Mapper.Map(expectedEdgeDeviceModel); _ = this.mockDeviceModelImageManager.Setup(c => c.ComputeImageUri(It.IsAny())) diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/LoRaWANCommandServiceTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/LoRaWANCommandServiceTests.cs index 5e0dd353c..4b0aaaa2e 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/LoRaWANCommandServiceTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/LoRaWANCommandServiceTests.cs @@ -13,8 +13,8 @@ namespace AzureIoTHub.Portal.Tests.Unit.Domain.Services using AzureIoTHub.Portal.Domain; using AzureIoTHub.Portal.Domain.Exceptions; using AzureIoTHub.Portal.Server.Services; + using EntityFramework.Exceptions.Common; using FluentAssertions; - using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Models.v10.LoRaWAN; using Moq; @@ -97,7 +97,26 @@ public async Task PostShouldCreateCommandShouldDeleteExistingModelCommandsAndCre } [Test] - public async Task PostShouldCreateCommandShouldThrowInternalServerErrorExceptionWhenDDbUpdateExceptionIsThrown() + public void PostShouldCreateCommandShouldThrowAResourceNotFoundExceptionWhenModelentityIsNull() + { + // Arrange + var deviceModel = Fixture.Create(); + + var newCommands = Fixture.CreateMany(5); + + _ = this.mockDeviceModelRepository.Setup(repository => repository.GetByIdAsync(deviceModel.Id)) + .ReturnsAsync(value: null); + + // Act + var act = async () => await this.loRaWanCommandService.PostDeviceModelCommands(deviceModel.Id, newCommands.ToArray()); + + // Assert + _ = act.Should().ThrowAsync(); + MockRepository.VerifyAll(); + } + + [Test] + public async Task PostShouldCreateCommandShouldThrowUniqueConstraintExceptionWhenDDbUpdateExceptionIsThrown() { // Arrange var deviceModel = Fixture.Create(); @@ -114,13 +133,13 @@ public async Task PostShouldCreateCommandShouldThrowInternalServerErrorException .Returns(Task.CompletedTask); _ = this.mockUnitOfWork.Setup(work => work.SaveAsync()) - .ThrowsAsync(new DbUpdateException()); + .ThrowsAsync(new UniqueConstraintException()); // Act var act = () => this.loRaWanCommandService.PostDeviceModelCommands(deviceModel.Id, commands.ToArray()); // Assert - _ = await act.Should().ThrowAsync(); + _ = await act.Should().ThrowAsync(); MockRepository.VerifyAll(); } @@ -224,65 +243,5 @@ public void ExecuteCommandShouldReturnNotFoundWhenCommandIsNotFound() MockRepository.VerifyAll(); } - //[Test] - //public void ExecuteCommandFailedShouldThrowInternalServerErrorException() - //{ - // // Arrange - // var modelId = Guid.NewGuid().ToString(); - // var deviceId = Guid.NewGuid().ToString(); - // var commandId = Guid.NewGuid().ToString(); - - // var mockResponse = MockRepository.Create(); - // _ = this.mockDeviceModelCommandMapper - // .Setup(c => c.GetDeviceModelCommand(It.Is(x => x.RowKey == commandId && x.PartitionKey == modelId))) - // .Returns(new DeviceModelCommandDto - // { - // Name = commandId, - // Frame = Guid.NewGuid().ToString(), - // Port = 125 - // }); - - // _ = this.mockCommandsTableClient.Setup(c => c.Query( - // It.Is(x => x == $"RowKey eq '{commandId}' and PartitionKey eq '{modelId}'"), - // It.IsAny(), - // It.IsAny>(), - // It.IsAny())) - // .Returns(Pageable.FromPages(new[] - // { - // Page.FromValues(new[] - // { - // new TableEntity(modelId, commandId) - // }, null, mockResponse.Object) - // })); - - // _ = this.mockTableClientFactory.Setup(c => c.GetDeviceCommands()) - // .Returns(this.mockCommandsTableClient.Object); - - // using var internalServerError = new HttpResponseMessage(HttpStatusCode.InternalServerError); - - // _ = this.mockLoraDeviceMethodManager.Setup(c => c.ExecuteLoRaDeviceMessage( - // It.Is(x => x == deviceId), - // It.Is(x => x.Name == commandId))) - // .ReturnsAsync(internalServerError); - - // _ = this.mockDeviceService.Setup(c => c.GetDeviceTwin(It.Is(x => x == deviceId))) - // .ReturnsAsync(new Twin() - // { - // DeviceId = deviceId, - // ModelId = modelId, - // }); - - // _ = this.mockDeviceTwinMapper.Setup(c => c.CreateDeviceDetails(It.IsAny(), It.IsAny>())) - // .Returns>((_, _) => new LoRaDeviceDetails - // { - // DeviceID = deviceId, - // ModelId = modelId, - // }); - - // // Assert - // _ = Assert.ThrowsAsync(async () => await this.loRaWanCommandService.ExecuteLoRaWANCommand(deviceId, commandId)); - - // MockRepository.VerifyAll(); - //} } } diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/LoRaWANConcentratorServiceTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/LoRaWANConcentratorServiceTests.cs index 16188c582..abb425bdf 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/LoRaWANConcentratorServiceTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/LoRaWANConcentratorServiceTests.cs @@ -17,6 +17,7 @@ namespace AzureIoTHub.Portal.Tests.Unit.Server.Services using AzureIoTHub.Portal.Server.Services; using AzureIoTHub.Portal.Shared.Models.v1._0; using AzureIoTHub.Portal.Tests.Unit.UnitTests.Bases; + using EntityFramework.Exceptions.Common; using FluentAssertions; using Microsoft.Azure.Devices; using Microsoft.Azure.Devices.Shared; @@ -167,7 +168,7 @@ public async Task CreateDeviceAsyncExpectedBehaviorShouldCreateConcentrator() } [Test] - public async Task CreateDeviceAsyncDbUpdateExceptionShouldThrowInternalServerErrorException() + public async Task CreateDeviceAsyncDbUpdateExceptionShouldThrowMaxLengthExceededException() { // Arrange var expectedConcentrator = Fixture.Create(); @@ -177,7 +178,7 @@ public async Task CreateDeviceAsyncDbUpdateExceptionShouldThrowInternalServerErr .Returns(Task.CompletedTask); _ = this.mockUnitOfWork.Setup(work => work.SaveAsync()) - .ThrowsAsync(new DbUpdateException()); + .ThrowsAsync(new MaxLengthExceededException()); _ = this.mockExternalDeviceService.Setup(service => service.CreateNewTwinFromDeviceId(It.IsAny())) .ReturnsAsync(new Twin { DeviceId = expectedConcentratorDto.DeviceId }); @@ -195,7 +196,7 @@ public async Task CreateDeviceAsyncDbUpdateExceptionShouldThrowInternalServerErr var act = () => this.concentratorService.CreateDeviceAsync(expectedConcentratorDto); // Assert - _ = await act.Should().ThrowAsync(); + _ = await act.Should().ThrowAsync(); MockRepository.VerifyAll(); } @@ -278,7 +279,7 @@ public async Task UpdateDeviceAsyncConcentratorNotFoundInDBShouldThrowResourceNo } [Test] - public async Task UpdateDeviceAsyncDbUpdateExceptionShouldThrowInternalServerErrorException() + public async Task UpdateDeviceAsyncDbUpdateExceptionShouldThrowUniqueConstraintException() { // Arrange var expectedConcentrator = Fixture.Create(); @@ -291,7 +292,7 @@ public async Task UpdateDeviceAsyncDbUpdateExceptionShouldThrowInternalServerErr .Verifiable(); _ = this.mockUnitOfWork.Setup(work => work.SaveAsync()) - .ThrowsAsync(new DbUpdateException()); + .ThrowsAsync(new UniqueConstraintException()); _ = this.mockExternalDeviceService.Setup(service => service.GetDevice(It.IsAny())) .ReturnsAsync(new Device()); @@ -315,7 +316,7 @@ public async Task UpdateDeviceAsyncDbUpdateExceptionShouldThrowInternalServerErr var act = () => this.concentratorService.UpdateDeviceAsync(expectedConcentratorDto); // Assert - _ = await act.Should().ThrowAsync(); + _ = await act.Should().ThrowAsync(); MockRepository.VerifyAll(); } @@ -366,7 +367,7 @@ public async Task DeleteDeviceAsyncConcentratorNotFoundInDBShouldReturn() } [Test] - public async Task DeleteDeviceAsyncDbUpdateExceptionShouldThrowInternalServerErrorException() + public async Task DeleteDeviceAsyncDbUpdateExceptionShouldThrowReferenceConstraintException() { // Arrange var expectedConcentrator = Fixture.Create(); @@ -379,7 +380,7 @@ public async Task DeleteDeviceAsyncDbUpdateExceptionShouldThrowInternalServerErr .Verifiable(); _ = this.mockUnitOfWork.Setup(work => work.SaveAsync()) - .ThrowsAsync(new DbUpdateException()); + .ThrowsAsync(new ReferenceConstraintException()); _ = this.mockExternalDeviceService.Setup(service => service.DeleteDevice(It.IsAny())) .Returns(Task.CompletedTask); @@ -388,7 +389,7 @@ public async Task DeleteDeviceAsyncDbUpdateExceptionShouldThrowInternalServerErr var act = () => this.concentratorService.DeleteDeviceAsync(expectedConcentratorDto.DeviceId); // Assert - _ = await act.Should().ThrowAsync(); + _ = await act.Should().ThrowAsync(); MockRepository.VerifyAll(); } } diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/LoRaWanDeviceServiceTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/LoRaWanDeviceServiceTests.cs index b9fa61be9..06802bc2e 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/LoRaWanDeviceServiceTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/LoRaWanDeviceServiceTests.cs @@ -26,6 +26,7 @@ namespace AzureIoTHub.Portal.Tests.Unit.Server.Services using Microsoft.Azure.Devices; using Microsoft.EntityFrameworkCore; using AutoMapper; + using EntityFramework.Exceptions.Common; [TestFixture] public class LoRaWanDeviceServiceTests : BackendUnitTest @@ -147,7 +148,7 @@ public async Task CreateDevice_NewDevice_DeviceCreated() } [Test] - public async Task CreateDevice_DbUpdateExceptionIsThrown_InternalServerErrorExceptionIsThrown() + public async Task CreateDevice_DbUpdateExceptionIsThrown_UniqueConstraintExceptionIsThrown() { // Arrange var deviceDto = new LoRaDeviceDetails @@ -170,13 +171,13 @@ public async Task CreateDevice_DbUpdateExceptionIsThrown_InternalServerErrorExce .Returns(Task.CompletedTask); _ = this.mockUnitOfWork.Setup(work => work.SaveAsync()) - .ThrowsAsync(new DbUpdateException()); + .ThrowsAsync(new UniqueConstraintException()); // Act var act = () => this.lorawanDeviceService.CreateDevice(deviceDto); // Assert - _ = await act.Should().ThrowAsync(); + _ = await act.Should().ThrowAsync(); MockRepository.VerifyAll(); } @@ -271,7 +272,7 @@ public async Task UpdateDevice_DeviceNotExist_ResourceNotFoundExceptionIsThrown( } [Test] - public async Task UpdateDevice_DbUpdateExceptionIsRaised_InternalServerErrorExceptionIsThrown() + public async Task UpdateDevice_DbUpdateExceptionIsRaised_CannotInsertNullExceptionIsThrown() { // Arrange var deviceDto = new LoRaDeviceDetails @@ -305,13 +306,13 @@ public async Task UpdateDevice_DbUpdateExceptionIsRaised_InternalServerErrorExce .Verifiable(); _ = this.mockUnitOfWork.Setup(work => work.SaveAsync()) - .ThrowsAsync(new DbUpdateException()); + .ThrowsAsync(new CannotInsertNullException()); // Act var act = () => this.lorawanDeviceService.UpdateDevice(deviceDto); // Assert - _ = await act.Should().ThrowAsync(); + _ = await act.Should().ThrowAsync(); MockRepository.VerifyAll(); } @@ -372,7 +373,7 @@ public async Task DeleteDevice_DeviceNotExist_NothingIsDone() } [Test] - public async Task DeleteDevice_DbUpdateExceptionIsRaised_InternalServerErrorExceptionIsThrown() + public async Task DeleteDevice_DbUpdateExceptionIsRaised_ReferenceConstraintExceptionIsThrown() { // Arrange var deviceDto = new LoRaDeviceDetails @@ -393,13 +394,13 @@ public async Task DeleteDevice_DbUpdateExceptionIsRaised_InternalServerErrorExce .Verifiable(); _ = this.mockUnitOfWork.Setup(work => work.SaveAsync()) - .ThrowsAsync(new DbUpdateException()); + .ThrowsAsync(new ReferenceConstraintException()); // Act var act = () => this.lorawanDeviceService.DeleteDevice(deviceDto.DeviceID); // Assert - _ = await act.Should().ThrowAsync(); + _ = await act.Should().ThrowAsync(); MockRepository.VerifyAll(); } }