| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- using Admin.NET.Plugin.AiDOP.Controllers;
- using Admin.NET.Plugin.AiDOP.Infrastructure;
- using Admin.NET.Plugin.AiDOP.Service;
- using Admin.NET.Plugin.AiDOP.SmartOps;
- using Xunit;
- namespace Admin.NET.Plugin.AiDOP.Tests.SmartOps;
- public class SmartOpsTrustedScopeTests
- {
- private const long TenantA = 838257186181189;
- private const long FactoryA = 838257186320453;
- private const long FactoryB = 838257212858437;
- [Fact]
- public void PlatformTenant_IsRejected()
- {
- Assert.Throws<InvalidOperationException>(() =>
- SmartOpsTrustedScopeRules.EnsureBusinessTenant(SmartOpsTrustedScopeRules.PlatformTenantId));
- Assert.Throws<InvalidOperationException>(() =>
- SmartOpsTrustedScopeRules.EnsureBusinessTenant(0));
- Assert.Throws<InvalidOperationException>(() =>
- SmartOpsTrustedScopeRules.EnsureBusinessTenant(1));
- }
- [Fact]
- public void BusinessTenant_IsAccepted()
- {
- SmartOpsTrustedScopeRules.EnsureBusinessTenant(TenantA);
- }
- [Theory]
- [InlineData(838257186181189, 838257186320453, 1L, 838257186320453)]
- [InlineData(838257186181189, 838257186320453, 838257212858437L, 838257186320453)]
- [InlineData(838257186181189, 838257186320453, 838257186181189L, 838257186320453)]
- [InlineData(838257186181189, 838257186320453, 838257186320453L, 838257186320453)]
- public void ClientFactory_IsNeverUsedAsPermissionBoundary(
- long tenantId, long orgId, long candidate, long expected)
- {
- Assert.Equal(expected, SmartOpsTrustedScopeRules.ResolveFactory(tenantId, orgId, candidate));
- }
- [Fact]
- public void MissingOrSelfFactory_IsRejected()
- {
- Assert.Throws<InvalidOperationException>(() =>
- SmartOpsTrustedScopeRules.ResolveFactory(TenantA, 0, FactoryA));
- Assert.Throws<InvalidOperationException>(() =>
- SmartOpsTrustedScopeRules.ResolveFactory(TenantA, TenantA, FactoryA));
- }
- [Fact]
- public void AuthorizedFactory_MatchesTenantOrgOnly()
- {
- Assert.True(SmartOpsTrustedScopeRules.IsAuthorizedFactory(TenantA, FactoryA, FactoryA));
- Assert.False(SmartOpsTrustedScopeRules.IsAuthorizedFactory(TenantA, FactoryA, FactoryB));
- }
- [Fact]
- public void OperationalFactory_AcceptsLegacyDefaultAndTrustedOrg()
- {
- Assert.True(SmartOpsOperationalFactory.Matches(TenantA, FactoryA, 1));
- Assert.True(SmartOpsOperationalFactory.Matches(TenantA, FactoryA, FactoryA));
- Assert.True(SmartOpsOperationalFactory.Matches(TenantA, FactoryA, 0));
- Assert.True(SmartOpsOperationalFactory.Matches(TenantA, FactoryA, null));
- Assert.False(SmartOpsOperationalFactory.Matches(TenantA, FactoryA, TenantA));
- Assert.False(SmartOpsOperationalFactory.Matches(TenantA, FactoryA, FactoryB));
- }
- [Fact]
- public void PlanNo_IsTenantScopedAndMonotonic()
- {
- var prefix = SmartOpsImprovementPlanNo.BuildPrefix(new DateTime(2026, 8, 17));
- Assert.Equal("SOP-20260817-", prefix);
- Assert.Equal("SOP-20260817-001", SmartOpsImprovementPlanNo.Next(prefix, Array.Empty<string>()));
- Assert.Equal(
- "SOP-20260817-003",
- SmartOpsImprovementPlanNo.Next(prefix, new[] { "SOP-20260817-001", "SOP-20260817-002" }));
- }
- [Fact]
- public void ConcurrentPlanNo_DoesNotReuseExistingNumbers()
- {
- var prefix = "SOP-20260817-";
- var existing = new List<string>();
- var generated = new HashSet<string>();
- for (var i = 0; i < 20; i++)
- {
- var next = SmartOpsImprovementPlanNo.Next(prefix, existing);
- Assert.True(generated.Add(next));
- existing.Add(next);
- }
- Assert.Equal(20, generated.Count);
- Assert.Contains("SOP-20260817-020", generated);
- }
- [Fact]
- public void DiagnosisAndImprovement_UseTrustedScopeNotRequestTenant()
- {
- var diagnosis = typeof(AidopKanbanController).GetMethod(nameof(AidopKanbanController.GetSmartDiagnosis));
- Assert.NotNull(diagnosis);
- var controllerSource = ReadSiblingSource(
- typeof(AdoSmartOpsImprovementPlanController),
- "AdoSmartOpsImprovementPlanController.cs");
- var diagnosisSource = ReadSiblingSource(
- typeof(AidopKanbanController),
- "AidopKanbanController.Diagnosis.cs");
- Assert.DoesNotContain("AidopTenantHelper.GetTenantId", controllerSource);
- Assert.DoesNotContain("AidopTenantHelper.GetTenantId", diagnosisSource);
- Assert.Contains("_trustedScope.ResolveAsync", controllerSource);
- Assert.Contains("_trustedScope.ResolveAsync", diagnosisSource);
- Assert.Contains("x.TenantId == plan.TenantId", controllerSource);
- Assert.Contains("x.TenantId == tenantId", controllerSource);
- Assert.DoesNotContain("[AllowAnonymous]", controllerSource);
- Assert.DoesNotContain("FactoryId = input.FactoryId", controllerSource);
- }
- [Fact]
- public void ApproverGuard_ClearsFiltersWhenResolvingRoleMembers()
- {
- var source = ReadSiblingSource(
- typeof(SmartOpsImprovementApproverGuard),
- "SmartOpsImprovementApproverGuard.cs");
- Assert.Contains("Queryable<SysUserRole>()", source);
- Assert.Contains(".ClearFilter()", source);
- Assert.Contains("u.TenantId == tenantId", source);
- }
- [Fact]
- public void ApprovalCallback_UpdatesWithTenantCondition()
- {
- var source = ReadSiblingSource(
- typeof(SmartOpsImprovementBizHandler),
- "SmartOpsImprovementBizHandler.cs");
- Assert.Contains("x.TenantId == plan.TenantId", source);
- Assert.DoesNotContain(".Where(x => x.Id == bizId)", source.Replace("x.Id == bizId && x.TenantId == plan.TenantId", ""));
- }
- private static string ReadSiblingSource(Type type, string fileName)
- {
- var root = FindRepoRoot();
- var matches = Directory.GetFiles(root, fileName, SearchOption.AllDirectories)
- .Where(path => path.Replace('\\', '/').Contains("/Admin.NET.Plugin.AiDOP/")
- && !path.Contains(".Tests"))
- .ToList();
- Assert.NotEmpty(matches);
- return File.ReadAllText(matches[0]);
- }
- private static string FindRepoRoot()
- {
- var dir = new DirectoryInfo(AppContext.BaseDirectory);
- while (dir != null)
- {
- if (File.Exists(Path.Combine(dir.FullName, "AGENTS.md")))
- return dir.FullName;
- dir = dir.Parent;
- }
- return Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "..", "..", "..", "..", "..", ".."));
- }
- }
|