Completata integrazione con autententicazione

This commit is contained in:
2025-09-23 13:06:14 +02:00
parent 6d5bc278d7
commit 560fb7607f
8 changed files with 1203 additions and 13 deletions

View File

@@ -0,0 +1,191 @@
using IntegryControlPanel.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace IntegryControlPanel.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class IntegryDataController : ControllerBase
{
private readonly IIntegryControlPanelService _integryService;
private readonly ILogger<IntegryDataController> _logger;
public IntegryDataController(
IIntegryControlPanelService integryService,
ILogger<IntegryDataController> logger)
{
_integryService = integryService;
_logger = logger;
}
[HttpGet("customers")]
[Authorize]
public async Task<IActionResult> GetCustomers()
{
try
{
var customers = await _integryService.GetAllCustomersAsync();
return Ok(customers);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving customers");
return StatusCode(500, "Internal server error");
}
}
[HttpGet("customers/{id}")]
[Authorize]
public async Task<IActionResult> GetCustomer(int id)
{
try
{
var customer = await _integryService.GetCustomerByIdAsync(id);
if (customer == null)
return NotFound();
return Ok(customer);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving customer {CustomerId}", id);
return StatusCode(500, "Internal server error");
}
}
[HttpGet("customers/{customerId}/servers")]
[Authorize]
public async Task<IActionResult> GetServersByCustomer(int customerId)
{
try
{
var servers = await _integryService.GetServersByCustomerIdAsync(customerId);
return Ok(servers);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving servers for customer {CustomerId}", customerId);
return StatusCode(500, "Internal server error");
}
}
[HttpGet("customers/{customerId}/devices")]
[Authorize]
public async Task<IActionResult> GetDevicesByCustomer(int customerId)
{
try
{
var devices = await _integryService.GetDevicesByCustomerIdAsync(customerId);
return Ok(devices);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving devices for customer {CustomerId}", customerId);
return StatusCode(500, "Internal server error");
}
}
[HttpGet("dashboard/stats")]
[Authorize]
public async Task<IActionResult> GetDashboardStats()
{
try
{
var stats = new
{
TotalCustomers = await _integryService.GetTotalCustomersAsync(),
TotalServers = await _integryService.GetTotalServersAsync(),
TotalDevices = await _integryService.GetTotalDevicesAsync(),
TotalInstallations = await _integryService.GetTotalInstallationsAsync()
};
return Ok(stats);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving dashboard stats");
return StatusCode(500, "Internal server error");
}
}
[HttpGet("dashboard/server-updates")]
[Authorize]
public async Task<IActionResult> GetServerLastUpdates()
{
try
{
var updates = await _integryService.GetServerLastUpdatesAsync();
return Ok(updates);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving server last updates");
return StatusCode(500, "Internal server error");
}
}
[HttpGet("services")]
[Authorize]
public async Task<IActionResult> GetServices()
{
try
{
var services = await _integryService.GetAllServicesAsync();
return Ok(services);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving services");
return StatusCode(500, "Internal server error");
}
}
[HttpGet("test-connection")]
public async Task<IActionResult> TestConnection()
{
try
{
var customerCount = await _integryService.GetTotalCustomersAsync();
return Ok(new {
Message = "Database connection successful",
CustomerCount = customerCount,
Timestamp = DateTime.Now
});
}
catch (Exception ex)
{
_logger.LogError(ex, "Database connection test failed");
return StatusCode(500, new {
Message = "Database connection failed",
Error = ex.Message,
Timestamp = DateTime.Now
});
}
}
[HttpGet("test-customers")]
public async Task<IActionResult> TestCustomers()
{
try
{
var customers = await _integryService.GetAllCustomersAsync();
return Ok(new {
Message = "Successfully retrieved customers",
Count = customers.Count(),
Customers = customers.Take(5).Select(c => new { c.Id, c.Name, c.Slug }),
Timestamp = DateTime.Now
});
}
catch (Exception ex)
{
_logger.LogError(ex, "Error testing customers retrieval");
return StatusCode(500, new {
Message = "Error retrieving customers",
Error = ex.Message,
Timestamp = DateTime.Now
});
}
}
}
}

View File

@@ -45,8 +45,14 @@ public partial class IntegryControlPanelDbContext : DbContext
public virtual DbSet<VwServerLastUpdate> VwServerLastUpdates { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
#warning To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see https://go.microsoft.com/fwlink/?LinkId=723263.
=> optionsBuilder.UseSqlServer("Server=SERVERDB2019;Database=integry_control_panel_test;Trusted_Connection=True;MultipleActiveResultSets=true;TrustServerCertificate=True;");
{
// Rimossa la connection string hard-coded - sarà configurata tramite DI
if (!optionsBuilder.IsConfigured)
{
// Configurazione di fallback solo per il design-time se necessaria
// optionsBuilder.UseSqlServer("Design time connection string if needed");
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{

View File

@@ -0,0 +1,303 @@
// <auto-generated />
using System;
using IntegryControlPanel.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace IntegryControlPanel.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("20250923110204_AddRoleSupport")]
partial class AddRoleSupport
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.9")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("IntegryControlPanel.Data.ApplicationUser", b =>
{
b.Property<string>("Id")
.HasColumnType("nvarchar(450)");
b.Property<int>("AccessFailedCount")
.HasColumnType("int");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("nvarchar(max)");
b.Property<string>("Department")
.HasColumnType("nvarchar(max)");
b.Property<string>("DisplayName")
.HasColumnType("nvarchar(max)");
b.Property<string>("Email")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<bool>("EmailConfirmed")
.HasColumnType("bit");
b.Property<string>("FirstName")
.HasColumnType("nvarchar(max)");
b.Property<bool>("IsLdapUser")
.HasColumnType("bit");
b.Property<DateTime?>("LastLdapSync")
.HasColumnType("datetime2");
b.Property<string>("LastName")
.HasColumnType("nvarchar(max)");
b.Property<string>("LdapUsername")
.HasColumnType("nvarchar(max)");
b.Property<bool>("LockoutEnabled")
.HasColumnType("bit");
b.Property<DateTimeOffset?>("LockoutEnd")
.HasColumnType("datetimeoffset");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("NormalizedUserName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("PasswordHash")
.HasColumnType("nvarchar(max)");
b.Property<string>("PhoneNumber")
.HasColumnType("nvarchar(max)");
b.Property<bool>("PhoneNumberConfirmed")
.HasColumnType("bit");
b.Property<string>("SecurityStamp")
.HasColumnType("nvarchar(max)");
b.Property<string>("Title")
.HasColumnType("nvarchar(max)");
b.Property<bool>("TwoFactorEnabled")
.HasColumnType("bit");
b.Property<string>("UserName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.HasKey("Id");
b.HasIndex("NormalizedEmail")
.HasDatabaseName("EmailIndex");
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasDatabaseName("UserNameIndex")
.HasFilter("[NormalizedUserName] IS NOT NULL");
b.ToTable("AspNetUsers", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id")
.HasColumnType("nvarchar(450)");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("nvarchar(max)");
b.Property<string>("Name")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("NormalizedName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.HasKey("Id");
b.HasIndex("NormalizedName")
.IsUnique()
.HasDatabaseName("RoleNameIndex")
.HasFilter("[NormalizedName] IS NOT NULL");
b.ToTable("AspNetRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("nvarchar(max)");
b.Property<string>("ClaimValue")
.HasColumnType("nvarchar(max)");
b.Property<string>("RoleId")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("AspNetRoleClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("nvarchar(max)");
b.Property<string>("ClaimValue")
.HasColumnType("nvarchar(max)");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AspNetUserClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.Property<string>("LoginProvider")
.HasColumnType("nvarchar(450)");
b.Property<string>("ProviderKey")
.HasColumnType("nvarchar(450)");
b.Property<string>("ProviderDisplayName")
.HasColumnType("nvarchar(max)");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.HasKey("LoginProvider", "ProviderKey");
b.HasIndex("UserId");
b.ToTable("AspNetUserLogins", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("nvarchar(450)");
b.Property<string>("RoleId")
.HasColumnType("nvarchar(450)");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("AspNetUserRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("nvarchar(450)");
b.Property<string>("LoginProvider")
.HasColumnType("nvarchar(450)");
b.Property<string>("Name")
.HasColumnType("nvarchar(450)");
b.Property<string>("Value")
.HasColumnType("nvarchar(max)");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AspNetUserTokens", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("IntegryControlPanel.Data.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("IntegryControlPanel.Data.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("IntegryControlPanel.Data.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("IntegryControlPanel.Data.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,22 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace IntegryControlPanel.Migrations
{
/// <inheritdoc />
public partial class AddRoleSupport : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
}
}
}

View File

@@ -24,20 +24,42 @@ builder.Services.AddCascadingAuthenticationState();
builder.Services.AddScoped<IdentityUserAccessor>();
builder.Services.AddScoped<IdentityRedirectManager>();
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = IdentityConstants.ApplicationScheme;
options.DefaultSignInScheme = IdentityConstants.ExternalScheme;
})
.AddIdentityCookies();
builder.Services.AddAuthorization();
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");
// Configurazione DbContext per Identity (ApplicationDbContext)
var defaultConnectionString = builder.Configuration.GetConnectionString("DefaultConnection")
?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
options.UseSqlServer(defaultConnectionString));
// Configurazione DbContext per il database esistente (IntegryControlPanelDbContext)
var integryConnectionString = builder.Configuration.GetConnectionString("IntegryControlPanelConnection")
?? throw new InvalidOperationException("Connection string 'IntegryControlPanelConnection' not found.");
builder.Services.AddDbContext<IntegryControlPanelDbContext>(options =>
options.UseSqlServer(integryConnectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddIdentityCore<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
// Configurazione Identity completa con ruoli - gestisce automaticamente l'autenticazione
builder.Services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
options.SignIn.RequireConfirmedAccount = false; // Cambiato a false per semplificare i test
// Configurazioni aggiuntive per Identity
options.Password.RequireDigit = true;
options.Password.RequiredLength = 6;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireUppercase = false;
options.Password.RequireLowercase = false;
// Configurazioni per il lockout
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
options.Lockout.MaxFailedAccessAttempts = 5;
options.Lockout.AllowedForNewUsers = true;
// Configurazioni per gli utenti
options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
options.User.RequireUniqueEmail = false;
})
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddSignInManager<LdapSignInManager>()
.AddDefaultTokenProviders();
@@ -46,6 +68,9 @@ builder.Services.AddIdentityCore<ApplicationUser>(options => options.SignIn.Requ
builder.Services.AddScoped<ILdapService, LdapService>();
builder.Services.AddScoped<LdapUserManager>();
// Registra il servizio per gestire il database esistente
builder.Services.AddScoped<IIntegryControlPanelService, IntegryControlPanelService>();
builder.Services.AddSingleton<IEmailSender<ApplicationUser>, IdentityNoOpEmailSender>();
var app = builder.Build();
@@ -65,6 +90,10 @@ else
app.UseHttpsRedirection();
// Aggiungiamo l'autenticazione nel pipeline
app.UseAuthentication();
app.UseAuthorization();
app.UseAntiforgery();
app.MapStaticAssets();

View File

@@ -0,0 +1,56 @@
using IntegryControlPanel.Data;
using IntegryControlPanel.Models.IntegryControlPanel;
using Microsoft.EntityFrameworkCore;
namespace IntegryControlPanel.Services
{
public interface IIntegryControlPanelService
{
// Customer operations
Task<IEnumerable<Customer>> GetAllCustomersAsync();
Task<Customer?> GetCustomerByIdAsync(int id);
Task<Customer?> GetCustomerBySlugAsync(string slug);
Task<Customer> CreateCustomerAsync(Customer customer);
Task<Customer> UpdateCustomerAsync(Customer customer);
Task<bool> DeleteCustomerAsync(int id);
// Server operations
Task<IEnumerable<Server>> GetServersByCustomerIdAsync(int customerId);
Task<Server?> GetServerByIdAsync(int id);
Task<Server> CreateServerAsync(Server server);
Task<Server> UpdateServerAsync(Server server);
Task<bool> DeleteServerAsync(int id);
// Device operations
Task<IEnumerable<Device>> GetDevicesByCustomerIdAsync(int customerId);
Task<Device?> GetDeviceByIdAsync(int id);
Task<Device> CreateDeviceAsync(Device device);
Task<Device> UpdateDeviceAsync(Device device);
// Installation operations
Task<IEnumerable<Installation>> GetInstallationsByCustomerIdAsync(int customerId);
Task<Installation?> GetInstallationByIdAsync(int id);
Task<Installation> CreateInstallationAsync(Installation installation);
Task<Installation> UpdateInstallationAsync(Installation installation);
// Service operations
Task<IEnumerable<Service>> GetAllServicesAsync();
Task<Service?> GetServiceByIdAsync(int id);
Task<Service?> GetServiceBySlugAsync(string slug);
Task<Service> CreateServiceAsync(Service service);
Task<Service> UpdateServiceAsync(Service service);
// Release operations
Task<IEnumerable<Release>> GetReleasesByServiceIdAsync(int serviceId);
Task<Release?> GetReleaseByIdAsync(int id);
Task<Release> CreateReleaseAsync(Release release);
Task<Release> UpdateReleaseAsync(Release release);
// Dashboard operations
Task<IEnumerable<VwServerLastUpdate>> GetServerLastUpdatesAsync();
Task<int> GetTotalCustomersAsync();
Task<int> GetTotalServersAsync();
Task<int> GetTotalDevicesAsync();
Task<int> GetTotalInstallationsAsync();
}
}

View File

@@ -0,0 +1,583 @@
using IntegryControlPanel.Data;
using IntegryControlPanel.Models.IntegryControlPanel;
using Microsoft.EntityFrameworkCore;
namespace IntegryControlPanel.Services
{
public class IntegryControlPanelService : IIntegryControlPanelService
{
private readonly IntegryControlPanelDbContext _context;
private readonly ILogger<IntegryControlPanelService> _logger;
public IntegryControlPanelService(IntegryControlPanelDbContext context, ILogger<IntegryControlPanelService> logger)
{
_context = context;
_logger = logger;
}
#region Customer Operations
public async Task<IEnumerable<Customer>> GetAllCustomersAsync()
{
try
{
return await _context.Customers
.OrderBy(c => c.Name)
.ToListAsync();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving all customers");
throw;
}
}
public async Task<Customer?> GetCustomerByIdAsync(int id)
{
try
{
return await _context.Customers
.Include(c => c.Servers)
.Include(c => c.Devices)
.Include(c => c.ApplicationInfos)
.FirstOrDefaultAsync(c => c.Id == id);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving customer with id {CustomerId}", id);
throw;
}
}
public async Task<Customer?> GetCustomerBySlugAsync(string slug)
{
try
{
return await _context.Customers
.Include(c => c.Servers)
.Include(c => c.Devices)
.FirstOrDefaultAsync(c => c.Slug == slug);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving customer with slug {Slug}", slug);
throw;
}
}
public async Task<Customer> CreateCustomerAsync(Customer customer)
{
try
{
_context.Customers.Add(customer);
await _context.SaveChangesAsync();
_logger.LogInformation("Created customer {CustomerName} with id {CustomerId}", customer.Name, customer.Id);
return customer;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error creating customer {CustomerName}", customer.Name);
throw;
}
}
public async Task<Customer> UpdateCustomerAsync(Customer customer)
{
try
{
_context.Customers.Update(customer);
await _context.SaveChangesAsync();
_logger.LogInformation("Updated customer {CustomerName} with id {CustomerId}", customer.Name, customer.Id);
return customer;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error updating customer with id {CustomerId}", customer.Id);
throw;
}
}
public async Task<bool> DeleteCustomerAsync(int id)
{
try
{
var customer = await _context.Customers.FindAsync(id);
if (customer == null)
return false;
_context.Customers.Remove(customer);
await _context.SaveChangesAsync();
_logger.LogInformation("Deleted customer with id {CustomerId}", id);
return true;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error deleting customer with id {CustomerId}", id);
throw;
}
}
#endregion
#region Server Operations
public async Task<IEnumerable<Server>> GetServersByCustomerIdAsync(int customerId)
{
try
{
return await _context.Servers
.Where(s => s.CustomerId == customerId)
.Include(s => s.Customer)
.Include(s => s.Installations)
.OrderBy(s => s.Ip)
.ToListAsync();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving servers for customer {CustomerId}", customerId);
throw;
}
}
public async Task<Server?> GetServerByIdAsync(int id)
{
try
{
return await _context.Servers
.Include(s => s.Customer)
.Include(s => s.Installations)
.ThenInclude(i => i.Release)
.FirstOrDefaultAsync(s => s.Id == id);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving server with id {ServerId}", id);
throw;
}
}
public async Task<Server> CreateServerAsync(Server server)
{
try
{
_context.Servers.Add(server);
await _context.SaveChangesAsync();
_logger.LogInformation("Created server {ServerIp} for customer {CustomerId}", server.Ip, server.CustomerId);
return server;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error creating server {ServerIp}", server.Ip);
throw;
}
}
public async Task<Server> UpdateServerAsync(Server server)
{
try
{
_context.Servers.Update(server);
await _context.SaveChangesAsync();
_logger.LogInformation("Updated server with id {ServerId}", server.Id);
return server;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error updating server with id {ServerId}", server.Id);
throw;
}
}
public async Task<bool> DeleteServerAsync(int id)
{
try
{
var server = await _context.Servers.FindAsync(id);
if (server == null)
return false;
_context.Servers.Remove(server);
await _context.SaveChangesAsync();
_logger.LogInformation("Deleted server with id {ServerId}", id);
return true;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error deleting server with id {ServerId}", id);
throw;
}
}
#endregion
#region Device Operations
public async Task<IEnumerable<Device>> GetDevicesByCustomerIdAsync(int customerId)
{
try
{
return await _context.Devices
.Where(d => d.CustomerId == customerId)
.Include(d => d.Customer)
.Include(d => d.Installations)
.OrderBy(d => d.Ip)
.ToListAsync();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving devices for customer {CustomerId}", customerId);
throw;
}
}
public async Task<Device?> GetDeviceByIdAsync(int id)
{
try
{
return await _context.Devices
.Include(d => d.Customer)
.Include(d => d.Installations)
.ThenInclude(i => i.Release)
.FirstOrDefaultAsync(d => d.Id == id);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving device with id {DeviceId}", id);
throw;
}
}
public async Task<Device> CreateDeviceAsync(Device device)
{
try
{
_context.Devices.Add(device);
await _context.SaveChangesAsync();
_logger.LogInformation("Created device {DeviceIp} for customer {CustomerId}", device.Ip, device.CustomerId);
return device;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error creating device {DeviceIp}", device.Ip);
throw;
}
}
public async Task<Device> UpdateDeviceAsync(Device device)
{
try
{
_context.Devices.Update(device);
await _context.SaveChangesAsync();
_logger.LogInformation("Updated device with id {DeviceId}", device.Id);
return device;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error updating device with id {DeviceId}", device.Id);
throw;
}
}
#endregion
#region Installation Operations
public async Task<IEnumerable<Installation>> GetInstallationsByCustomerIdAsync(int customerId)
{
try
{
return await _context.Installations
.Include(i => i.Server)
.Include(i => i.Device)
.Include(i => i.Release)
.ThenInclude(r => r.Service)
.Where(i => i.Server!.CustomerId == customerId || i.Device!.CustomerId == customerId)
.OrderByDescending(i => i.LastUpdate)
.ToListAsync();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving installations for customer {CustomerId}", customerId);
throw;
}
}
public async Task<Installation?> GetInstallationByIdAsync(int id)
{
try
{
return await _context.Installations
.Include(i => i.Server)
.ThenInclude(s => s!.Customer)
.Include(i => i.Device)
.ThenInclude(d => d!.Customer)
.Include(i => i.Release)
.ThenInclude(r => r!.Service)
.FirstOrDefaultAsync(i => i.Id == id);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving installation with id {InstallationId}", id);
throw;
}
}
public async Task<Installation> CreateInstallationAsync(Installation installation)
{
try
{
_context.Installations.Add(installation);
await _context.SaveChangesAsync();
_logger.LogInformation("Created installation with id {InstallationId}", installation.Id);
return installation;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error creating installation");
throw;
}
}
public async Task<Installation> UpdateInstallationAsync(Installation installation)
{
try
{
_context.Installations.Update(installation);
await _context.SaveChangesAsync();
_logger.LogInformation("Updated installation with id {InstallationId}", installation.Id);
return installation;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error updating installation with id {InstallationId}", installation.Id);
throw;
}
}
#endregion
#region Service Operations
public async Task<IEnumerable<Service>> GetAllServicesAsync()
{
try
{
return await _context.Services
.Include(s => s.Releases)
.OrderBy(s => s.Name)
.ToListAsync();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving all services");
throw;
}
}
public async Task<Service?> GetServiceByIdAsync(int id)
{
try
{
return await _context.Services
.Include(s => s.Releases)
.FirstOrDefaultAsync(s => s.Id == id);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving service with id {ServiceId}", id);
throw;
}
}
public async Task<Service?> GetServiceBySlugAsync(string slug)
{
try
{
return await _context.Services
.Include(s => s.Releases)
.FirstOrDefaultAsync(s => s.Slug == slug);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving service with slug {Slug}", slug);
throw;
}
}
public async Task<Service> CreateServiceAsync(Service service)
{
try
{
_context.Services.Add(service);
await _context.SaveChangesAsync();
_logger.LogInformation("Created service {ServiceName} with id {ServiceId}", service.Name, service.Id);
return service;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error creating service {ServiceName}", service.Name);
throw;
}
}
public async Task<Service> UpdateServiceAsync(Service service)
{
try
{
_context.Services.Update(service);
await _context.SaveChangesAsync();
_logger.LogInformation("Updated service with id {ServiceId}", service.Id);
return service;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error updating service with id {ServiceId}", service.Id);
throw;
}
}
#endregion
#region Release Operations
public async Task<IEnumerable<Release>> GetReleasesByServiceIdAsync(int serviceId)
{
try
{
return await _context.Releases
.Where(r => r.ServiceId == serviceId)
.Include(r => r.Service)
.OrderByDescending(r => r.ReleaseDate)
.ToListAsync();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving releases for service {ServiceId}", serviceId);
throw;
}
}
public async Task<Release?> GetReleaseByIdAsync(int id)
{
try
{
return await _context.Releases
.Include(r => r.Service)
.Include(r => r.Installations)
.FirstOrDefaultAsync(r => r.Id == id);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving release with id {ReleaseId}", id);
throw;
}
}
public async Task<Release> CreateReleaseAsync(Release release)
{
try
{
_context.Releases.Add(release);
await _context.SaveChangesAsync();
_logger.LogInformation("Created release {ReleaseVersion} for service {ServiceId}", release.Version, release.ServiceId);
return release;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error creating release {ReleaseVersion}", release.Version);
throw;
}
}
public async Task<Release> UpdateReleaseAsync(Release release)
{
try
{
_context.Releases.Update(release);
await _context.SaveChangesAsync();
_logger.LogInformation("Updated release with id {ReleaseId}", release.Id);
return release;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error updating release with id {ReleaseId}", release.Id);
throw;
}
}
#endregion
#region Dashboard Operations
public async Task<IEnumerable<VwServerLastUpdate>> GetServerLastUpdatesAsync()
{
try
{
return await _context.VwServerLastUpdates
.OrderByDescending(v => v.LastUpdate)
.Take(50) // Limita i risultati per le performance
.ToListAsync();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving server last updates");
throw;
}
}
public async Task<int> GetTotalCustomersAsync()
{
try
{
return await _context.Customers.CountAsync();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error counting customers");
throw;
}
}
public async Task<int> GetTotalServersAsync()
{
try
{
return await _context.Servers.CountAsync();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error counting servers");
throw;
}
}
public async Task<int> GetTotalDevicesAsync()
{
try
{
return await _context.Devices.CountAsync();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error counting devices");
throw;
}
}
public async Task<int> GetTotalInstallationsAsync()
{
try
{
return await _context.Installations.CountAsync();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error counting installations");
throw;
}
}
#endregion
}
}

View File

@@ -1,7 +1,7 @@
{
"ConnectionStrings": {
"DefaultConnection": "Server=SERVERDB2019;Database=integry_control_panel_test;Trusted_Connection=True;MultipleActiveResultSets=true"
"DefaultConnection": "Server=SERVERDB2019;Database=integry_control_panel_identity;Trusted_Connection=True;MultipleActiveResultSets=true;TrustServerCertificate=True;",
"IntegryControlPanelConnection": "Server=SERVERDB2019;Database=integry_control_panel_test;Trusted_Connection=True;MultipleActiveResultSets=true;TrustServerCertificate=True;"
},
"LDAP": {
"Server": "your-domain-controller.domain.com",