Integrazione base del DB esistente e login tramite LDAP
This commit is contained in:
@@ -24,8 +24,8 @@
|
||||
|
||||
<MudGrid>
|
||||
<MudItem md="12">
|
||||
<MudStaticTextField For="@(() => Input.Email)" @bind-Value="Input.Email"
|
||||
Label="Email" Placeholder="name@example.com"
|
||||
<MudStaticTextField For="@(() => Input.Username)" @bind-Value="Input.Username"
|
||||
Label="Username" Placeholder="MarioR"
|
||||
UserAttributes="@(new() { { "autocomplete", "username" }, { "aria-required", "true" } } )" />
|
||||
</MudItem>
|
||||
<MudItem md="12">
|
||||
@@ -82,7 +82,7 @@
|
||||
{
|
||||
// This doesn't count login failures towards account lockout
|
||||
// To enable password failures to trigger account lockout, set lockoutOnFailure: true
|
||||
var result = await SignInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: false);
|
||||
var result = await SignInManager.PasswordSignInAsync(Input.Username, Input.Password, Input.RememberMe, lockoutOnFailure: false);
|
||||
if (result.Succeeded)
|
||||
{
|
||||
Logger.LogInformation("User logged in.");
|
||||
@@ -108,8 +108,8 @@
|
||||
private sealed class InputModel
|
||||
{
|
||||
[Required]
|
||||
[EmailAddress]
|
||||
public string Email { get; set; } = "";
|
||||
// [EmailAddress]
|
||||
public string Username { get; set; } = "";
|
||||
|
||||
[Required]
|
||||
[DataType(DataType.Password)]
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
using IntegryControlPanel.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace IntegryControlPanel.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
public class LdapController : ControllerBase
|
||||
{
|
||||
private readonly ILdapService _ldapService;
|
||||
private readonly LdapUserManager _ldapUserManager;
|
||||
private readonly ILogger<LdapController> _logger;
|
||||
|
||||
public LdapController(
|
||||
ILdapService ldapService,
|
||||
LdapUserManager ldapUserManager,
|
||||
ILogger<LdapController> logger)
|
||||
{
|
||||
_ldapService = ldapService;
|
||||
_ldapUserManager = ldapUserManager;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
[HttpPost("sync-user")]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> SyncUser([FromBody] string username)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(username))
|
||||
return BadRequest("Username is required");
|
||||
|
||||
try
|
||||
{
|
||||
var user = await _ldapUserManager.SyncUserFromLdapAsync(username);
|
||||
if (user == null)
|
||||
return NotFound($"User {username} not found in LDAP");
|
||||
|
||||
return Ok(new
|
||||
{
|
||||
Message = "User synced successfully",
|
||||
User = new
|
||||
{
|
||||
user.UserName,
|
||||
user.Email,
|
||||
user.FirstName,
|
||||
user.LastName,
|
||||
user.Department,
|
||||
user.Title,
|
||||
user.LastLdapSync
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error syncing user {Username}", username);
|
||||
return StatusCode(500, "Internal server error");
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet("users-in-group/{groupName}")]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> GetUsersInGroup(string groupName)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(groupName))
|
||||
return BadRequest("Group name is required");
|
||||
|
||||
try
|
||||
{
|
||||
var users = await _ldapService.GetUsersInGroupAsync(groupName);
|
||||
return Ok(users);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error getting users in group {GroupName}", groupName);
|
||||
return StatusCode(500, "Internal server error");
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet("user/{username}")]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> GetUser(string username)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(username))
|
||||
return BadRequest("Username is required");
|
||||
|
||||
try
|
||||
{
|
||||
var user = await _ldapService.GetUserAsync(username);
|
||||
if (user == null)
|
||||
return NotFound($"User {username} not found in LDAP");
|
||||
|
||||
return Ok(user);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error getting user {Username}", username);
|
||||
return StatusCode(500, "Internal server error");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,13 @@ namespace IntegryControlPanel.Data
|
||||
// Add profile data for application users by adding properties to the ApplicationUser class
|
||||
public class ApplicationUser : IdentityUser
|
||||
{
|
||||
public string? FirstName { get; set; }
|
||||
public string? LastName { get; set; }
|
||||
public string? DisplayName { get; set; }
|
||||
public string? Department { get; set; }
|
||||
public string? Title { get; set; }
|
||||
public bool IsLdapUser { get; set; } = false;
|
||||
public string? LdapUsername { get; set; }
|
||||
public DateTime? LastLdapSync { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,515 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using IntegryControlPanel.Models.IntegryControlPanel;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace IntegryControlPanel.Data;
|
||||
|
||||
public partial class IntegryControlPanelDbContext : DbContext
|
||||
{
|
||||
public IntegryControlPanelDbContext()
|
||||
{
|
||||
}
|
||||
|
||||
public IntegryControlPanelDbContext(DbContextOptions<IntegryControlPanelDbContext> options)
|
||||
: base(options)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual DbSet<ApplicationInfo> ApplicationInfos { get; set; }
|
||||
|
||||
public virtual DbSet<Models.IntegryControlPanel.Client> Clients { get; set; }
|
||||
|
||||
public virtual DbSet<Configurazioni> Configurazionis { get; set; }
|
||||
|
||||
public virtual DbSet<Customer> Customers { get; set; }
|
||||
|
||||
public virtual DbSet<DatabaseEngine> DatabaseEngines { get; set; }
|
||||
|
||||
public virtual DbSet<DatabasesInfo> DatabasesInfos { get; set; }
|
||||
|
||||
public virtual DbSet<Device> Devices { get; set; }
|
||||
|
||||
public virtual DbSet<Installation> Installations { get; set; }
|
||||
|
||||
public virtual DbSet<PvmsInfo> PvmsInfos { get; set; }
|
||||
|
||||
public virtual DbSet<Release> Releases { get; set; }
|
||||
|
||||
public virtual DbSet<SalvataggiSoap> SalvataggiSoaps { get; set; }
|
||||
|
||||
public virtual DbSet<Server> Servers { get; set; }
|
||||
|
||||
public virtual DbSet<Service> Services { get; set; }
|
||||
|
||||
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;");
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder.Entity<ApplicationInfo>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Id).HasName("PK__applicat__3213E83F4185DE9F");
|
||||
|
||||
entity.ToTable("application_infos");
|
||||
|
||||
entity.HasIndex(e => e.CustomerId, "IDX_D5E65179395C3F3");
|
||||
|
||||
entity.Property(e => e.Id).HasColumnName("id");
|
||||
entity.Property(e => e.AnnoContab).HasColumnName("anno_contab");
|
||||
entity.Property(e => e.AnnoMagaz).HasColumnName("anno_magaz");
|
||||
entity.Property(e => e.AnsiPadding)
|
||||
.IsRequired()
|
||||
.HasDefaultValueSql("('0')")
|
||||
.HasColumnName("ansi_padding");
|
||||
entity.Property(e => e.ConcatNullYieldsNull)
|
||||
.IsRequired()
|
||||
.HasDefaultValueSql("('0')")
|
||||
.HasColumnName("concat_null_yields_null");
|
||||
entity.Property(e => e.CustomerId).HasColumnName("customer_id");
|
||||
entity.Property(e => e.DelimitedIdentifier)
|
||||
.IsRequired()
|
||||
.HasDefaultValueSql("('0')")
|
||||
.HasColumnName("delimited_identifier");
|
||||
entity.Property(e => e.MenuPersonalizzato)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("menu_personalizzato");
|
||||
entity.Property(e => e.Name)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("name");
|
||||
entity.Property(e => e.NewUpdProgMaga).HasColumnName("new_upd_prog_maga");
|
||||
|
||||
entity.HasOne(d => d.Customer).WithMany(p => p.ApplicationInfos)
|
||||
.HasForeignKey(d => d.CustomerId)
|
||||
.HasConstraintName("FK_D5E65179395C3F3");
|
||||
});
|
||||
|
||||
modelBuilder.Entity<Models.IntegryControlPanel.Client>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Id).HasName("PK__clients__3213E83FFF8DC3E2");
|
||||
|
||||
entity.ToTable("clients");
|
||||
|
||||
entity.Property(e => e.Id).HasColumnName("id");
|
||||
entity.Property(e => e.DeviceId)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("device_id");
|
||||
entity.Property(e => e.InsertDate)
|
||||
.HasPrecision(6)
|
||||
.HasColumnName("insert_date");
|
||||
entity.Property(e => e.LastUpdate)
|
||||
.HasPrecision(6)
|
||||
.HasColumnName("last_update");
|
||||
entity.Property(e => e.NomeAzienda)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("nome_azienda");
|
||||
entity.Property(e => e.RemoteAddr)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("remote_addr");
|
||||
});
|
||||
|
||||
modelBuilder.Entity<Configurazioni>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Id).HasName("PK__configur__3213E83FB9077FED");
|
||||
|
||||
entity.ToTable("configurazioni");
|
||||
|
||||
entity.Property(e => e.Id).HasColumnName("id");
|
||||
entity.Property(e => e.JavaVersion)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("java_version");
|
||||
entity.Property(e => e.LastUpdate)
|
||||
.HasPrecision(6)
|
||||
.HasColumnName("last_update");
|
||||
entity.Property(e => e.MaxPermSize)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("max_perm_size");
|
||||
entity.Property(e => e.NomeAzienda)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("nome_azienda");
|
||||
entity.Property(e => e.OsArch)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("os_arch");
|
||||
entity.Property(e => e.OsName)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("os_name");
|
||||
entity.Property(e => e.RemoteAddr)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("remote_addr");
|
||||
entity.Property(e => e.Xms)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("xms");
|
||||
entity.Property(e => e.Xmx)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("xmx");
|
||||
});
|
||||
|
||||
modelBuilder.Entity<Customer>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Id).HasName("PK__customer__3213E83FD00417AC");
|
||||
|
||||
entity.ToTable("customers");
|
||||
|
||||
entity.HasIndex(e => e.Slug, "UNIQ_62534E21989D9B62")
|
||||
.IsUnique()
|
||||
.HasFilter("([slug] IS NOT NULL)");
|
||||
|
||||
entity.Property(e => e.Id).HasColumnName("id");
|
||||
entity.Property(e => e.Active)
|
||||
.IsRequired()
|
||||
.HasDefaultValueSql("('0')")
|
||||
.HasColumnName("active");
|
||||
entity.Property(e => e.Name)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("name");
|
||||
entity.Property(e => e.PartitaIva)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("partita_iva");
|
||||
entity.Property(e => e.Slug)
|
||||
.HasMaxLength(191)
|
||||
.HasColumnName("slug");
|
||||
});
|
||||
|
||||
modelBuilder.Entity<DatabaseEngine>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Id).HasName("PK__database__3213E83F8526E221");
|
||||
|
||||
entity.ToTable("database_engines");
|
||||
|
||||
entity.HasIndex(e => e.CustomerId, "UNIQ_1D94CC5C9395C3F3")
|
||||
.IsUnique()
|
||||
.HasFilter("([customer_id] IS NOT NULL)");
|
||||
|
||||
entity.Property(e => e.Id).HasColumnName("id");
|
||||
entity.Property(e => e.CustomerId).HasColumnName("customer_id");
|
||||
entity.Property(e => e.ProductEdition)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("product_edition");
|
||||
entity.Property(e => e.ProductLevel)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("product_level");
|
||||
entity.Property(e => e.ProductVersion)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("product_version");
|
||||
entity.Property(e => e.ProductVersionName)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("product_version_name");
|
||||
|
||||
entity.HasOne(d => d.Customer).WithOne(p => p.DatabaseEngine)
|
||||
.HasForeignKey<DatabaseEngine>(d => d.CustomerId)
|
||||
.HasConstraintName("FK_1D94CC5C9395C3F3");
|
||||
});
|
||||
|
||||
modelBuilder.Entity<DatabasesInfo>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Id).HasName("PK__database__3213E83FC619B4B0");
|
||||
|
||||
entity.ToTable("databases_info");
|
||||
|
||||
entity.HasIndex(e => e.DatabaseEngineId, "IDX_99DAF4F8AB25983");
|
||||
|
||||
entity.Property(e => e.Id).HasColumnName("id");
|
||||
entity.Property(e => e.DatabaseEngineId).HasColumnName("database_engine_id");
|
||||
entity.Property(e => e.LogicalName)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("logical_name");
|
||||
entity.Property(e => e.MaxSizeMb).HasColumnName("max_size_mb");
|
||||
entity.Property(e => e.Name)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("name");
|
||||
entity.Property(e => e.SizeMb).HasColumnName("size_mb");
|
||||
|
||||
entity.HasOne(d => d.DatabaseEngine).WithMany(p => p.DatabasesInfos)
|
||||
.HasForeignKey(d => d.DatabaseEngineId)
|
||||
.HasConstraintName("FK_99DAF4F8AB25983");
|
||||
});
|
||||
|
||||
modelBuilder.Entity<Device>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Id).HasName("PK__devices__3213E83F185C7B65");
|
||||
|
||||
entity.ToTable("devices");
|
||||
|
||||
entity.HasIndex(e => e.CustomerId, "IDX_11074E9A9395C3F3");
|
||||
|
||||
entity.Property(e => e.Id).HasColumnName("id");
|
||||
entity.Property(e => e.CustomerId).HasColumnName("customer_id");
|
||||
entity.Property(e => e.Info)
|
||||
.IsUnicode(false)
|
||||
.HasComment("(DC2Type:simple_array)")
|
||||
.HasColumnName("info");
|
||||
entity.Property(e => e.Ip)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("ip");
|
||||
entity.Property(e => e.Port).HasColumnName("port");
|
||||
|
||||
entity.HasOne(d => d.Customer).WithMany(p => p.Devices)
|
||||
.HasForeignKey(d => d.CustomerId)
|
||||
.HasConstraintName("FK_11074E9A9395C3F3");
|
||||
});
|
||||
|
||||
modelBuilder.Entity<Installation>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Id).HasName("PK__installa__3213E83F11ECD973");
|
||||
|
||||
entity.ToTable("installations");
|
||||
|
||||
entity.HasIndex(e => e.ServerId, "IDX_A774F67B1844E6B7");
|
||||
|
||||
entity.HasIndex(e => e.DeviceId, "IDX_A774F67B94A4C7D4");
|
||||
|
||||
entity.HasIndex(e => e.ReleaseId, "IDX_A774F67BB12A727D");
|
||||
|
||||
entity.Property(e => e.Id).HasColumnName("id");
|
||||
entity.Property(e => e.DeviceId).HasColumnName("device_id");
|
||||
entity.Property(e => e.InstallDate)
|
||||
.HasPrecision(6)
|
||||
.HasColumnName("install_date");
|
||||
entity.Property(e => e.LastUpdate)
|
||||
.HasPrecision(6)
|
||||
.HasColumnName("last_update");
|
||||
entity.Property(e => e.Notes)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("notes");
|
||||
entity.Property(e => e.Options)
|
||||
.IsUnicode(false)
|
||||
.HasComment("(DC2Type:simple_array)")
|
||||
.HasColumnName("options");
|
||||
entity.Property(e => e.ReleaseId).HasColumnName("release_id");
|
||||
entity.Property(e => e.ServerId).HasColumnName("server_id");
|
||||
|
||||
entity.HasOne(d => d.Device).WithMany(p => p.Installations)
|
||||
.HasForeignKey(d => d.DeviceId)
|
||||
.HasConstraintName("FK_A774F67B94A4C7D4");
|
||||
|
||||
entity.HasOne(d => d.Release).WithMany(p => p.Installations)
|
||||
.HasForeignKey(d => d.ReleaseId)
|
||||
.HasConstraintName("FK_A774F67BB12A727D");
|
||||
|
||||
entity.HasOne(d => d.Server).WithMany(p => p.Installations)
|
||||
.HasForeignKey(d => d.ServerId)
|
||||
.HasConstraintName("FK_A774F67B1844E6B7");
|
||||
});
|
||||
|
||||
modelBuilder.Entity<PvmsInfo>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Id).HasName("PK__pvms_inf__3213E83F8EA1FE36");
|
||||
|
||||
entity.ToTable("pvms_info");
|
||||
|
||||
entity.HasIndex(e => e.CustomerId, "IDX_4BCCAB779395C3F3");
|
||||
|
||||
entity.Property(e => e.Id).HasColumnName("id");
|
||||
entity.Property(e => e.CustomerId).HasColumnName("customer_id");
|
||||
entity.Property(e => e.DefaultCharset)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("default_charset");
|
||||
entity.Property(e => e.Imagick)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("imagick");
|
||||
entity.Property(e => e.MagicQuotesGpc).HasColumnName("magic_quotes_gpc");
|
||||
entity.Property(e => e.MaxExecutionTime).HasColumnName("max_execution_time");
|
||||
entity.Property(e => e.MaxInputVars).HasColumnName("max_input_vars");
|
||||
entity.Property(e => e.MemoryLimit)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("memory_limit");
|
||||
entity.Property(e => e.PhpVersion)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("php_version");
|
||||
entity.Property(e => e.PostMaxSize)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("post_max_size");
|
||||
entity.Property(e => e.SodiumMissing).HasColumnName("sodium_missing");
|
||||
entity.Property(e => e.Timezone)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("timezone");
|
||||
entity.Property(e => e.UploadMaxSize)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("upload_max_size");
|
||||
|
||||
entity.HasOne(d => d.Customer).WithMany(p => p.PvmsInfos)
|
||||
.HasForeignKey(d => d.CustomerId)
|
||||
.HasConstraintName("FK_4BCCAB779395C3F3");
|
||||
});
|
||||
|
||||
modelBuilder.Entity<Release>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Id).HasName("PK__releases__3213E83F59E90B83");
|
||||
|
||||
entity.ToTable("releases");
|
||||
|
||||
entity.HasIndex(e => e.ServiceId, "IDX_7896E4D1ED5CA9E6");
|
||||
|
||||
entity.Property(e => e.Id).HasColumnName("id");
|
||||
entity.Property(e => e.Changelog)
|
||||
.IsUnicode(false)
|
||||
.HasColumnName("changelog");
|
||||
entity.Property(e => e.ReleaseDate)
|
||||
.HasPrecision(6)
|
||||
.HasColumnName("release_date");
|
||||
entity.Property(e => e.ServiceId).HasColumnName("service_id");
|
||||
entity.Property(e => e.Version)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("version");
|
||||
|
||||
entity.HasOne(d => d.Service).WithMany(p => p.Releases)
|
||||
.HasForeignKey(d => d.ServiceId)
|
||||
.HasConstraintName("FK_7896E4D1ED5CA9E6");
|
||||
});
|
||||
|
||||
modelBuilder.Entity<SalvataggiSoap>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Id).HasName("PK__salvatag__3213E83F51C2D8BF");
|
||||
|
||||
entity.ToTable("salvataggi_soap");
|
||||
|
||||
entity.HasIndex(e => e.ApplicationInfoId, "IDX_BC9B16D5B635C4CB");
|
||||
|
||||
entity.Property(e => e.Id).HasColumnName("id");
|
||||
entity.Property(e => e.ApplicationInfoId).HasColumnName("application_info_id");
|
||||
entity.Property(e => e.Name)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("name");
|
||||
|
||||
entity.HasOne(d => d.ApplicationInfo).WithMany(p => p.SalvataggiSoaps)
|
||||
.HasForeignKey(d => d.ApplicationInfoId)
|
||||
.HasConstraintName("FK_BC9B16D5B635C4CB");
|
||||
});
|
||||
|
||||
modelBuilder.Entity<Server>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Id).HasName("PK__servers__3213E83F0E4B2C74");
|
||||
|
||||
entity.ToTable("servers");
|
||||
|
||||
entity.HasIndex(e => e.CustomerId, "IDX_4F8AF5F79395C3F3");
|
||||
|
||||
entity.Property(e => e.Id).HasColumnName("id");
|
||||
entity.Property(e => e.CreatedAt)
|
||||
.HasPrecision(6)
|
||||
.HasColumnName("created_at");
|
||||
entity.Property(e => e.CustomerId).HasColumnName("customer_id");
|
||||
entity.Property(e => e.Info)
|
||||
.IsUnicode(false)
|
||||
.HasComment("(DC2Type:simple_array)")
|
||||
.HasColumnName("info");
|
||||
entity.Property(e => e.Ip)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("ip");
|
||||
entity.Property(e => e.JavaVersion)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("java_version");
|
||||
entity.Property(e => e.LastUpdate)
|
||||
.HasPrecision(6)
|
||||
.HasColumnName("last_update");
|
||||
entity.Property(e => e.MaxPermSize)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("max_perm_size");
|
||||
entity.Property(e => e.OsArch)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("os_arch");
|
||||
entity.Property(e => e.OsName)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("os_name");
|
||||
entity.Property(e => e.Port).HasColumnName("port");
|
||||
entity.Property(e => e.RemoteAddr)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("remote_addr");
|
||||
entity.Property(e => e.UpdatedAt)
|
||||
.HasPrecision(6)
|
||||
.HasColumnName("updated_at");
|
||||
entity.Property(e => e.Xms)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("xms");
|
||||
entity.Property(e => e.Xmx)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("xmx");
|
||||
|
||||
entity.HasOne(d => d.Customer).WithMany(p => p.Servers)
|
||||
.HasForeignKey(d => d.CustomerId)
|
||||
.HasConstraintName("FK_4F8AF5F79395C3F3");
|
||||
});
|
||||
|
||||
modelBuilder.Entity<Service>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Id).HasName("PK__services__3213E83FB43C1FE2");
|
||||
|
||||
entity.ToTable("services");
|
||||
|
||||
entity.HasIndex(e => e.Slug, "UNIQ_7332E169989D9B62")
|
||||
.IsUnique()
|
||||
.HasFilter("([slug] IS NOT NULL)");
|
||||
|
||||
entity.Property(e => e.Id).HasColumnName("id");
|
||||
entity.Property(e => e.Description)
|
||||
.IsUnicode(false)
|
||||
.HasColumnName("description");
|
||||
entity.Property(e => e.InsertDate)
|
||||
.HasPrecision(6)
|
||||
.HasColumnName("insert_date");
|
||||
entity.Property(e => e.Language)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("language");
|
||||
entity.Property(e => e.Name)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("name");
|
||||
entity.Property(e => e.Slug)
|
||||
.HasMaxLength(191)
|
||||
.HasColumnName("slug");
|
||||
});
|
||||
|
||||
modelBuilder.Entity<VwServerLastUpdate>(entity =>
|
||||
{
|
||||
entity
|
||||
.HasNoKey()
|
||||
.ToView("vw_server_last_update");
|
||||
|
||||
entity.Property(e => e.CreatedAt)
|
||||
.HasPrecision(6)
|
||||
.HasColumnName("created_at");
|
||||
entity.Property(e => e.CustomerId).HasColumnName("customer_id");
|
||||
entity.Property(e => e.Id).HasColumnName("id");
|
||||
entity.Property(e => e.Info)
|
||||
.IsUnicode(false)
|
||||
.HasColumnName("info");
|
||||
entity.Property(e => e.Ip)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("ip");
|
||||
entity.Property(e => e.JavaVersion)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("java_version");
|
||||
entity.Property(e => e.LastUpdate)
|
||||
.HasPrecision(6)
|
||||
.HasColumnName("last_update");
|
||||
entity.Property(e => e.MaxPermSize)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("max_perm_size");
|
||||
entity.Property(e => e.OsArch)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("os_arch");
|
||||
entity.Property(e => e.OsName)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("os_name");
|
||||
entity.Property(e => e.Port).HasColumnName("port");
|
||||
entity.Property(e => e.RemoteAddr)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("remote_addr");
|
||||
entity.Property(e => e.UpdatedAt)
|
||||
.HasPrecision(6)
|
||||
.HasColumnName("updated_at");
|
||||
entity.Property(e => e.Xms)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("xms");
|
||||
entity.Property(e => e.Xmx)
|
||||
.HasMaxLength(255)
|
||||
.HasColumnName("xmx");
|
||||
});
|
||||
|
||||
OnModelCreatingPartial(modelBuilder);
|
||||
}
|
||||
|
||||
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
|
||||
}
|
||||
303
IntegryControlPanel/IntegryControlPanel/Data/Migrations/20250923102919_AddLdapUserProperties.Designer.cs
generated
Normal file
303
IntegryControlPanel/IntegryControlPanel/Data/Migrations/20250923102919_AddLdapUserProperties.Designer.cs
generated
Normal 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("20250923102919_AddLdapUserProperties")]
|
||||
partial class AddLdapUserProperties
|
||||
{
|
||||
/// <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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace IntegryControlPanel.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddLdapUserProperties : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Department",
|
||||
table: "AspNetUsers",
|
||||
type: "nvarchar(max)",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "DisplayName",
|
||||
table: "AspNetUsers",
|
||||
type: "nvarchar(max)",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "FirstName",
|
||||
table: "AspNetUsers",
|
||||
type: "nvarchar(max)",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "IsLdapUser",
|
||||
table: "AspNetUsers",
|
||||
type: "bit",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.AddColumn<DateTime>(
|
||||
name: "LastLdapSync",
|
||||
table: "AspNetUsers",
|
||||
type: "datetime2",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "LastName",
|
||||
table: "AspNetUsers",
|
||||
type: "nvarchar(max)",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "LdapUsername",
|
||||
table: "AspNetUsers",
|
||||
type: "nvarchar(max)",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Title",
|
||||
table: "AspNetUsers",
|
||||
type: "nvarchar(max)",
|
||||
nullable: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Department",
|
||||
table: "AspNetUsers");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "DisplayName",
|
||||
table: "AspNetUsers");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "FirstName",
|
||||
table: "AspNetUsers");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "IsLdapUser",
|
||||
table: "AspNetUsers");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "LastLdapSync",
|
||||
table: "AspNetUsers");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "LastName",
|
||||
table: "AspNetUsers");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "LdapUsername",
|
||||
table: "AspNetUsers");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Title",
|
||||
table: "AspNetUsers");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
// <auto-generated />
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using IntegryControlPanel.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
@@ -17,7 +17,7 @@ namespace IntegryControlPanel.Migrations
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "8.0.0")
|
||||
.HasAnnotation("ProductVersion", "9.0.9")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
||||
|
||||
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
||||
@@ -34,6 +34,12 @@ namespace IntegryControlPanel.Migrations
|
||||
.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)");
|
||||
@@ -41,6 +47,21 @@ namespace IntegryControlPanel.Migrations
|
||||
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");
|
||||
|
||||
@@ -67,6 +88,9 @@ namespace IntegryControlPanel.Migrations
|
||||
b.Property<string>("SecurityStamp")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<bool>("TwoFactorEnabled")
|
||||
.HasColumnType("bit");
|
||||
|
||||
|
||||
@@ -9,6 +9,11 @@
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.9">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.DirectoryServices.Protocols" Version="9.0.9" />
|
||||
<ProjectReference Include="..\IntegryControlPanel.Client\IntegryControlPanel.Client.csproj" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="9.*" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="9.*" />
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace IntegryControlPanel.Models.IntegryControlPanel;
|
||||
|
||||
public partial class ApplicationInfo
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public int? CustomerId { get; set; }
|
||||
|
||||
public string Name { get; set; } = null!;
|
||||
|
||||
public bool NewUpdProgMaga { get; set; }
|
||||
|
||||
public string? MenuPersonalizzato { get; set; }
|
||||
|
||||
public int? AnnoMagaz { get; set; }
|
||||
|
||||
public int? AnnoContab { get; set; }
|
||||
|
||||
public bool? AnsiPadding { get; set; }
|
||||
|
||||
public bool? DelimitedIdentifier { get; set; }
|
||||
|
||||
public bool? ConcatNullYieldsNull { get; set; }
|
||||
|
||||
public virtual Customer? Customer { get; set; }
|
||||
|
||||
public virtual ICollection<SalvataggiSoap> SalvataggiSoaps { get; set; } = new List<SalvataggiSoap>();
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace IntegryControlPanel.Models.IntegryControlPanel;
|
||||
|
||||
public partial class Client
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public string NomeAzienda { get; set; } = null!;
|
||||
|
||||
public string DeviceId { get; set; } = null!;
|
||||
|
||||
public DateTime? LastUpdate { get; set; }
|
||||
|
||||
public DateTime InsertDate { get; set; }
|
||||
|
||||
public string? RemoteAddr { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace IntegryControlPanel.Models.IntegryControlPanel;
|
||||
|
||||
public partial class Configurazioni
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public string NomeAzienda { get; set; } = null!;
|
||||
|
||||
public string? JavaVersion { get; set; }
|
||||
|
||||
public string? OsArch { get; set; }
|
||||
|
||||
public string? OsName { get; set; }
|
||||
|
||||
public string? Xmx { get; set; }
|
||||
|
||||
public string? Xms { get; set; }
|
||||
|
||||
public string? MaxPermSize { get; set; }
|
||||
|
||||
public DateTime? LastUpdate { get; set; }
|
||||
|
||||
public string? RemoteAddr { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace IntegryControlPanel.Models.IntegryControlPanel;
|
||||
|
||||
public partial class Customer
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public string Name { get; set; } = null!;
|
||||
|
||||
public string Slug { get; set; } = null!;
|
||||
|
||||
public bool? Active { get; set; }
|
||||
|
||||
public string? PartitaIva { get; set; }
|
||||
|
||||
public virtual ICollection<ApplicationInfo> ApplicationInfos { get; set; } = new List<ApplicationInfo>();
|
||||
|
||||
public virtual DatabaseEngine? DatabaseEngine { get; set; }
|
||||
|
||||
public virtual ICollection<Device> Devices { get; set; } = new List<Device>();
|
||||
|
||||
public virtual ICollection<PvmsInfo> PvmsInfos { get; set; } = new List<PvmsInfo>();
|
||||
|
||||
public virtual ICollection<Server> Servers { get; set; } = new List<Server>();
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace IntegryControlPanel.Models.IntegryControlPanel;
|
||||
|
||||
public partial class DatabaseEngine
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public int? CustomerId { get; set; }
|
||||
|
||||
public string ProductVersion { get; set; } = null!;
|
||||
|
||||
public string ProductVersionName { get; set; } = null!;
|
||||
|
||||
public string ProductLevel { get; set; } = null!;
|
||||
|
||||
public string ProductEdition { get; set; } = null!;
|
||||
|
||||
public virtual Customer? Customer { get; set; }
|
||||
|
||||
public virtual ICollection<DatabasesInfo> DatabasesInfos { get; set; } = new List<DatabasesInfo>();
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace IntegryControlPanel.Models.IntegryControlPanel;
|
||||
|
||||
public partial class DatabasesInfo
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public int? DatabaseEngineId { get; set; }
|
||||
|
||||
public string Name { get; set; } = null!;
|
||||
|
||||
public string LogicalName { get; set; } = null!;
|
||||
|
||||
public int SizeMb { get; set; }
|
||||
|
||||
public int MaxSizeMb { get; set; }
|
||||
|
||||
public virtual DatabaseEngine? DatabaseEngine { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace IntegryControlPanel.Models.IntegryControlPanel;
|
||||
|
||||
public partial class Device
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public int? CustomerId { get; set; }
|
||||
|
||||
public string Ip { get; set; } = null!;
|
||||
|
||||
public int Port { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// (DC2Type:simple_array)
|
||||
/// </summary>
|
||||
public string Info { get; set; } = null!;
|
||||
|
||||
public virtual Customer? Customer { get; set; }
|
||||
|
||||
public virtual ICollection<Installation> Installations { get; set; } = new List<Installation>();
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace IntegryControlPanel.Models.IntegryControlPanel;
|
||||
|
||||
public partial class Installation
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public int? ReleaseId { get; set; }
|
||||
|
||||
public int? ServerId { get; set; }
|
||||
|
||||
public int? DeviceId { get; set; }
|
||||
|
||||
public string? Notes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// (DC2Type:simple_array)
|
||||
/// </summary>
|
||||
public string Options { get; set; } = null!;
|
||||
|
||||
public DateTime InstallDate { get; set; }
|
||||
|
||||
public DateTime LastUpdate { get; set; }
|
||||
|
||||
public virtual Device? Device { get; set; }
|
||||
|
||||
public virtual Release? Release { get; set; }
|
||||
|
||||
public virtual Server? Server { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace IntegryControlPanel.Models.IntegryControlPanel;
|
||||
|
||||
public partial class PvmsInfo
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public int? CustomerId { get; set; }
|
||||
|
||||
public string PhpVersion { get; set; } = null!;
|
||||
|
||||
public string Timezone { get; set; } = null!;
|
||||
|
||||
public string Imagick { get; set; } = null!;
|
||||
|
||||
public bool SodiumMissing { get; set; }
|
||||
|
||||
public int MaxExecutionTime { get; set; }
|
||||
|
||||
public bool MagicQuotesGpc { get; set; }
|
||||
|
||||
public string DefaultCharset { get; set; } = null!;
|
||||
|
||||
public string MemoryLimit { get; set; } = null!;
|
||||
|
||||
public string PostMaxSize { get; set; } = null!;
|
||||
|
||||
public string UploadMaxSize { get; set; } = null!;
|
||||
|
||||
public int MaxInputVars { get; set; }
|
||||
|
||||
public virtual Customer? Customer { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace IntegryControlPanel.Models.IntegryControlPanel;
|
||||
|
||||
public partial class Release
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public int? ServiceId { get; set; }
|
||||
|
||||
public string Version { get; set; } = null!;
|
||||
|
||||
public string? Changelog { get; set; }
|
||||
|
||||
public DateTime ReleaseDate { get; set; }
|
||||
|
||||
public virtual ICollection<Installation> Installations { get; set; } = new List<Installation>();
|
||||
|
||||
public virtual Service? Service { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace IntegryControlPanel.Models.IntegryControlPanel;
|
||||
|
||||
public partial class SalvataggiSoap
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public int? ApplicationInfoId { get; set; }
|
||||
|
||||
public string Name { get; set; } = null!;
|
||||
|
||||
public virtual ApplicationInfo? ApplicationInfo { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace IntegryControlPanel.Models.IntegryControlPanel;
|
||||
|
||||
public partial class Server
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public int? CustomerId { get; set; }
|
||||
|
||||
public string? Ip { get; set; }
|
||||
|
||||
public int? Port { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// (DC2Type:simple_array)
|
||||
/// </summary>
|
||||
public string? Info { get; set; }
|
||||
|
||||
public string? JavaVersion { get; set; }
|
||||
|
||||
public string? OsArch { get; set; }
|
||||
|
||||
public string? OsName { get; set; }
|
||||
|
||||
public string? Xmx { get; set; }
|
||||
|
||||
public string? Xms { get; set; }
|
||||
|
||||
public string? MaxPermSize { get; set; }
|
||||
|
||||
public DateTime? LastUpdate { get; set; }
|
||||
|
||||
public string? RemoteAddr { get; set; }
|
||||
|
||||
public DateTime? CreatedAt { get; set; }
|
||||
|
||||
public DateTime? UpdatedAt { get; set; }
|
||||
|
||||
public virtual Customer? Customer { get; set; }
|
||||
|
||||
public virtual ICollection<Installation> Installations { get; set; } = new List<Installation>();
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace IntegryControlPanel.Models.IntegryControlPanel;
|
||||
|
||||
public partial class Service
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public string Name { get; set; } = null!;
|
||||
|
||||
public string Slug { get; set; } = null!;
|
||||
|
||||
public string? Language { get; set; }
|
||||
|
||||
public string? Description { get; set; }
|
||||
|
||||
public DateTime InsertDate { get; set; }
|
||||
|
||||
public virtual ICollection<Release> Releases { get; set; } = new List<Release>();
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace IntegryControlPanel.Models.IntegryControlPanel;
|
||||
|
||||
public partial class VwServerLastUpdate
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public int? CustomerId { get; set; }
|
||||
|
||||
public string? Ip { get; set; }
|
||||
|
||||
public int? Port { get; set; }
|
||||
|
||||
public string? Info { get; set; }
|
||||
|
||||
public string? JavaVersion { get; set; }
|
||||
|
||||
public string? OsArch { get; set; }
|
||||
|
||||
public string? OsName { get; set; }
|
||||
|
||||
public string? Xmx { get; set; }
|
||||
|
||||
public string? Xms { get; set; }
|
||||
|
||||
public string? MaxPermSize { get; set; }
|
||||
|
||||
public DateTime? LastUpdate { get; set; }
|
||||
|
||||
public string? RemoteAddr { get; set; }
|
||||
|
||||
public DateTime? CreatedAt { get; set; }
|
||||
|
||||
public DateTime? UpdatedAt { get; set; }
|
||||
}
|
||||
15
IntegryControlPanel/IntegryControlPanel/Models/LdapUser.cs
Normal file
15
IntegryControlPanel/IntegryControlPanel/Models/LdapUser.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
namespace IntegryControlPanel.Models
|
||||
{
|
||||
public class LdapUser
|
||||
{
|
||||
public string Username { get; set; } = string.Empty;
|
||||
public string Email { get; set; } = string.Empty;
|
||||
public string FirstName { get; set; } = string.Empty;
|
||||
public string LastName { get; set; } = string.Empty;
|
||||
public string DisplayName { get; set; } = string.Empty;
|
||||
public List<string> Groups { get; set; } = new();
|
||||
public string? Department { get; set; }
|
||||
public string? Title { get; set; }
|
||||
public string? PhoneNumber { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ using IntegryControlPanel.Client.Pages;
|
||||
using IntegryControlPanel.Components;
|
||||
using IntegryControlPanel.Components.Account;
|
||||
using IntegryControlPanel.Data;
|
||||
using IntegryControlPanel.Services;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using MudBlazor.Services;
|
||||
@@ -16,6 +17,9 @@ builder.Services.AddRazorComponents()
|
||||
.AddInteractiveWebAssemblyComponents()
|
||||
.AddAuthenticationStateSerialization();
|
||||
|
||||
// Add controllers
|
||||
builder.Services.AddControllers();
|
||||
|
||||
builder.Services.AddCascadingAuthenticationState();
|
||||
builder.Services.AddScoped<IdentityUserAccessor>();
|
||||
builder.Services.AddScoped<IdentityRedirectManager>();
|
||||
@@ -35,9 +39,13 @@ builder.Services.AddDatabaseDeveloperPageExceptionFilter();
|
||||
|
||||
builder.Services.AddIdentityCore<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
|
||||
.AddEntityFrameworkStores<ApplicationDbContext>()
|
||||
.AddSignInManager()
|
||||
.AddSignInManager<LdapSignInManager>()
|
||||
.AddDefaultTokenProviders();
|
||||
|
||||
// Registra i servizi LDAP
|
||||
builder.Services.AddScoped<ILdapService, LdapService>();
|
||||
builder.Services.AddScoped<LdapUserManager>();
|
||||
|
||||
builder.Services.AddSingleton<IEmailSender<ApplicationUser>, IdentityNoOpEmailSender>();
|
||||
|
||||
var app = builder.Build();
|
||||
@@ -57,7 +65,6 @@ else
|
||||
|
||||
app.UseHttpsRedirection();
|
||||
|
||||
|
||||
app.UseAntiforgery();
|
||||
|
||||
app.MapStaticAssets();
|
||||
@@ -65,6 +72,9 @@ app.MapRazorComponents<App>()
|
||||
.AddInteractiveWebAssemblyRenderMode()
|
||||
.AddAdditionalAssemblies(typeof(IntegryControlPanel.Client._Imports).Assembly);
|
||||
|
||||
// Map controllers
|
||||
app.MapControllers();
|
||||
|
||||
// Add additional endpoints required by the Identity /Account Razor components.
|
||||
app.MapAdditionalIdentityEndpoints();
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
using IntegryControlPanel.Models;
|
||||
|
||||
namespace IntegryControlPanel.Services
|
||||
{
|
||||
public interface ILdapService
|
||||
{
|
||||
Task<LdapUser?> AuthenticateAsync(string username, string password);
|
||||
Task<LdapUser?> GetUserAsync(string username);
|
||||
Task<IEnumerable<LdapUser>> GetUsersInGroupAsync(string groupName);
|
||||
}
|
||||
}
|
||||
193
IntegryControlPanel/IntegryControlPanel/Services/LdapService.cs
Normal file
193
IntegryControlPanel/IntegryControlPanel/Services/LdapService.cs
Normal file
@@ -0,0 +1,193 @@
|
||||
using IntegryControlPanel.Models;
|
||||
using IntegryControlPanel.Services;
|
||||
using System.DirectoryServices.Protocols;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
|
||||
namespace IntegryControlPanel.Services
|
||||
{
|
||||
public class LdapService : ILdapService
|
||||
{
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly ILogger<LdapService> _logger;
|
||||
|
||||
private string LdapServer => _configuration["LDAP:Server"] ?? throw new InvalidOperationException("LDAP Server not configured");
|
||||
private int LdapPort => int.Parse(_configuration["LDAP:Port"] ?? "389");
|
||||
private string BaseDn => _configuration["LDAP:BaseDN"] ?? throw new InvalidOperationException("LDAP BaseDN not configured");
|
||||
private string ServiceAccountDn => _configuration["LDAP:ServiceAccountDN"] ?? throw new InvalidOperationException("LDAP ServiceAccountDN not configured");
|
||||
private string ServiceAccountPassword => _configuration["LDAP:ServiceAccountPassword"] ?? throw new InvalidOperationException("LDAP ServiceAccountPassword not configured");
|
||||
private bool UseSSL => bool.Parse(_configuration["LDAP:UseSSL"] ?? "false");
|
||||
|
||||
public LdapService(IConfiguration configuration, ILogger<LdapService> logger)
|
||||
{
|
||||
_configuration = configuration;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task<LdapUser?> AuthenticateAsync(string username, string password)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(username) || string.IsNullOrWhiteSpace(password))
|
||||
return null;
|
||||
|
||||
try
|
||||
{
|
||||
using var connection = new LdapConnection(new LdapDirectoryIdentifier(LdapServer, LdapPort));
|
||||
|
||||
if (UseSSL)
|
||||
{
|
||||
connection.SessionOptions.SecureSocketLayer = true;
|
||||
}
|
||||
|
||||
// Prova prima a fare bind con le credenziali utente per autenticare
|
||||
string userDn = $"cn={username},{BaseDn}";
|
||||
connection.Credential = new NetworkCredential(userDn, password);
|
||||
connection.AuthType = AuthType.Basic;
|
||||
|
||||
await Task.Run(() => connection.Bind());
|
||||
|
||||
// Se l'autenticazione ha successo, ottieni le informazioni dell'utente
|
||||
var user = await GetUserInfoAsync(connection, username);
|
||||
|
||||
return user;
|
||||
}
|
||||
catch (LdapException ex)
|
||||
{
|
||||
_logger.LogWarning("LDAP authentication failed for user {Username}: {Message}", username, ex.Message);
|
||||
return null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error during LDAP authentication for user {Username}", username);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<LdapUser?> GetUserAsync(string username)
|
||||
{
|
||||
try
|
||||
{
|
||||
using var connection = await CreateServiceConnectionAsync();
|
||||
return await GetUserInfoAsync(connection, username);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error getting user {Username} from LDAP", username);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<LdapUser>> GetUsersInGroupAsync(string groupName)
|
||||
{
|
||||
try
|
||||
{
|
||||
using var connection = await CreateServiceConnectionAsync();
|
||||
|
||||
var searchFilter = $"(&(objectClass=person)(memberOf=cn={groupName},{BaseDn}))";
|
||||
var searchRequest = new SearchRequest(BaseDn, searchFilter, SearchScope.Subtree);
|
||||
searchRequest.Attributes.AddRange(new[] { "cn", "mail", "givenName", "sn", "displayName", "memberOf", "department", "title", "telephoneNumber" });
|
||||
|
||||
var response = (SearchResponse)await Task.Run(() => connection.SendRequest(searchRequest));
|
||||
var users = new List<LdapUser>();
|
||||
|
||||
foreach (SearchResultEntry entry in response.Entries)
|
||||
{
|
||||
var user = MapLdapEntryToUser(entry);
|
||||
if (user != null)
|
||||
users.Add(user);
|
||||
}
|
||||
|
||||
return users;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error getting users in group {GroupName} from LDAP", groupName);
|
||||
return Enumerable.Empty<LdapUser>();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<LdapConnection> CreateServiceConnectionAsync()
|
||||
{
|
||||
var connection = new LdapConnection(new LdapDirectoryIdentifier(LdapServer, LdapPort));
|
||||
|
||||
if (UseSSL)
|
||||
{
|
||||
connection.SessionOptions.SecureSocketLayer = true;
|
||||
}
|
||||
|
||||
connection.Credential = new NetworkCredential(ServiceAccountDn, ServiceAccountPassword);
|
||||
connection.AuthType = AuthType.Basic;
|
||||
|
||||
await Task.Run(() => connection.Bind());
|
||||
|
||||
return connection;
|
||||
}
|
||||
|
||||
private async Task<LdapUser?> GetUserInfoAsync(LdapConnection connection, string username)
|
||||
{
|
||||
var searchFilter = $"(&(objectClass=person)(cn={username}))";
|
||||
var searchRequest = new SearchRequest(BaseDn, searchFilter, SearchScope.Subtree);
|
||||
searchRequest.Attributes.AddRange(new[] { "cn", "mail", "givenName", "sn", "displayName", "memberOf", "department", "title", "telephoneNumber" });
|
||||
|
||||
var response = (SearchResponse)await Task.Run(() => connection.SendRequest(searchRequest));
|
||||
|
||||
if (response.Entries.Count == 0)
|
||||
return null;
|
||||
|
||||
return MapLdapEntryToUser(response.Entries[0]);
|
||||
}
|
||||
|
||||
private LdapUser? MapLdapEntryToUser(SearchResultEntry entry)
|
||||
{
|
||||
try
|
||||
{
|
||||
var user = new LdapUser
|
||||
{
|
||||
Username = GetAttributeValue(entry, "cn") ?? string.Empty,
|
||||
Email = GetAttributeValue(entry, "mail") ?? string.Empty,
|
||||
FirstName = GetAttributeValue(entry, "givenName") ?? string.Empty,
|
||||
LastName = GetAttributeValue(entry, "sn") ?? string.Empty,
|
||||
DisplayName = GetAttributeValue(entry, "displayName") ?? string.Empty,
|
||||
Department = GetAttributeValue(entry, "department"),
|
||||
Title = GetAttributeValue(entry, "title"),
|
||||
PhoneNumber = GetAttributeValue(entry, "telephoneNumber")
|
||||
};
|
||||
|
||||
// Estrai i gruppi
|
||||
if (entry.Attributes.Contains("memberOf"))
|
||||
{
|
||||
foreach (var group in entry.Attributes["memberOf"].GetValues(typeof(string)).Cast<string>())
|
||||
{
|
||||
// Estrai solo il nome del gruppo dal DN
|
||||
var groupName = ExtractGroupNameFromDn(group);
|
||||
if (!string.IsNullOrEmpty(groupName))
|
||||
user.Groups.Add(groupName);
|
||||
}
|
||||
}
|
||||
|
||||
return user;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error mapping LDAP entry to user");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private string? GetAttributeValue(SearchResultEntry entry, string attributeName)
|
||||
{
|
||||
if (!entry.Attributes.Contains(attributeName))
|
||||
return null;
|
||||
|
||||
var values = entry.Attributes[attributeName].GetValues(typeof(string));
|
||||
return values.Length > 0 ? values[0] as string : null;
|
||||
}
|
||||
|
||||
private string ExtractGroupNameFromDn(string groupDn)
|
||||
{
|
||||
// Estrai il nome del gruppo da un DN come "cn=GroupName,ou=Groups,dc=domain,dc=com"
|
||||
var parts = groupDn.Split(',');
|
||||
var cnPart = parts.FirstOrDefault(p => p.Trim().StartsWith("cn=", StringComparison.OrdinalIgnoreCase));
|
||||
return cnPart?.Substring(3) ?? string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
using IntegryControlPanel.Data;
|
||||
using IntegryControlPanel.Services;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace IntegryControlPanel.Services
|
||||
{
|
||||
public class LdapSignInManager : SignInManager<ApplicationUser>
|
||||
{
|
||||
private readonly LdapUserManager _ldapUserManager;
|
||||
private readonly ILogger<LdapSignInManager> _logger;
|
||||
|
||||
public LdapSignInManager(
|
||||
UserManager<ApplicationUser> userManager,
|
||||
IHttpContextAccessor contextAccessor,
|
||||
IUserClaimsPrincipalFactory<ApplicationUser> claimsFactory,
|
||||
IOptions<IdentityOptions> optionsAccessor,
|
||||
ILogger<SignInManager<ApplicationUser>> logger,
|
||||
IAuthenticationSchemeProvider schemes,
|
||||
IUserConfirmation<ApplicationUser> confirmation,
|
||||
LdapUserManager ldapUserManager,
|
||||
ILogger<LdapSignInManager> ldapLogger)
|
||||
: base(userManager, contextAccessor, claimsFactory, optionsAccessor, logger, schemes, confirmation)
|
||||
{
|
||||
_ldapUserManager = ldapUserManager;
|
||||
_logger = ldapLogger;
|
||||
}
|
||||
|
||||
public override async Task<SignInResult> PasswordSignInAsync(string userName, string password, bool isPersistent, bool lockoutOnFailure)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Prima tenta l'autenticazione LDAP
|
||||
var ldapUser = await _ldapUserManager.AuthenticateAsync(userName, password);
|
||||
|
||||
if (ldapUser != null)
|
||||
{
|
||||
_logger.LogInformation("LDAP authentication successful for user {Username}", userName);
|
||||
|
||||
// Accedi all'utente
|
||||
await SignInAsync(ldapUser, isPersistent);
|
||||
return SignInResult.Success;
|
||||
}
|
||||
|
||||
_logger.LogWarning("LDAP authentication failed for user {Username}, trying local authentication", userName);
|
||||
|
||||
// Se l'autenticazione LDAP fallisce, prova con l'autenticazione locale
|
||||
return await base.PasswordSignInAsync(userName, password, isPersistent, lockoutOnFailure);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error during sign in for user {Username}", userName);
|
||||
return SignInResult.Failed;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<SignInResult> LdapSignInAsync(string userName, string password, bool isPersistent)
|
||||
{
|
||||
try
|
||||
{
|
||||
var ldapUser = await _ldapUserManager.AuthenticateAsync(userName, password);
|
||||
|
||||
if (ldapUser == null)
|
||||
{
|
||||
_logger.LogWarning("LDAP authentication failed for user {Username}", userName);
|
||||
return SignInResult.Failed;
|
||||
}
|
||||
|
||||
await SignInAsync(ldapUser, isPersistent);
|
||||
_logger.LogInformation("LDAP sign in successful for user {Username}", userName);
|
||||
return SignInResult.Success;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error during LDAP sign in for user {Username}", userName);
|
||||
return SignInResult.Failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,228 @@
|
||||
using IntegryControlPanel.Data;
|
||||
using IntegryControlPanel.Services;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace IntegryControlPanel.Services
|
||||
{
|
||||
public class LdapUserManager : IDisposable
|
||||
{
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
private readonly ILdapService _ldapService;
|
||||
private readonly ILogger<LdapUserManager> _logger;
|
||||
|
||||
public LdapUserManager(
|
||||
UserManager<ApplicationUser> userManager,
|
||||
ILdapService ldapService,
|
||||
ILogger<LdapUserManager> logger)
|
||||
{
|
||||
_userManager = userManager;
|
||||
_ldapService = ldapService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task<ApplicationUser?> AuthenticateAsync(string username, string password)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Prima tenta l'autenticazione LDAP
|
||||
var ldapUser = await _ldapService.AuthenticateAsync(username, password);
|
||||
if (ldapUser == null)
|
||||
{
|
||||
_logger.LogWarning("LDAP authentication failed for user {Username}", username);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Cerca l'utente esistente nel database locale
|
||||
var existingUser = await _userManager.Users
|
||||
.FirstOrDefaultAsync(u => u.LdapUsername == username || u.UserName == username);
|
||||
|
||||
if (existingUser != null)
|
||||
{
|
||||
// Aggiorna le informazioni dell'utente esistente
|
||||
await UpdateUserFromLdapAsync(existingUser, ldapUser);
|
||||
return existingUser;
|
||||
}
|
||||
|
||||
// Crea un nuovo utente se non esiste
|
||||
var newUser = await CreateUserFromLdapAsync(ldapUser);
|
||||
return newUser;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error during LDAP authentication for user {Username}", username);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<ApplicationUser?> SyncUserFromLdapAsync(string username)
|
||||
{
|
||||
try
|
||||
{
|
||||
var ldapUser = await _ldapService.GetUserAsync(username);
|
||||
if (ldapUser == null)
|
||||
return null;
|
||||
|
||||
var existingUser = await _userManager.Users
|
||||
.FirstOrDefaultAsync(u => u.LdapUsername == username || u.UserName == username);
|
||||
|
||||
if (existingUser != null)
|
||||
{
|
||||
await UpdateUserFromLdapAsync(existingUser, ldapUser);
|
||||
return existingUser;
|
||||
}
|
||||
|
||||
return await CreateUserFromLdapAsync(ldapUser);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error syncing user {Username} from LDAP", username);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<ApplicationUser> CreateUserFromLdapAsync(Models.LdapUser ldapUser)
|
||||
{
|
||||
var user = new ApplicationUser
|
||||
{
|
||||
UserName = ldapUser.Username,
|
||||
Email = ldapUser.Email,
|
||||
EmailConfirmed = true, // Gli utenti LDAP sono considerati verificati
|
||||
FirstName = ldapUser.FirstName,
|
||||
LastName = ldapUser.LastName,
|
||||
DisplayName = ldapUser.DisplayName,
|
||||
Department = ldapUser.Department,
|
||||
Title = ldapUser.Title,
|
||||
PhoneNumber = ldapUser.PhoneNumber,
|
||||
IsLdapUser = true,
|
||||
LdapUsername = ldapUser.Username,
|
||||
LastLdapSync = DateTime.UtcNow
|
||||
};
|
||||
|
||||
var result = await _userManager.CreateAsync(user);
|
||||
if (!result.Succeeded)
|
||||
{
|
||||
var errors = string.Join(", ", result.Errors.Select(e => e.Description));
|
||||
throw new InvalidOperationException($"Failed to create user: {errors}");
|
||||
}
|
||||
|
||||
// Aggiungi ruoli basati sui gruppi LDAP se necessario
|
||||
await AssignRolesFromLdapGroupsAsync(user, ldapUser.Groups);
|
||||
|
||||
_logger.LogInformation("Created new user {Username} from LDAP", ldapUser.Username);
|
||||
return user;
|
||||
}
|
||||
|
||||
private async Task UpdateUserFromLdapAsync(ApplicationUser user, Models.LdapUser ldapUser)
|
||||
{
|
||||
bool hasChanges = false;
|
||||
|
||||
if (user.Email != ldapUser.Email)
|
||||
{
|
||||
user.Email = ldapUser.Email;
|
||||
hasChanges = true;
|
||||
}
|
||||
|
||||
if (user.FirstName != ldapUser.FirstName)
|
||||
{
|
||||
user.FirstName = ldapUser.FirstName;
|
||||
hasChanges = true;
|
||||
}
|
||||
|
||||
if (user.LastName != ldapUser.LastName)
|
||||
{
|
||||
user.LastName = ldapUser.LastName;
|
||||
hasChanges = true;
|
||||
}
|
||||
|
||||
if (user.DisplayName != ldapUser.DisplayName)
|
||||
{
|
||||
user.DisplayName = ldapUser.DisplayName;
|
||||
hasChanges = true;
|
||||
}
|
||||
|
||||
if (user.Department != ldapUser.Department)
|
||||
{
|
||||
user.Department = ldapUser.Department;
|
||||
hasChanges = true;
|
||||
}
|
||||
|
||||
if (user.Title != ldapUser.Title)
|
||||
{
|
||||
user.Title = ldapUser.Title;
|
||||
hasChanges = true;
|
||||
}
|
||||
|
||||
if (user.PhoneNumber != ldapUser.PhoneNumber)
|
||||
{
|
||||
user.PhoneNumber = ldapUser.PhoneNumber;
|
||||
hasChanges = true;
|
||||
}
|
||||
|
||||
user.LastLdapSync = DateTime.UtcNow;
|
||||
user.IsLdapUser = true;
|
||||
user.LdapUsername = ldapUser.Username;
|
||||
|
||||
if (hasChanges)
|
||||
{
|
||||
var result = await _userManager.UpdateAsync(user);
|
||||
if (!result.Succeeded)
|
||||
{
|
||||
var errors = string.Join(", ", result.Errors.Select(e => e.Description));
|
||||
_logger.LogError("Failed to update user {Username}: {Errors}", user.UserName, errors);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogInformation("Updated user {Username} from LDAP", user.UserName);
|
||||
}
|
||||
}
|
||||
|
||||
// Aggiorna ruoli basati sui gruppi LDAP
|
||||
await AssignRolesFromLdapGroupsAsync(user, ldapUser.Groups);
|
||||
}
|
||||
|
||||
private async Task AssignRolesFromLdapGroupsAsync(ApplicationUser user, List<string> ldapGroups)
|
||||
{
|
||||
// Implementa la logica di mappatura tra gruppi LDAP e ruoli dell'applicazione
|
||||
// Esempio di mappatura:
|
||||
var roleMapping = new Dictionary<string, string>
|
||||
{
|
||||
{ "Administrators", "Admin" },
|
||||
{ "IT-Support", "ITSupport" },
|
||||
{ "Users", "User" }
|
||||
};
|
||||
|
||||
var currentRoles = await _userManager.GetRolesAsync(user);
|
||||
var newRoles = new List<string>();
|
||||
|
||||
foreach (var ldapGroup in ldapGroups)
|
||||
{
|
||||
if (roleMapping.ContainsKey(ldapGroup))
|
||||
{
|
||||
newRoles.Add(roleMapping[ldapGroup]);
|
||||
}
|
||||
}
|
||||
|
||||
// Rimuovi ruoli che non dovrebbero pi<70> essere assegnati
|
||||
var rolesToRemove = currentRoles.Except(newRoles).ToList();
|
||||
if (rolesToRemove.Any())
|
||||
{
|
||||
await _userManager.RemoveFromRolesAsync(user, rolesToRemove);
|
||||
_logger.LogInformation("Removed roles {Roles} from user {Username}", string.Join(", ", rolesToRemove), user.UserName);
|
||||
}
|
||||
|
||||
// Aggiungi nuovi ruoli
|
||||
var rolesToAdd = newRoles.Except(currentRoles).ToList();
|
||||
if (rolesToAdd.Any())
|
||||
{
|
||||
await _userManager.AddToRolesAsync(user, rolesToAdd);
|
||||
_logger.LogInformation("Added roles {Roles} to user {Username}", string.Join(", ", rolesToAdd), user.UserName);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
// Non disporre di _userManager poich<63> <20> gestito dal DI container
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,17 @@
|
||||
{
|
||||
"LDAP": {
|
||||
"Server": "192.168.2.208",
|
||||
"Port": "389",
|
||||
"BaseDN": "OU=Azure AD,DC=studio-ml,DC=local",
|
||||
"ServiceAccountDN": "CN=Administrator,CN=Users,DC=studio-ml,DC=local",
|
||||
"ServiceAccountPassword": "inpmiy",
|
||||
"UseSSL": "false"
|
||||
},
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
"Microsoft.AspNetCore": "Warning",
|
||||
"IntegryControlPanel.Services": "Debug"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,21 @@
|
||||
{
|
||||
"ConnectionStrings": {
|
||||
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-IntegryControlPanel-c1120793-85cd-450e-893b-978f0af6aeab;Trusted_Connection=True;MultipleActiveResultSets=true"
|
||||
"DefaultConnection": "Server=SERVERDB2019;Database=integry_control_panel_test;Trusted_Connection=True;MultipleActiveResultSets=true"
|
||||
|
||||
},
|
||||
"LDAP": {
|
||||
"Server": "your-domain-controller.domain.com",
|
||||
"Port": "389",
|
||||
"BaseDN": "DC=domain,DC=com",
|
||||
"ServiceAccountDN": "CN=ServiceAccount,CN=Users,DC=domain,DC=com",
|
||||
"ServiceAccountPassword": "your-service-account-password",
|
||||
"UseSSL": "false"
|
||||
},
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
"Microsoft.AspNetCore": "Warning",
|
||||
"IntegryControlPanel.Services": "Information"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
|
||||
Reference in New Issue
Block a user