refactor: relocate options classes to dedicated Options folders

Move configuration options from Core/DataAccess/DataSync/ExcelIO to
dedicated Options folders within each project for better organization.
Update all references and tests accordingly.
This commit is contained in:
Joseph Doherty
2026-01-03 08:55:08 -05:00
parent 3cb73eb09f
commit ec4c8fab87
52 changed files with 4628 additions and 202 deletions
@@ -1,6 +1,6 @@
using System.Text.Json.Serialization;
using JdeScoping.Api.Hubs;
using JdeScoping.Core.Options;
using JdeScoping.Api.Options;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
@@ -1,4 +1,4 @@
namespace JdeScoping.Core.Options;
namespace JdeScoping.Api.Options;
/// <summary>
/// Authentication configuration options
@@ -10,12 +10,6 @@ public class AuthOptions
/// </summary>
public const string SectionName = "Auth";
/// <summary>
/// Enable fake authentication for development.
/// When true, any credentials are accepted.
/// </summary>
public bool UseFakeAuth { get; set; } = false;
/// <summary>
/// Name of the authentication cookie.
/// </summary>
@@ -25,10 +19,4 @@ public class AuthOptions
/// Cookie expiration in minutes (default: 8 hours).
/// </summary>
public int CookieExpirationMinutes { get; set; } = 480;
/// <summary>
/// Optional list of usernames that bypass group check.
/// Use sparingly for admin/testing purposes.
/// </summary>
public string[] AdminBypassUsers { get; set; } = [];
}
@@ -1,32 +0,0 @@
namespace JdeScoping.Core.Options;
/// <summary>
/// Configuration options for data synchronization background jobs.
/// </summary>
public class DataSyncOptions
{
/// <summary>
/// Configuration section name in appsettings.json.
/// </summary>
public const string SectionName = "DataSync";
/// <summary>
/// Cron schedule for mass (full) data refresh. Empty string disables the schedule.
/// </summary>
public string MassRefreshCronSchedule { get; set; } = "0 0 6 * * SAT";
/// <summary>
/// Cron schedule for daily incremental data refresh. Empty string disables the schedule.
/// </summary>
public string DailyRefreshCronSchedule { get; set; } = "0 0 4 * * *";
/// <summary>
/// Cron schedule for hourly data refresh. Empty string disables the schedule.
/// </summary>
public string HourlyRefreshCronSchedule { get; set; } = "0 0 * * * *";
/// <summary>
/// Maximum number of concurrent update operations.
/// </summary>
public int MaxConcurrentUpdates { get; set; } = 4;
}
@@ -1,27 +0,0 @@
namespace JdeScoping.Core.Options;
/// <summary>
/// Configuration options for Excel export functionality.
/// </summary>
public class ExcelExportOptions
{
/// <summary>
/// Configuration section name in appsettings.json.
/// </summary>
public const string SectionName = "ExcelExport";
/// <summary>
/// Directory for temporary Excel files.
/// </summary>
public string TempDirectory { get; set; } = "/tmp/lotfinder";
/// <summary>
/// Maximum number of rows per Excel sheet.
/// </summary>
public int MaxRowsPerSheet { get; set; } = 1048576;
/// <summary>
/// Default date format for Excel cells.
/// </summary>
public string DefaultDateFormat { get; set; } = "yyyy-MM-dd HH:mm:ss";
}
@@ -1,8 +0,0 @@
namespace JdeScoping.Core.Options;
public class SearchOptions
{
public int MaxResultRows { get; set; } = 100000;
public int TimeoutSeconds { get; set; } = 300;
public int MaxConcurrentSearches { get; set; } = 5;
}
@@ -1,7 +1,6 @@
using JdeScoping.Core.Interfaces;
using JdeScoping.Core.Options;
using JdeScoping.DataAccess;
using JdeScoping.DataAccess.Configuration;
using JdeScoping.DataAccess.Options;
using JdeScoping.DataAccess.FilterHandlers;
using JdeScoping.DataAccess.Interfaces;
using JdeScoping.DataAccess.QueryBuilders;
@@ -1,4 +1,4 @@
namespace JdeScoping.DataAccess.Configuration;
namespace JdeScoping.DataAccess.Options;
/// <summary>
/// Configuration options for the data access layer.
@@ -0,0 +1,27 @@
namespace JdeScoping.DataAccess.Options;
/// <summary>
/// Configuration options for search operations.
/// </summary>
public class SearchOptions
{
/// <summary>
/// Configuration section name in appsettings.json.
/// </summary>
public const string SectionName = "Search";
/// <summary>
/// Maximum number of result rows to return.
/// </summary>
public int MaxResultRows { get; set; } = 100000;
/// <summary>
/// Search query timeout in seconds.
/// </summary>
public int TimeoutSeconds { get; set; } = 300;
/// <summary>
/// Maximum number of concurrent search operations.
/// </summary>
public int MaxConcurrentSearches { get; set; } = 5;
}
@@ -1,4 +1,4 @@
namespace JdeScoping.DataAccess.Configuration;
namespace JdeScoping.DataAccess.Options;
/// <summary>
/// Configuration options for search processing.
@@ -1,4 +1,4 @@
namespace JdeScoping.Core.Options;
namespace JdeScoping.DataAccess.Options;
/// <summary>
/// Configuration options for search processing background service.
@@ -2,7 +2,7 @@ using System.Runtime.CompilerServices;
using Dapper;
using JdeScoping.Core.Models;
using JdeScoping.Core.Models.Quality;
using JdeScoping.DataAccess.Configuration;
using JdeScoping.DataAccess.Options;
using JdeScoping.DataAccess.Interfaces;
using JdeScoping.DataAccess.Queries;
using Microsoft.Extensions.Logging;
@@ -1,6 +1,6 @@
using System.Runtime.CompilerServices;
using Dapper;
using JdeScoping.DataAccess.Configuration;
using JdeScoping.DataAccess.Options;
using JdeScoping.DataAccess.Interfaces;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
@@ -1,6 +1,6 @@
using System.Data;
using JdeScoping.Core.Interfaces;
using JdeScoping.DataAccess.Configuration;
using JdeScoping.DataAccess.Options;
using JdeScoping.DataAccess.Exceptions;
using JdeScoping.DataAccess.Interfaces;
using Microsoft.Data.SqlClient;
@@ -1,6 +1,6 @@
using System.Runtime.CompilerServices;
using Dapper;
using JdeScoping.DataAccess.Configuration;
using JdeScoping.DataAccess.Options;
using JdeScoping.DataAccess.Interfaces;
using JdeScoping.DataAccess.Models;
using JdeScoping.DataAccess.Models.Results;
@@ -1,4 +1,4 @@
using JdeScoping.DataSync.Configuration;
using JdeScoping.DataSync.Options;
using JdeScoping.DataSync.Contracts;
using JdeScoping.DataSync.Telemetry;
using Microsoft.Extensions.DependencyInjection;
@@ -4,7 +4,7 @@ using JdeScoping.Core.Models.Organization;
using JdeScoping.Core.Models.Quality;
using JdeScoping.Core.Models.WorkOrders;
using JdeScoping.DataSync;
using JdeScoping.DataSync.Configuration;
using JdeScoping.DataSync.Options;
using JdeScoping.DataSync.Configuration.MergeConfigurations;
using JdeScoping.DataSync.Contracts;
using JdeScoping.DataSync.Fetchers.Cms;
@@ -1,5 +1,5 @@
using JdeScoping.Core.Models.Enums;
using JdeScoping.DataSync.Configuration;
using JdeScoping.DataSync.Options;
namespace JdeScoping.DataSync.Models;
@@ -1,4 +1,4 @@
namespace JdeScoping.DataSync.Configuration;
namespace JdeScoping.DataSync.Options;
/// <summary>
/// Configuration for a single data source table sync.
@@ -1,6 +1,6 @@
using System.ComponentModel.DataAnnotations;
namespace JdeScoping.DataSync.Configuration;
namespace JdeScoping.DataSync.Options;
/// <summary>
/// Configuration options for the data synchronization service.
@@ -1,7 +1,7 @@
using JdeScoping.Core.Models;
using JdeScoping.Core.Models.Enums;
using JdeScoping.Core.Models.Infrastructure;
using JdeScoping.DataSync.Configuration;
using JdeScoping.DataSync.Options;
using JdeScoping.DataSync.Contracts;
using JdeScoping.DataSync.Models;
using Microsoft.Extensions.Logging;
@@ -1,4 +1,4 @@
using JdeScoping.DataSync.Configuration;
using JdeScoping.DataSync.Options;
using JdeScoping.DataSync.Contracts;
using JdeScoping.DataSync.Telemetry;
using Microsoft.Extensions.DependencyInjection;
@@ -4,7 +4,7 @@ using JdeScoping.Core.Models;
using JdeScoping.Core.Models.Enums;
using JdeScoping.Core.Interfaces;
using JdeScoping.DataAccess.Interfaces;
using JdeScoping.DataSync.Configuration;
using JdeScoping.DataSync.Options;
using JdeScoping.DataSync.Contracts;
using JdeScoping.DataSync.Models;
using JdeScoping.DataSync.Telemetry;
@@ -1,6 +1,6 @@
using JdeScoping.Core.Interfaces;
using JdeScoping.ExcelIO;
using JdeScoping.ExcelIO.Configuration;
using JdeScoping.ExcelIO.Options;
using JdeScoping.ExcelIO.Generators;
using JdeScoping.ExcelIO.Helpers;
using JdeScoping.ExcelIO.Parsing;
@@ -2,7 +2,7 @@ using System.Reflection;
using ClosedXML.Excel;
using JdeScoping.Core.Interfaces;
using JdeScoping.ExcelIO.Attributes;
using JdeScoping.ExcelIO.Configuration;
using JdeScoping.ExcelIO.Options;
using JdeScoping.ExcelIO.Formatting;
using JdeScoping.ExcelIO.Generators;
using JdeScoping.ExcelIO.Models.Reporting;
@@ -1,5 +1,5 @@
using ClosedXML.Excel;
using JdeScoping.ExcelIO.Configuration;
using JdeScoping.ExcelIO.Options;
using JdeScoping.ExcelIO.Formatting;
using JdeScoping.ExcelIO.Models.Reporting;
using Microsoft.Extensions.Options;
@@ -1,4 +1,4 @@
namespace JdeScoping.ExcelIO.Configuration;
namespace JdeScoping.ExcelIO.Options;
/// <summary>
/// Configuration options for Excel export functionality.
+4 -3
View File
@@ -1,7 +1,9 @@
using JdeScoping.Api;
using JdeScoping.Core.Interfaces;
using JdeScoping.Core.Options;
using JdeScoping.DataAccess.Configuration;
using JdeScoping.DataAccess.Options;
using JdeScoping.DataSync.Options;
using JdeScoping.ExcelIO.Options;
using JdeScoping.Infrastructure.Options;
using JdeScoping.Database;
using Microsoft.Extensions.Options;
@@ -68,7 +70,6 @@ static void ValidateServices(IServiceProvider services)
// Validate Options classes are bound
_ = provider.GetRequiredService<IOptions<DataAccessOptions>>();
_ = provider.GetRequiredService<IOptions<DataSyncOptions>>();
_ = provider.GetRequiredService<IOptions<JdeScoping.DataSync.Configuration.DataSyncOptions>>();
_ = provider.GetRequiredService<IOptions<ExcelExportOptions>>();
_ = provider.GetRequiredService<IOptions<SearchProcessingOptions>>();
_ = provider.GetRequiredService<IOptions<DataSourceOptions>>();
+4 -4
View File
@@ -112,16 +112,16 @@
]
},
"Auth": {
"UseFakeAuth": false,
"CookieName": "ScopingTool.Auth",
"CookieExpirationMinutes": 480,
"AdminBypassUsers": []
"CookieExpirationMinutes": 480
},
"Ldap": {
"ServerUrls": ["ldap.corp.example.com"],
"GroupDn": "CN=ScopingTool-Users,OU=Groups,DC=corp,DC=example,DC=com",
"SearchBase": "DC=corp,DC=example,DC=com",
"ConnectionTimeoutSeconds": 30
"ConnectionTimeoutSeconds": 30,
"UseFakeAuth": false,
"AdminBypassUsers": []
},
"ExcelExport": {
"TempDirectory": "/tmp/lotfinder",
@@ -2,7 +2,7 @@ using System.DirectoryServices.Protocols;
using System.Net;
using JdeScoping.Core.Interfaces;
using JdeScoping.Core.Models;
using JdeScoping.Core.Options;
using JdeScoping.Infrastructure.Options;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
@@ -16,16 +16,13 @@ public sealed class LdapAuthService : IAuthService
private const string LdapLookupFormat = "(sAMAccountName={0})";
private readonly LdapOptions _options;
private readonly AuthOptions _authOptions;
private readonly ILogger<LdapAuthService> _logger;
public LdapAuthService(
IOptions<LdapOptions> options,
IOptions<AuthOptions> authOptions,
ILogger<LdapAuthService> logger)
{
_options = options.Value;
_authOptions = authOptions.Value;
_logger = logger;
}
@@ -41,7 +38,7 @@ public sealed class LdapAuthService : IAuthService
}
// Check if user is in admin bypass list
var isAdminBypass = _authOptions.AdminBypassUsers
var isAdminBypass = _options.AdminBypassUsers
.Any(u => string.Equals(u, username, StringComparison.OrdinalIgnoreCase));
// Try each configured LDAP server
@@ -1,4 +1,4 @@
namespace JdeScoping.Core.Options;
namespace JdeScoping.Infrastructure.Options;
/// <summary>
/// Configuration options for data source selection (Oracle vs file-based).
@@ -1,4 +1,4 @@
namespace JdeScoping.Core.Options;
namespace JdeScoping.Infrastructure.Options;
/// <summary>
/// LDAP configuration options for authentication
@@ -32,4 +32,16 @@ public class LdapOptions
/// Connection timeout in seconds.
/// </summary>
public int ConnectionTimeoutSeconds { get; set; } = 30;
/// <summary>
/// Enable fake authentication for development.
/// When true, any credentials are accepted.
/// </summary>
public bool UseFakeAuth { get; set; } = false;
/// <summary>
/// Optional list of usernames that bypass group check.
/// Use sparingly for admin/testing purposes.
/// </summary>
public string[] AdminBypassUsers { get; set; } = [];
}
@@ -3,7 +3,7 @@ using System.Text.Json;
using JdeScoping.Core.Interfaces;
using JdeScoping.Core.Models;
using JdeScoping.Core.Models.Quality;
using JdeScoping.Core.Options;
using JdeScoping.Infrastructure.Options;
using Microsoft.Extensions.Options;
namespace JdeScoping.Infrastructure.Sources.Cms;
@@ -5,7 +5,7 @@ using JdeScoping.Core.Models;
using JdeScoping.Core.Models.Inventory;
using JdeScoping.Core.Models.Organization;
using JdeScoping.Core.Models.WorkOrders;
using JdeScoping.Core.Options;
using JdeScoping.Infrastructure.Options;
using Microsoft.Extensions.Options;
namespace JdeScoping.Infrastructure.Sources.Jde;