Skip to content

Commit

Permalink
Synchronize concentrators between Azure and DB (#1313)
Browse files Browse the repository at this point in the history
* WIP

* Fix typo in SyncConcentratorJobs

* Add SynConcentratorsJobTests

* Add migration

* Add clientThumbprint property in SyncConcentratorJobTests

* RetrieveClientThumbprintValue() moved to DeviceHelper
  • Loading branch information
audserraCGI authored Oct 7, 2022
1 parent 14c889a commit fecd9f5
Show file tree
Hide file tree
Showing 34 changed files with 1,165 additions and 218 deletions.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright (c) CGI France. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#nullable disable

namespace AzureIoTHub.Portal.Infrastructure.Migrations
{
using Microsoft.EntityFrameworkCore.Migrations;

public partial class AddConcentrator : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
_ = migrationBuilder.CreateTable(
name: "Concentrators",
columns: table => new
{
Id = table.Column<string>(type: "text", nullable: false),
Name = table.Column<string>(type: "text", nullable: false),
LoraRegion = table.Column<string>(type: "text", nullable: false),
DeviceType = table.Column<string>(type: "text", nullable: false),
ClientThumbprint = table.Column<string>(type: "text", nullable: false),
IsConnected = table.Column<bool>(type: "boolean", nullable: false),
IsEnabled = table.Column<bool>(type: "boolean", nullable: false),
Version = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
_ = table.PrimaryKey("PK_Concentrators", x => x.Id);
});
}

protected override void Down(MigrationBuilder migrationBuilder)
{
_ = migrationBuilder.DropTable(
name: "Concentrators");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,41 @@ protected override void BuildModel(ModelBuilder modelBuilder)

NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);

modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.Concentrator", b =>
{
b.Property<string>("Id")
.HasColumnType("text");

b.Property<string>("ClientThumbprint")
.IsRequired()
.HasColumnType("text");

b.Property<string>("DeviceType")
.IsRequired()
.HasColumnType("text");

b.Property<bool>("IsConnected")
.HasColumnType("boolean");

b.Property<bool>("IsEnabled")
.HasColumnType("boolean");

b.Property<string>("LoraRegion")
.IsRequired()
.HasColumnType("text");

b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");

b.Property<int>("Version")
.HasColumnType("integer");

b.HasKey("Id");

b.ToTable("Concentrators");
});

modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.Device", b =>
{
b.Property<string>("Id")
Expand Down
7 changes: 2 additions & 5 deletions src/AzureIoTHub.Portal.Infrastructure/PortalDbContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,9 @@

namespace AzureIoTHub.Portal.Infrastructure
{
using AzureIoTHub.Portal.Domain;
using AzureIoTHub.Portal.Domain.Entities;
using AzureIoTHub.Portal.Infrastructure.Seeds;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;


public class PortalDbContext : DbContext
{
Expand All @@ -22,6 +18,7 @@ public class PortalDbContext : DbContext
public DbSet<DeviceTagValue> DeviceTagValues { get; set; }
public DbSet<EdgeDeviceModel> EdgeDeviceModels { get; set; }
public DbSet<EdgeDeviceModelCommand> EdgeDeviceModelCommands { get; set; }
public DbSet<Concentrator> Concentrators { get; set; }

#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
public PortalDbContext(DbContextOptions<PortalDbContext> options)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright (c) CGI France. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace AzureIoTHub.Portal.Infrastructure.Repositories
{
using AzureIoTHub.Portal.Domain.Repositories;
using Domain.Entities;

public class ConcentratorRepository : GenericRepository<Concentrator>, IConcentratorRepository
{
public ConcentratorRepository(PortalDbContext context) : base(context)
{
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public void ReturnButtonMustNavigateToPreviousPage()
{
// Arrange
_ = this.mockLoRaWanConcentratorsClientService.Setup(service => service.GetConcentrator(this.mockDeviceId))
.ReturnsAsync(new Concentrator());
.ReturnsAsync(new ConcentratorDto());

_ = this.mockLoRaWanConcentratorsClientService.Setup(service => service.GetFrequencyPlans())
.ReturnsAsync(new[]
Expand Down Expand Up @@ -98,7 +98,7 @@ public void ConcentratorDetailPageShouldProcessProblemDetailsExceptionWhenIssueO
public void ClickOnSaveShouldPutConcentratorDetails()
{
// Arrange
var mockConcentrator = new Concentrator()
var mockConcentrator = new ConcentratorDto()
{
DeviceId = "1234567890123456",
DeviceName = Guid.NewGuid().ToString(),
Expand Down Expand Up @@ -133,7 +133,7 @@ public void ClickOnSaveShouldPutConcentratorDetails()
public void ConcentratorShouldNotBeUpdatedWhenModelIsNotValid()
{
// Arrange
var mockConcentrator = new Concentrator()
var mockConcentrator = new ConcentratorDto()
{
DeviceId = string.Empty,
DeviceName = Guid.NewGuid().ToString(),
Expand Down Expand Up @@ -163,7 +163,7 @@ public void ConcentratorShouldNotBeUpdatedWhenModelIsNotValid()
public void ClickOnSaveShouldProcessProblemDetailsExceptionWhenIssueOccursOnUpdatingConcentratorDetails()
{
// Arrange
var mockConcentrator = new Concentrator()
var mockConcentrator = new ConcentratorDto()
{
DeviceId = "1234567890123456",
DeviceName = Guid.NewGuid().ToString(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ public void ConcentratorListPageShouldLoadAndShowConcentrators()

_ = this.mockLoRaWanConcentratorsClientService.Setup(service =>
service.GetConcentrators(It.Is<string>(s => expectedUri.Equals(s, StringComparison.Ordinal))))
.ReturnsAsync(new PaginationResult<Concentrator>
.ReturnsAsync(new PaginationResult<ConcentratorDto>
{
Items = new List<Concentrator>
Items = new List<ConcentratorDto>
{
new(),
new(),
Expand Down Expand Up @@ -100,9 +100,9 @@ public void ClickToItemShouldRedirectToConcentratorDetailsPage()

_ = this.mockLoRaWanConcentratorsClientService.Setup(service =>
service.GetConcentrators(It.Is<string>(s => expectedUri.Equals(s, StringComparison.Ordinal))))
.ReturnsAsync(new PaginationResult<Concentrator>
.ReturnsAsync(new PaginationResult<ConcentratorDto>
{
Items = new List<Concentrator>
Items = new List<ConcentratorDto>
{
new()
{
Expand Down Expand Up @@ -130,9 +130,9 @@ public void ClickOnAddNewDeviceShouldNavigateToNewDevicePage()

_ = this.mockLoRaWanConcentratorsClientService.Setup(service =>
service.GetConcentrators(It.Is<string>(s => expectedUri.Equals(s, StringComparison.Ordinal))))
.ReturnsAsync(new PaginationResult<Concentrator>
.ReturnsAsync(new PaginationResult<ConcentratorDto>
{
Items = new List<Concentrator>
Items = new List<ConcentratorDto>
{
new(),
new(),
Expand All @@ -159,9 +159,9 @@ public void ClickOnRefreshShouldReloadConcentrators()

_ = this.mockLoRaWanConcentratorsClientService.Setup(service =>
service.GetConcentrators(It.Is<string>(s => expectedUri.Equals(s, StringComparison.Ordinal))))
.ReturnsAsync(new PaginationResult<Concentrator>
.ReturnsAsync(new PaginationResult<ConcentratorDto>
{
Items = Array.Empty<Concentrator>()
Items = Array.Empty<ConcentratorDto>()
});

var cut = RenderComponent<ConcentratorListPage>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public override void Setup()
public void ClickOnSaveShouldPostConcentratorDetails()
{
// Arrange
var mockConcentrator = new Concentrator
var mockConcentrator = new ConcentratorDto
{
DeviceId = "1234567890123456",
DeviceName = Guid.NewGuid().ToString(),
Expand All @@ -68,7 +68,7 @@ public void ClickOnSaveShouldPostConcentratorDetails()
});

_ = this.mockLoRaWanConcentratorsClientService.Setup(service =>
service.CreateConcentrator(It.Is<Concentrator>(concentrator =>
service.CreateConcentrator(It.Is<ConcentratorDto>(concentrator =>
mockConcentrator.DeviceId.Equals(concentrator.DeviceId, StringComparison.Ordinal))))
.Returns(Task.CompletedTask);

Expand All @@ -78,8 +78,8 @@ public void ClickOnSaveShouldPostConcentratorDetails()
cut.WaitForAssertion(() => cut.Find("#saveButton"));


cut.Find($"#{nameof(Concentrator.DeviceId)}").Change(mockConcentrator.DeviceId);
cut.Find($"#{nameof(Concentrator.DeviceName)}").Change(mockConcentrator.DeviceName);
cut.Find($"#{nameof(ConcentratorDto.DeviceId)}").Change(mockConcentrator.DeviceId);
cut.Find($"#{nameof(ConcentratorDto.DeviceName)}").Change(mockConcentrator.DeviceName);
cut.Instance.ChangeRegion(mockConcentrator.LoraRegion);

// Act
Expand All @@ -94,7 +94,7 @@ public void ClickOnSaveShouldPostConcentratorDetails()
public void ClickOnSaveShouldProcessProblemDetailsExceptionWhenIssueOccursOnCreatingConcentratorDetails()
{
// Arrange
var mockConcentrator = new Concentrator
var mockConcentrator = new ConcentratorDto
{
DeviceId = "1234567890123456",
DeviceName = Guid.NewGuid().ToString(),
Expand All @@ -108,16 +108,16 @@ public void ClickOnSaveShouldProcessProblemDetailsExceptionWhenIssueOccursOnCrea
});

_ = this.mockLoRaWanConcentratorsClientService.Setup(service =>
service.CreateConcentrator(It.Is<Concentrator>(concentrator =>
service.CreateConcentrator(It.Is<ConcentratorDto>(concentrator =>
mockConcentrator.DeviceId.Equals(concentrator.DeviceId, StringComparison.Ordinal))))
.ThrowsAsync(new ProblemDetailsException(new ProblemDetailsWithExceptionDetails()));

var cut = RenderComponent<CreateConcentratorPage>();
cut.WaitForAssertion(() => cut.Find("#saveButton"));


cut.Find($"#{nameof(Concentrator.DeviceId)}").Change(mockConcentrator.DeviceId);
cut.Find($"#{nameof(Concentrator.DeviceName)}").Change(mockConcentrator.DeviceName);
cut.Find($"#{nameof(ConcentratorDto.DeviceId)}").Change(mockConcentrator.DeviceId);
cut.Find($"#{nameof(ConcentratorDto.DeviceName)}").Change(mockConcentrator.DeviceName);
cut.Instance.ChangeRegion(mockConcentrator.LoraRegion);

// Act
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ public override void Setup()
public async Task GetConcentratorsShouldReturnConcentrators()
{
// Arrange
var expectedConcentrators = new PaginationResult<Concentrator>
var expectedConcentrators = new PaginationResult<ConcentratorDto>
{
Items = new List<Concentrator>()
Items = new List<ConcentratorDto>()
{
new ()
}
Expand All @@ -64,7 +64,7 @@ public async Task GetConcentratorShouldReturnConcentrator()
// Arrange
var deviceId = Fixture.Create<string>();

var expectedConcentrator = new Concentrator();
var expectedConcentrator = new ConcentratorDto();

_ = MockHttpClient.When(HttpMethod.Get, $"/api/lorawan/concentrators/{deviceId}")
.RespondJson(expectedConcentrator);
Expand All @@ -82,13 +82,13 @@ public async Task GetConcentratorShouldReturnConcentrator()
public async Task CreateConcentratorShouldCreateConcentrator()
{
// Arrange
var concentrator = new Concentrator();
var concentrator = new ConcentratorDto();

_ = MockHttpClient.When(HttpMethod.Post, "/api/lorawan/concentrators")
.With(m =>
{
_ = m.Content.Should().BeAssignableTo<ObjectContent<Concentrator>>();
var body = m.Content as ObjectContent<Concentrator>;
_ = m.Content.Should().BeAssignableTo<ObjectContent<ConcentratorDto>>();
var body = m.Content as ObjectContent<ConcentratorDto>;
_ = body.Value.Should().BeEquivalentTo(concentrator);
return true;
})
Expand All @@ -106,13 +106,13 @@ public async Task CreateConcentratorShouldCreateConcentrator()
public async Task UpdateConcentratorShouldUpdateConcentrator()
{
// Arrange
var concentrator = new Concentrator();
var concentrator = new ConcentratorDto();

_ = MockHttpClient.When(HttpMethod.Put, "/api/lorawan/concentrators")
.With(m =>
{
_ = m.Content.Should().BeAssignableTo<ObjectContent<Concentrator>>();
var body = m.Content as ObjectContent<Concentrator>;
_ = m.Content.Should().BeAssignableTo<ObjectContent<ConcentratorDto>>();
var body = m.Content as ObjectContent<ConcentratorDto>;
_ = body.Value.Should().BeEquivalentTo(concentrator);
return true;
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public void ValidateValidConcentrator()
{
// Arrange
var concentratorValidator = new ConcentratorValidator();
var concentrator = new Concentrator()
var concentrator = new ConcentratorDto()
{
DeviceId = "0123456789abcdef",
DeviceName = Guid.NewGuid().ToString(),
Expand All @@ -39,7 +39,7 @@ public void ValidateMissingFieldShouldReturnError(
{
// Arrange
var concentratorValidator = new ConcentratorValidator();
var concentrator = new Concentrator()
var concentrator = new ConcentratorDto()
{
DeviceId = "0123456789abcdef",
DeviceName =DeviceNameValue,
Expand All @@ -60,7 +60,7 @@ public void ValidateMissingDeviceIdShouldReturnError()
{
// Arrange
var concentratorValidator = new ConcentratorValidator();
var concentrator = new Concentrator()
var concentrator = new ConcentratorDto()
{
DeviceId = "",
DeviceName = Guid.NewGuid().ToString(),
Expand All @@ -83,7 +83,7 @@ public void ValidateBadFormatDeviceIdShouldReturnError()
{
// Arrange
var concentratorValidator = new ConcentratorValidator();
var concentrator = new Concentrator()
var concentrator = new ConcentratorDto()
{
DeviceId = Guid.NewGuid().ToString(),
DeviceName = Guid.NewGuid().ToString(),
Expand All @@ -104,7 +104,7 @@ public void ValidateBadFormatClientThumbprintShouldReturnError()
{
// Arrange
var concentratorValidator = new ConcentratorValidator();
var concentrator = new Concentrator()
var concentrator = new ConcentratorDto()
{
DeviceId = "0123456789abcdef",
DeviceName = Guid.NewGuid().ToString(),
Expand All @@ -126,7 +126,7 @@ public void ValidateAllFieldsEmptyShouldReturnError()
{
// Arrange
var concentratorValidator = new ConcentratorValidator();
var concentrator = new Concentrator();
var concentrator = new ConcentratorDto();

// Act
var concentratorValidation = concentratorValidator.Validate(concentrator);
Expand Down
Loading

0 comments on commit fecd9f5

Please sign in to comment.