Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Bug: Failed to delete a device that is not present in IoT Hub #1836 #1839

Merged
merged 2 commits into from
Mar 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/AzureIoTHub.Portal.Server/Services/DeviceService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ namespace AzureIoTHub.Portal.Server.Services
using Domain.Exceptions;
using Domain.Repositories;
using Infrastructure;
using Microsoft.Extensions.Logging;
using Models.v10;

public class DeviceService : DeviceServiceBase<DeviceDetails>
Expand All @@ -37,8 +38,9 @@ public DeviceService(IMapper mapper,
IDeviceTagService deviceTagService,
IDeviceModelImageManager deviceModelImageManager,
IDeviceTwinMapper<DeviceListItem, DeviceDetails> deviceTwinMapper,
PortalDbContext portalDbContext)
: base(portalDbContext, mapper, externalDevicesService, deviceTagService, deviceModelImageManager, deviceTwinMapper)
PortalDbContext portalDbContext,
ILogger<DeviceService> logger)
: base(portalDbContext, mapper, externalDevicesService, deviceTagService, deviceModelImageManager, deviceTwinMapper, logger)
{
this.mapper = mapper;
this.unitOfWork = unitOfWork;
Expand Down
16 changes: 14 additions & 2 deletions src/AzureIoTHub.Portal.Server/Services/DeviceServiceBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ namespace AzureIoTHub.Portal.Server.Services
using Infrastructure;
using Infrastructure.Repositories;
using Microsoft.Azure.Devices;
using Microsoft.Azure.Devices.Common.Exceptions;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Models.v10;
using Shared.Models.v1._0;
using Shared.Models.v10.Filters;
Expand All @@ -33,20 +35,23 @@ public abstract class DeviceServiceBase<TDto> : IDeviceService<TDto>
private readonly IDeviceTagService deviceTagService;
private readonly IDeviceModelImageManager deviceModelImageManager;
private readonly IDeviceTwinMapper<DeviceListItem, TDto> deviceTwinMapper;
private readonly ILogger<DeviceServiceBase<TDto>> logger;

protected DeviceServiceBase(PortalDbContext portalDbContext,
IMapper mapper,
IExternalDeviceService externalDevicesService,
IDeviceTagService deviceTagService,
IDeviceModelImageManager deviceModelImageManager,
IDeviceTwinMapper<DeviceListItem, TDto> deviceTwinMapper)
IDeviceTwinMapper<DeviceListItem, TDto> deviceTwinMapper,
ILogger<DeviceServiceBase<TDto>> logger)
{
this.portalDbContext = portalDbContext;
this.mapper = mapper;
this.externalDevicesService = externalDevicesService;
this.deviceTagService = deviceTagService;
this.deviceModelImageManager = deviceModelImageManager;
this.deviceTwinMapper = deviceTwinMapper;
this.logger = logger;
}

public async Task<PaginatedResult<DeviceListItem>> GetDevices(string searchText = null, bool? searchStatus = null, bool? searchState = null, int pageSize = 10,
Expand Down Expand Up @@ -181,7 +186,14 @@ public async Task<TDto> UpdateDevice(TDto device)

public virtual async Task DeleteDevice(string deviceId)
{
await this.externalDevicesService.DeleteDevice(deviceId);
try
{
await this.externalDevicesService.DeleteDevice(deviceId);
}
catch (DeviceNotFoundException e)
{
this.logger.LogWarning($"Unable to delete the device with ID {deviceId} because it doesn't exist on IoT Hub {e.Message}");
}

await DeleteDeviceInDatabase(deviceId);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public LoRaWanDeviceService(
PortalDbContext portalDbContext,
IDeviceModelImageManager deviceModelImageManager,
IDeviceTwinMapper<DeviceListItem, LoRaDeviceDetails> deviceTwinMapper)
: base(portalDbContext, mapper, externalDevicesService, deviceTagService, deviceModelImageManager, deviceTwinMapper)
: base(portalDbContext, mapper, externalDevicesService, deviceTagService, deviceModelImageManager, deviceTwinMapper, logger)
{
this.logger = logger;
this.mapper = mapper;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ namespace AzureIoTHub.Portal.Tests.Unit.Server.Services
using EntityFramework.Exceptions.Common;
using FluentAssertions;
using Microsoft.Azure.Devices;
using Microsoft.Azure.Devices.Common.Exceptions;
using Microsoft.Azure.Devices.Shared;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
Expand Down Expand Up @@ -652,5 +653,37 @@ public async Task GetAvailableLabels_LabelsExists_LabelsReturned()
_ = result.Count().Should().Be(expectedLabels.Count);
MockRepository.VerifyAll();
}

[Test]
public async Task DeleteDevice_DeviceNotFoundOnAzure_DeviceDeletedInDatabase()
{
// Arrange
var deviceDto = new DeviceDetails
{
DeviceID = Fixture.Create<string>()
};

_ = this.mockExternalDevicesService.Setup(service => service.DeleteDevice(deviceDto.DeviceID))
.ThrowsAsync(new DeviceNotFoundException(deviceDto.DeviceID));

_ = this.mockDeviceRepository.Setup(repository => repository.GetByIdAsync(deviceDto.DeviceID, d => d.Tags, d => d.Labels))
.ReturnsAsync(new Device
{
Tags = new List<DeviceTagValue>(),
Labels = new List<Label>()
});

this.mockDeviceRepository.Setup(repository => repository.Delete(deviceDto.DeviceID))
.Verifiable();

_ = this.mockUnitOfWork.Setup(work => work.SaveAsync())
.Returns(Task.CompletedTask);

// Act
await this.deviceService.DeleteDevice(deviceDto.DeviceID);

// Assert
MockRepository.VerifyAll();
}
}
}