using Centron.DAO; using Centron.Tests.BL.SetupUtils; using Centron.DAO.Mappings; using Centron.DAO.Mappings.Administration; using Centron.DAO.Mappings.Administration.Company; using Centron.DAO.Mappings.Administration.Employees; using Centron.DAO.Mappings.CustomerArea.Support; using Centron.DAO.Mappings.States; using Centron.Data.WebServices.Administration; using Centron.Data.WebServices.Administration.Login; using Centron.Interfaces.Administration.Logins; using Microsoft.Graph.Models; namespace Centron.Tests.BL.Administration.Logins; using Centron.BusinessLogic.Administration.Logins; using Centron.Interfaces.BL; using FluentNHibernate.Cfg; using FluentNHibernate.Cfg.Db; using NHibernate.Tool.hbm2ddl; using System.Collections.Generic; using DAO; using JetBrains.Annotations; using NHibernate; using Xunit; [TestSubject(typeof(EntraIDUsersBL))] public class EntraIDUsersBLTest { [Fact] public async Task MatchEntraIDUsersWorksAsExpected() { var session = CreateSession(); DbSetupUtils.SaveAppUser(session, "admin", "admin@admin.com", 1, "1-unique"); DbSetupUtils.SaveAppUser(session, "root", "root@admin.com", 10, null); DbSetupUtils.SaveAppUser(session, "Hans", "Hans@mail.com", 2, "2-matched"); DbSetupUtils.SaveAppUser(session, "Jake", "Jake@mail.com", 3, "3-matched"); DbSetupUtils.SaveAppUser(session, "Maria", "Maria@mail.com", 4, "4-unmatched"); DbSetupUtils.SaveAppUser(session, "Eve", "", 5, "5-matched"); DbSetupUtils.SaveAppUser(session, "Dave", "Dave@mail.com", 7, null); DbSetupUtils.SaveAppUser(session, "Lia", "Lia@mail.com", 8, "8-true"); await session.FlushAsync(); List entraUsers = [ CreateUser("Hans@mail.com", "2-matched"), CreateUser("jake@mail.com", "3-matched"), CreateUser("Maria@mail.com", "6-unmatched"), CreateUser("Eve@mail.com", "5-matched"), CreateUser("Dave@mail.com", "7-notsyncedyet"), CreateUser("Lia@mail.com", "8-false"), CreateUser("Lia-false@mail.com", "8-true"), CreateUser("john@mail.com", "10-unique") ]; var expectedResult = Result.AsSuccess(new MatchUsersResultDTO { MatchedUsers = [ new MatchedEntraIDCentronUserDTO { EntraIdUser = new EntraIDUserDTO { Email = "Hans@mail.com", SubjectIdentifier = "2-matched" }, AppUser = new AppUserDTO { Name = "Hans", EmployeeI3D = 2, I3D = 2, OpenIdConnectSubjectIdentifier = "2-matched" } }, new MatchedEntraIDCentronUserDTO { EntraIdUser = new EntraIDUserDTO { Email = "jake@mail.com", SubjectIdentifier = "3-matched" }, AppUser = new AppUserDTO { Name = "Jake", EmployeeI3D = 3, I3D = 3, OpenIdConnectSubjectIdentifier = "3-matched" } } ], UnmatchedUsers = [ new MatchedEntraIDCentronUserDTO { EntraIdUser = new EntraIDUserDTO { Email = "Dave@mail.com", SubjectIdentifier = "7-notsyncedyet" }, AppUser = new AppUserDTO { Name = "Dave", EmployeeI3D = 7, I3D = 7, OpenIdConnectSubjectIdentifier = null } } ], MisconfiguredSub = [ new MatchedEntraIDCentronUserDTO { EntraIdUser = null, AppUser = new AppUserDTO { Name = "admin", EmployeeI3D = 1, I3D = 1, OpenIdConnectSubjectIdentifier = "1-unique" } }, new MatchedEntraIDCentronUserDTO { EntraIdUser = new EntraIDUserDTO { Email = "Maria@mail.com", SubjectIdentifier = "6-unmatched" }, AppUser = new AppUserDTO { Name = "Maria", EmployeeI3D = 4, I3D = 4, OpenIdConnectSubjectIdentifier = "4-unmatched" } }, new MatchedEntraIDCentronUserDTO { EntraIdUser = new EntraIDUserDTO { Email = "Eve@mail.com", SubjectIdentifier = "5-matched" }, AppUser = new AppUserDTO { Name = "Eve", EmployeeI3D = 5, I3D = 5, OpenIdConnectSubjectIdentifier = "5-matched" } }, new MatchedEntraIDCentronUserDTO() { EntraIdUser = new EntraIDUserDTO { Email = "Lia-false@mail.com", SubjectIdentifier = "8-true" }, AppUser = new AppUserDTO { Name = "Lia", EmployeeI3D = 8, I3D = 8, OpenIdConnectSubjectIdentifier = "8-true" } } ], UsersNotInCentron = [ new EntraIDUserDTO { Email = "john@mail.com", SubjectIdentifier = "10-unique" } ], UsersNotInEntra = [ new AppUserDTO { Name = "root", EmployeeI3D = 10, I3D = 10, OpenIdConnectSubjectIdentifier = null } ] }); var daoSession = new DAOSession(session); var graphServiceClient = MockSetupUtils.PrepareGraphMock(entraUsers); var licenseManager = MockSetupUtils.PrepareLicenseManagerMock(LicenseGuids.OpenIDConnectAuthentication); var entraIDUsersBL = new EntraIDUsersBL(daoSession, graphServiceClient, licenseManager); var matchEntraIdUsers = await entraIDUsersBL.MatchEntraIDUsers(); Assert.Equivalent(expectedResult.Data, matchEntraIdUsers.Data, true); } [Fact] public async Task MatchEntraIDUsersMatch() { var session = CreateSession(); DbSetupUtils.SaveAppUser(session, "user", "user@mail.com", 1, "match"); await session.FlushAsync(); List entraUsers = [ CreateUser("user@mail.com", "match"), ]; var expectedResult = Result.AsSuccess(new MatchUsersResultDTO { MatchedUsers = [ new MatchedEntraIDCentronUserDTO { EntraIdUser = new EntraIDUserDTO { Email = "user@mail.com", SubjectIdentifier = "match" }, AppUser = new AppUserDTO { Name = "user", EmployeeI3D = 1, I3D = 1, OpenIdConnectSubjectIdentifier = "match" } } ], UnmatchedUsers = [], MisconfiguredSub = [], UsersNotInCentron = [], UsersNotInEntra = [] }); var daoSession = new DAOSession(session); var graphServiceClient = MockSetupUtils.PrepareGraphMock(entraUsers); var licenseManager = MockSetupUtils.PrepareLicenseManagerMock(LicenseGuids.OpenIDConnectAuthentication); var entraIDUsersBL = new EntraIDUsersBL(daoSession, graphServiceClient, licenseManager); var matchEntraIdUsers = await entraIDUsersBL.MatchEntraIDUsers(); Assert.Equivalent(expectedResult.Data, matchEntraIdUsers.Data, true); } [Fact] public async Task MatchEntraIDUsersUnmatched() { var session = CreateSession(); DbSetupUtils.SaveAppUser(session, "user", "user@mail.com", 1, null); await session.FlushAsync(); List entraUsers = [ CreateUser("user@mail.com", "not-synced-yet"), ]; var expectedResult = Result.AsSuccess(new MatchUsersResultDTO { MatchedUsers = [], UnmatchedUsers = [ new MatchedEntraIDCentronUserDTO { EntraIdUser = new EntraIDUserDTO { Email = "user@mail.com", SubjectIdentifier = "not-synced-yet" }, AppUser = new AppUserDTO { Name = "user", EmployeeI3D = 1, I3D = 1, OpenIdConnectSubjectIdentifier = null } } ], MisconfiguredSub = [], UsersNotInCentron = [], UsersNotInEntra = [] }); var daoSession = new DAOSession(session); var graphServiceClient = MockSetupUtils.PrepareGraphMock(entraUsers); var licenseManager = MockSetupUtils.PrepareLicenseManagerMock(LicenseGuids.OpenIDConnectAuthentication); var entraIDUsersBL = new EntraIDUsersBL(daoSession, graphServiceClient, licenseManager); var matchEntraIdUsers = await entraIDUsersBL.MatchEntraIDUsers(); Assert.Equivalent(expectedResult.Data, matchEntraIdUsers.Data, true); } [Fact] public async Task MatchEntraIDUsersMisconfiguredWrongEmail() { var session = CreateSession(); DbSetupUtils.SaveAppUser(session, "user", "wrong-user@mail.com", 1, "match"); await session.FlushAsync(); List entraUsers = [ CreateUser("correct-user@mail.com", "match"), ]; var expectedResult = Result.AsSuccess(new MatchUsersResultDTO { MatchedUsers = [], UnmatchedUsers = [], MisconfiguredSub = [ new MatchedEntraIDCentronUserDTO { EntraIdUser = new EntraIDUserDTO { Email = "correct-user@mail.com", SubjectIdentifier = "match" }, AppUser = new AppUserDTO { Name = "user", EmployeeI3D = 1, I3D = 1, OpenIdConnectSubjectIdentifier = "match" } } ], UsersNotInCentron = [], UsersNotInEntra = [] }); var daoSession = new DAOSession(session); var licenseManager = MockSetupUtils.PrepareLicenseManagerMock(LicenseGuids.OpenIDConnectAuthentication); var graphServiceClient = MockSetupUtils.PrepareGraphMock(entraUsers); var entraIDUsersBL = new EntraIDUsersBL(daoSession, graphServiceClient, licenseManager); var matchEntraIdUsers = await entraIDUsersBL.MatchEntraIDUsers(); Assert.Equivalent(expectedResult.Data, matchEntraIdUsers.Data, true); } [Fact] public async Task MatchEntraIDUsersMisconfiguredNoEntraUserWithSub() { var session = CreateSession(); DbSetupUtils.SaveAppUser(session, "user", "user@mail.com", 1, "non-existent-sub"); await session.FlushAsync(); var expectedResult = Result.AsSuccess(new MatchUsersResultDTO { MatchedUsers = [], UnmatchedUsers = [], MisconfiguredSub = [ new MatchedEntraIDCentronUserDTO { EntraIdUser = null, AppUser = new AppUserDTO { Name = "user", EmployeeI3D = 1, I3D = 1, OpenIdConnectSubjectIdentifier = "non-existent-sub" } } ], UsersNotInCentron = [], UsersNotInEntra = [] }); var daoSession = new DAOSession(session); var graphServiceClient = MockSetupUtils.PrepareGraphMock([]); var licenseManager = MockSetupUtils.PrepareLicenseManagerMock(LicenseGuids.OpenIDConnectAuthentication); var entraIDUsersBL = new EntraIDUsersBL(daoSession, graphServiceClient, licenseManager); var matchEntraIdUsers = await entraIDUsersBL.MatchEntraIDUsers(); Assert.Equivalent(expectedResult.Data, matchEntraIdUsers.Data, true); } [Fact] public async Task MatchEntraIDUsersNotInCentron() { var session = CreateSession(); await session.FlushAsync(); List entraUsers = [ CreateUser("user@mail.com", "not-synced-yet"), ]; var expectedResult = Result.AsSuccess(new MatchUsersResultDTO { MatchedUsers = [], UnmatchedUsers = [], MisconfiguredSub = [], UsersNotInCentron = [ new EntraIDUserDTO { Email = "user@mail.com", SubjectIdentifier = "not-synced-yet" } ], UsersNotInEntra = [] }); var daoSession = new DAOSession(session); var graphServiceClient = MockSetupUtils.PrepareGraphMock(entraUsers); var licenseManager = MockSetupUtils.PrepareLicenseManagerMock(LicenseGuids.OpenIDConnectAuthentication); var entraIDUsersBL = new EntraIDUsersBL(daoSession, graphServiceClient, licenseManager); var matchEntraIdUsers = await entraIDUsersBL.MatchEntraIDUsers(); Assert.Equivalent(expectedResult.Data, matchEntraIdUsers.Data, true); } [Fact] public async Task MatchEntraIDUsersNotInEntra() { var session = CreateSession(); DbSetupUtils.SaveAppUser(session, "user", "user@mail.com", 1, null); await session.FlushAsync(); var expectedResult = Result.AsSuccess(new MatchUsersResultDTO { MatchedUsers = [], UnmatchedUsers = [], MisconfiguredSub = [], UsersNotInCentron = [], UsersNotInEntra = [ new AppUserDTO { Name = "user", EmployeeI3D = 1, I3D = 1, OpenIdConnectSubjectIdentifier = null } ] }); var daoSession = new DAOSession(session); var graphServiceClient = MockSetupUtils.PrepareGraphMock([]); var licenseManager = MockSetupUtils.PrepareLicenseManagerMock(LicenseGuids.OpenIDConnectAuthentication); var entraIDUsersBL = new EntraIDUsersBL(daoSession, graphServiceClient, licenseManager); var matchEntraIdUsers = await entraIDUsersBL.MatchEntraIDUsers(); Assert.Equivalent(expectedResult.Data, matchEntraIdUsers.Data, true); } [Fact] public async Task MatchEntraIDUsersNotActive() { var session = CreateSession(); DbSetupUtils.SaveAppUser(session, "disabled", "disabled@mail.com", 1, isAccountDisabled: true); DbSetupUtils.SaveAppUser(session, "disabled-from-today", "disabled-from-today@mail.com", 2, disabledFromDate: DateTime.Today); DbSetupUtils.SaveAppUser(session, "disabled-from-yesterday", "disabled-from-yesterday@mail.com", 3, disabledFromDate: DateTime.Today - TimeSpan.FromDays(1)); DbSetupUtils.SaveAppUser(session, "disabled-to-today", "disabled-to-today@mail.com", 4, disabledToDate: DateTime.Today); DbSetupUtils.SaveAppUser(session, "disabled-to-tomorrow", "disabled-to-tomorrow@mail.com", 5, disabledToDate: DateTime.Today + TimeSpan.FromDays(1)); DbSetupUtils.SaveAppUser(session, "disabled-in-range", "disabled-in-range@mail.com", 6, disabledFromDate: DateTime.Today - TimeSpan.FromDays(1), disabledToDate: DateTime.Today + TimeSpan.FromDays(1)); await session.FlushAsync(); List entraUsers = [ CreateUser("disabled@mail.com", "not-synced-yet-1"), CreateUser("disabled-from-today@mail.com", "not-synced-yet-2"), CreateUser("disabled-from-yesterday@mail.com", "not-synced-yet-3"), CreateUser("disabled-to-today@mail.com", "not-synced-yet-4"), CreateUser("disabled-to-tomorrow@mail.com", "not-synced-yet-5"), CreateUser("disabled-in-range@mail.com", "not-synced-yet-6"), ]; var expectedResult = Result.AsSuccess(new MatchUsersResultDTO { MatchedUsers = [], UnmatchedUsers = [], MisconfiguredSub = [], UsersNotInCentron = [ new EntraIDUserDTO { Email = "disabled@mail.com", SubjectIdentifier = "not-synced-yet-1" }, new EntraIDUserDTO { Email = "disabled-from-today@mail.com", SubjectIdentifier = "not-synced-yet-2" }, new EntraIDUserDTO { Email = "disabled-from-yesterday@mail.com", SubjectIdentifier = "not-synced-yet-3" }, new EntraIDUserDTO { Email = "disabled-to-today@mail.com", SubjectIdentifier = "not-synced-yet-4" }, new EntraIDUserDTO { Email = "disabled-to-tomorrow@mail.com", SubjectIdentifier = "not-synced-yet-5" }, new EntraIDUserDTO { Email = "disabled-in-range@mail.com", SubjectIdentifier = "not-synced-yet-6" } ], UsersNotInEntra = [] }); var daoSession = new DAOSession(session); var graphServiceClient = MockSetupUtils.PrepareGraphMock(entraUsers); var licenseManager = MockSetupUtils.PrepareLicenseManagerMock(LicenseGuids.OpenIDConnectAuthentication); var entraIDUsersBL = new EntraIDUsersBL(daoSession, graphServiceClient, licenseManager); var matchEntraIdUsers = await entraIDUsersBL.MatchEntraIDUsers(); Assert.Equivalent(expectedResult.Data, matchEntraIdUsers.Data, true); } private User CreateUser(string email, string subjectId) { return new User { Id = subjectId, UserPrincipalName = email, }; } public ISession CreateSession() { var fluentConfiguration = Fluently.Configure() .Database(SQLiteConfiguration.Standard.InMemory) .Mappings(m => m.FluentMappings.Add()) .Mappings(m => m.FluentMappings.Add()) .Mappings(m => m.FluentMappings.Add()) .Mappings(m => m.FluentMappings.Add()) .Mappings(m => m.FluentMappings.Add()) .Mappings(m => m.FluentMappings.Add()) .Mappings(m => m.FluentMappings.Add()) .Mappings(m => m.FluentMappings.Add()); ISessionFactory sessionFactory = fluentConfiguration.BuildSessionFactory(); ISession session = sessionFactory.OpenSession(); new SchemaExport(fluentConfiguration.BuildConfiguration()).Execute(true, true, false, session.Connection, Console.Out); return session; } }