Add AD auth and B1 currency fields
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
using Microsoft.Data.Sqlite;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using TrafagSalesExporter.Data;
|
||||
using TrafagSalesExporter.Models;
|
||||
using TrafagSalesExporter.Services;
|
||||
|
||||
namespace TrafagSalesExporter.Tests;
|
||||
|
||||
public class CentralSalesRecordServiceTests : IDisposable
|
||||
{
|
||||
private readonly SqliteConnection _connection;
|
||||
private readonly TestDbContextFactory _dbFactory;
|
||||
|
||||
public CentralSalesRecordServiceTests()
|
||||
{
|
||||
_connection = new SqliteConnection("DataSource=:memory:");
|
||||
_connection.Open();
|
||||
|
||||
var options = new DbContextOptionsBuilder<AppDbContext>()
|
||||
.UseSqlite(_connection)
|
||||
.Options;
|
||||
|
||||
using var db = new AppDbContext(options);
|
||||
db.Database.EnsureCreated();
|
||||
|
||||
_dbFactory = new TestDbContextFactory(options);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_connection.Dispose();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ReplaceForSiteAsync_Persists_B1_Document_Currency_Fields()
|
||||
{
|
||||
var site = new Site
|
||||
{
|
||||
Id = 1,
|
||||
Schema = "SBODEMO",
|
||||
TSC = "TRCH",
|
||||
Land = "Schweiz",
|
||||
SourceSystem = "BI1",
|
||||
IsActive = true
|
||||
};
|
||||
|
||||
await using (var db = await _dbFactory.CreateDbContextAsync())
|
||||
{
|
||||
db.Sites.Add(site);
|
||||
await db.SaveChangesAsync();
|
||||
}
|
||||
|
||||
var service = new CentralSalesRecordService(_dbFactory, new NullAppEventLogService());
|
||||
await service.ReplaceForSiteAsync(site, [
|
||||
new SalesRecord
|
||||
{
|
||||
ExtractionDate = new DateTime(2026, 4, 29),
|
||||
Tsc = "TRCH",
|
||||
InvoiceNumber = "1001",
|
||||
PositionOnInvoice = 1,
|
||||
Material = "MAT",
|
||||
Name = "Article",
|
||||
ProductGroup = "PG",
|
||||
Quantity = 2m,
|
||||
StandardCost = 10m,
|
||||
StandardCostCurrency = "CHF",
|
||||
SalesPriceValue = 25m,
|
||||
SalesCurrency = "EUR",
|
||||
DocumentCurrency = "EUR",
|
||||
DocumentTotalForeignCurrency = 100m,
|
||||
DocumentTotalLocalCurrency = 95m,
|
||||
VatSumForeignCurrency = 8m,
|
||||
VatSumLocalCurrency = 7.6m,
|
||||
DocumentRate = 0.95m,
|
||||
CompanyCurrency = "CHF",
|
||||
Land = "Schweiz",
|
||||
DocumentType = "INV"
|
||||
}
|
||||
]);
|
||||
|
||||
var rows = await service.GetAllAsync();
|
||||
|
||||
var row = Assert.Single(rows);
|
||||
Assert.Equal("EUR", row.DocumentCurrency);
|
||||
Assert.Equal(100m, row.DocumentTotalForeignCurrency);
|
||||
Assert.Equal(95m, row.DocumentTotalLocalCurrency);
|
||||
Assert.Equal(8m, row.VatSumForeignCurrency);
|
||||
Assert.Equal(7.6m, row.VatSumLocalCurrency);
|
||||
Assert.Equal(0.95m, row.DocumentRate);
|
||||
Assert.Equal("CHF", row.CompanyCurrency);
|
||||
}
|
||||
|
||||
private sealed class NullAppEventLogService : IAppEventLogService
|
||||
{
|
||||
public Task WriteAsync(string category, string message, string level = "Info", int? siteId = null, string? land = null, string? details = null)
|
||||
=> Task.CompletedTask;
|
||||
|
||||
public Task WriteDebugAsync(string category, string message, int? siteId = null, string? land = null, string? details = null)
|
||||
=> Task.CompletedTask;
|
||||
}
|
||||
|
||||
private sealed class TestDbContextFactory : IDbContextFactory<AppDbContext>
|
||||
{
|
||||
private readonly DbContextOptions<AppDbContext> _options;
|
||||
|
||||
public TestDbContextFactory(DbContextOptions<AppDbContext> options)
|
||||
{
|
||||
_options = options;
|
||||
}
|
||||
|
||||
public AppDbContext CreateDbContext() => new(_options);
|
||||
|
||||
public Task<AppDbContext> CreateDbContextAsync(CancellationToken cancellationToken = default)
|
||||
=> Task.FromResult(new AppDbContext(_options));
|
||||
}
|
||||
}
|
||||
@@ -38,12 +38,19 @@ public class ManualExcelImportServiceTests
|
||||
ws.Cell(2, 18).Value = "PO-1";
|
||||
ws.Cell(2, 19).Value = 21.40m;
|
||||
ws.Cell(2, 20).Value = "EUR";
|
||||
ws.Cell(2, 21).Value = "DAP";
|
||||
ws.Cell(2, 22).Value = "Alice";
|
||||
ws.Cell(2, 23).Value = "14.04.2026";
|
||||
ws.Cell(2, 24).Value = "10.04.2026";
|
||||
ws.Cell(2, 25).Value = "Deutschland";
|
||||
ws.Cell(2, 26).Value = "Invoice";
|
||||
ws.Cell(2, 21).Value = "EUR";
|
||||
ws.Cell(2, 22).Value = 120.50m;
|
||||
ws.Cell(2, 23).Value = 110.25m;
|
||||
ws.Cell(2, 24).Value = 8.10m;
|
||||
ws.Cell(2, 25).Value = 7.45m;
|
||||
ws.Cell(2, 26).Value = 1.0925m;
|
||||
ws.Cell(2, 27).Value = "CHF";
|
||||
ws.Cell(2, 28).Value = "DAP";
|
||||
ws.Cell(2, 29).Value = "Alice";
|
||||
ws.Cell(2, 30).Value = "14.04.2026";
|
||||
ws.Cell(2, 31).Value = "10.04.2026";
|
||||
ws.Cell(2, 32).Value = "Deutschland";
|
||||
ws.Cell(2, 33).Value = "Invoice";
|
||||
});
|
||||
|
||||
try
|
||||
@@ -60,6 +67,13 @@ public class ManualExcelImportServiceTests
|
||||
Assert.Equal(2.5m, row.Quantity);
|
||||
Assert.Equal(10.25m, row.StandardCost);
|
||||
Assert.Equal(21.40m, row.SalesPriceValue);
|
||||
Assert.Equal("EUR", row.DocumentCurrency);
|
||||
Assert.Equal(120.50m, row.DocumentTotalForeignCurrency);
|
||||
Assert.Equal(110.25m, row.DocumentTotalLocalCurrency);
|
||||
Assert.Equal(8.10m, row.VatSumForeignCurrency);
|
||||
Assert.Equal(7.45m, row.VatSumLocalCurrency);
|
||||
Assert.Equal(1.0925m, row.DocumentRate);
|
||||
Assert.Equal("CHF", row.CompanyCurrency);
|
||||
Assert.Equal("Deutschland", row.Land);
|
||||
Assert.Equal("Invoice", row.DocumentType);
|
||||
Assert.Equal(new DateTime(2026, 4, 14), row.InvoiceDate);
|
||||
@@ -205,6 +219,13 @@ public class ManualExcelImportServiceTests
|
||||
"Purchase Order number",
|
||||
"Sales Price/Value",
|
||||
"Sales Currency",
|
||||
"Document Currency",
|
||||
"Document Total FC",
|
||||
"Document Total LC",
|
||||
"VAT Sum FC",
|
||||
"VAT Sum LC",
|
||||
"Document Rate",
|
||||
"Company Currency",
|
||||
"Incoterms 2020",
|
||||
"Sales responsible employee",
|
||||
"invoice date",
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
using System.Security.Claims;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using TrafagSalesExporter.Security;
|
||||
|
||||
namespace TrafagSalesExporter.Tests;
|
||||
|
||||
public class SecurityPolicyFactoryTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task AccessPolicy_Allows_User_In_Configured_Access_Group()
|
||||
{
|
||||
var policy = SecurityPolicyFactory.BuildAccessPolicy(new SecurityOptions
|
||||
{
|
||||
AccessGroups = ["TRAFAG\\TrafagSalesExporter-Users"]
|
||||
}, useDevelopmentAuthentication: false);
|
||||
|
||||
var result = await AuthorizeAsync(policy, CreateUser(roles: ["TRAFAG\\TrafagSalesExporter-Users"]));
|
||||
|
||||
Assert.True(result.Succeeded);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AccessPolicy_Denies_User_Outside_Configured_Access_Group()
|
||||
{
|
||||
var policy = SecurityPolicyFactory.BuildAccessPolicy(new SecurityOptions
|
||||
{
|
||||
AccessGroups = ["TRAFAG\\TrafagSalesExporter-Users"]
|
||||
}, useDevelopmentAuthentication: false);
|
||||
|
||||
var result = await AuthorizeAsync(policy, CreateUser(roles: ["TRAFAG\\OtherGroup"]));
|
||||
|
||||
Assert.False(result.Succeeded);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AccessPolicy_Allows_Authenticated_User_When_Development_Authentication_Is_Active()
|
||||
{
|
||||
var policy = SecurityPolicyFactory.BuildAccessPolicy(new SecurityOptions
|
||||
{
|
||||
AccessGroups = ["TRAFAG\\TrafagSalesExporter-Users"]
|
||||
}, useDevelopmentAuthentication: true);
|
||||
|
||||
var result = await AuthorizeAsync(policy, CreateUser());
|
||||
|
||||
Assert.True(result.Succeeded);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AdminPolicy_Allows_User_In_Admin_Group()
|
||||
{
|
||||
var policy = SecurityPolicyFactory.BuildAdminPolicy(new SecurityOptions
|
||||
{
|
||||
AdminGroups = ["TRAFAG\\TrafagSalesExporter-Admins"]
|
||||
}, useDevelopmentAuthentication: false);
|
||||
|
||||
var result = await AuthorizeAsync(policy, CreateUser(roles: ["TRAFAG\\TrafagSalesExporter-Admins"]));
|
||||
|
||||
Assert.True(result.Succeeded);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AdminPolicy_Denies_Normal_Access_User()
|
||||
{
|
||||
var policy = SecurityPolicyFactory.BuildAdminPolicy(new SecurityOptions
|
||||
{
|
||||
AdminGroups = ["TRAFAG\\TrafagSalesExporter-Admins"]
|
||||
}, useDevelopmentAuthentication: false);
|
||||
|
||||
var result = await AuthorizeAsync(policy, CreateUser(roles: ["TRAFAG\\TrafagSalesExporter-Users"]));
|
||||
|
||||
Assert.False(result.Succeeded);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AdminPolicy_Allows_Development_Admin_Claim()
|
||||
{
|
||||
var policy = SecurityPolicyFactory.BuildAdminPolicy(new SecurityOptions(), useDevelopmentAuthentication: true);
|
||||
|
||||
var result = await AuthorizeAsync(policy, CreateUser(claims:
|
||||
[
|
||||
new Claim(DevelopmentAuthenticationHandler.AdminClaimType, "true")
|
||||
]));
|
||||
|
||||
Assert.True(result.Succeeded);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AdminPolicy_Denies_Development_User_Without_Admin_Claim()
|
||||
{
|
||||
var policy = SecurityPolicyFactory.BuildAdminPolicy(new SecurityOptions(), useDevelopmentAuthentication: true);
|
||||
|
||||
var result = await AuthorizeAsync(policy, CreateUser());
|
||||
|
||||
Assert.False(result.Succeeded);
|
||||
}
|
||||
|
||||
private static async Task<AuthorizationResult> AuthorizeAsync(AuthorizationPolicy policy, ClaimsPrincipal user)
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
services.AddLogging();
|
||||
services.AddAuthorization();
|
||||
var provider = services.BuildServiceProvider();
|
||||
var service = provider.GetRequiredService<IAuthorizationService>();
|
||||
|
||||
return await service.AuthorizeAsync(user, resource: null, policy);
|
||||
}
|
||||
|
||||
private static ClaimsPrincipal CreateUser(IEnumerable<string>? roles = null, IEnumerable<Claim>? claims = null)
|
||||
{
|
||||
var allClaims = new List<Claim>
|
||||
{
|
||||
new(ClaimTypes.Name, "TRAFAG\\tester")
|
||||
};
|
||||
|
||||
allClaims.AddRange((roles ?? []).Select(role => new Claim(ClaimTypes.Role, role)));
|
||||
allClaims.AddRange(claims ?? []);
|
||||
|
||||
return new ClaimsPrincipal(new ClaimsIdentity(allClaims, "Test"));
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user