using Centron.BusinessLogic.Administration.Rights; using Centron.Data.WebServices.Administration; using Centron.Data.WebServices.Administration.Employees; using Centron.Data.WebServices.EmployeeArea; using Centron.Host.Messages; using Centron.Interfaces.Administration.Employees; using CentronSoftware.Centron.WebServices.Connections; using System.Linq.Expressions; namespace Centron.Tests.Integration.Tests.EmployeeManagement { /// /// We test if a user with no admin rights is able to retrieve sensible employee data from collegues via webservice /// /// public class Ticket154840 { private const string _appUserLogin = "drnorights"; private const string _appUserPassword = "123456"; private const string _appUserDevice = "TestDevice"; [Fact] public async Task Execute() { // Prepare var connection = IntegrationTestHelper.GetConnection(); var adminToken = await IntegrationTestHelper.Login(connection); var adminUserEmployee = await this.GetLoggedInEmployee(connection, adminToken); var secretAgentEmployee = await this.GetOrCreateEmployee(connection, adminToken, this.CreateSecretAgentEmployeeDTO); var drNoRightsEmployee = await this.GetOrCreateEmployee(connection, adminToken, this.CreateDrNoRightsEmployeeDTO); var drNoRightsAppUser = await this.GetOrCreateAppUser(connection, adminToken, this.CreateDrNoRightsAppUser(drNoRightsEmployee)); var noRightsGroup = await this.GetOrCreateRightsGroup(connection, adminToken); await this.AddUserToRightsGroup(connection, adminToken, drNoRightsAppUser.I3D, noRightsGroup.I3D); // Test reading employee data with administrative rights await this.RequestOtherEmployeeDataWithAdministrativeRights(connection, adminToken, secretAgentEmployee); await this.RequestOwnEmployeeDataWithAdministrativeRights(connection, adminToken, adminUserEmployee); await IntegrationTestHelper.Logout(connection); // Logout admin var drNoRightsToken = await IntegrationTestHelper.Login(connection, _appUserLogin, _appUserPassword, _appUserDevice); // Test reading employee data without administrative rights await this.RequestOtherEmployeeDataWithoutAdministrativeRights(connection, drNoRightsToken, secretAgentEmployee); await this.RequestOwnEmployeeDataWithoutAdministrativeRights(connection, drNoRightsToken, drNoRightsEmployee); } #region Get/Create Employee data private EmployeeDTO CreateSecretAgentEmployeeDTO() { return new EmployeeDTO() { FirstName = "James", LastName = "Bond", ShortSign = "007", Employeenumber = 7, Email = "bond@mi6.uk", DisplayText = "Top Secret!", RemainingDaysOfVacation = 28, VacationEntitlement = 7, State = 1, SupportLevel = null, DefaultStorageI3D = null, Dispatcher = false, IsActive = true, Availability = EmployeeAvailability.DoNotDisturb, LastAvailabilityChange = new DateTime(2021, 10, 8, 07, 07, 07), BranchI3D = null, LeavingDate = new DateTime(2077, 07, 07, 07, 07, 07), Template1 = false, Template2 = false, Template3 = false, Template4 = false, PersonnelNumber = 7, SuperiorI3D = null, Image = new byte[] { 0, 0, 7 }, SalutationI3D = 1, Street = "No. 25, Wellington Square", Zip = "SW3 4NJ", City = "London", EMailLockbox = "box007", Phone1 = "007 official", Phone2 = "007 mobile", Phone3 = "007 private", Phone4 = "007 bereau", Fax1 = "007 fax1", Fax2 = "007 fax2", Birthday = new DateTime(1980, 11, 11), Salary = 82000, Job = "Secret Agent", LanguageSkills = "Italian, French, Russian, German, Portuguese, Spanish, Mandarin, Cantonese, Japanese", HoursForNextMonth = 160, TrialPeriod = 6, RemindTrialPeriod = true, TrialPeriodRemindInDays = 30, ContractPeriod = 12, RemindContractEnd = true, ContractRemindInDays = 30, CommencementDate = new DateTime(1962, 10, 6), ContractKind = "License to kill", SaleText = "25 films so far... what else to say", Comment = "Oh, just a drink. A martini, shaken, not stirred.", CostCenter = null, SupplierI3D = null, RootDirI3D = null, ManagementVariableField01 = 1000.0m, ManagementVariableField02 = 2000.0m, ManagementVariableField03 = 3000.0m, ManagementVariableField04 = 4000.0m, ManagementVariableField05 = 5000.0m, ManagementVariableField06 = 6000.0m, ManagementVariableField07 = 7000.0m, ManagementVariableField08 = 8000.0m, ManagementVariableField09 = 9000.0m, ManagementVariableField10 = 10000.0m, SignatureAsPicture = new byte[] { 0, 0, 7 }, SignatureAsPictureFileExtension = "png", Signature = "Bond, James Bond" }; } private EmployeeDTO CreateDrNoRightsEmployeeDTO() { return new EmployeeDTO() { FirstName = "Julius", LastName = "No", ShortSign = "Dr. No", Employeenumber = 7, Email = "julius@no.uk", DisplayText = "Mad Scientist!", RemainingDaysOfVacation = 100, VacationEntitlement = 4, State = 1, SupportLevel = null, DefaultStorageI3D = null, Dispatcher = false, IsActive = true, Availability = EmployeeAvailability.Busy, LastAvailabilityChange = new DateTime(1962, 10, 6, 00, 00, 00), BranchI3D = null, LeavingDate = new DateTime(2088, 2, 2, 2, 2, 2), Template1 = false, Template2 = false, Template3 = false, Template4 = false, PersonnelNumber = 2, SuperiorI3D = null, Image = new byte[] { 2, 2, 2 }, SalutationI3D = 1, Street = "SPECTRE Base", Zip = "FL 33042", City = "Crab Key Island", EMailLockbox = "boxDrNo", Phone1 = "Nr2 official", Phone2 = "Nr2 mobile", Phone3 = "Nr2 private", Phone4 = "Nr2 bereau", Fax1 = "Nr2 fax1", Fax2 = "Nr2 fax2", Birthday = new DateTime(1918, 2, 2), Salary = 1000000, Job = "Mad Scientist", LanguageSkills = "English, Chinese", HoursForNextMonth = 240, TrialPeriod = 3, RemindTrialPeriod = false, TrialPeriodRemindInDays = 10, ContractPeriod = 36, RemindContractEnd = false, ContractRemindInDays = 10, CommencementDate = new DateTime(1962, 10, 6), ContractKind = "SPECTRE Main Member", SaleText = "Plays with atoms", Comment = "The successful criminal brain is always superior. It has to be.", CostCenter = null, SupplierI3D = null, RootDirI3D = null, ManagementVariableField01 = 1000000.0m, ManagementVariableField02 = 2000000.0m, ManagementVariableField03 = 3000000.0m, ManagementVariableField04 = 4000000.0m, ManagementVariableField05 = 5000000.0m, ManagementVariableField06 = 6000000.0m, ManagementVariableField07 = 7000000.0m, ManagementVariableField08 = 8000000.0m, ManagementVariableField09 = 9000000.0m, ManagementVariableField10 = 10000000.0m, SignatureAsPicture = new byte[] { 2, 2, 2 }, SignatureAsPictureFileExtension = "png", Signature = "Dr. Julius No" }; } private async Task GetOrCreateEmployee(CentronWebService connection, string adminToken, Func createEmployeeMethod) { var newEmployee = createEmployeeMethod(); var existingEmployee = await this.LoadEmployee(connection, adminToken, newEmployee); if (existingEmployee == null) { existingEmployee = newEmployee; newEmployee.I3D = await this.SaveEmployee(newEmployee, connection, adminToken); } return existingEmployee; } private async Task LoadEmployee(CentronWebService connection, string loginToken, EmployeeDTO newEmployee) { var request = new Request() { Ticket = loginToken }; var response = await connection.CallAsync(f => f.GetAllActiveEmployees(request)); Assert.Equal(StatusCode.Success, response.Status); Assert.NotNull(response.Result); var result = response.Result.FirstOrDefault(f => string.Equals(f.FirstName, newEmployee.FirstName) && string.Equals(f.LastName, newEmployee.LastName) && f.PersonnelNumber == newEmployee.PersonnelNumber); return result; } private async Task SaveEmployee(EmployeeDTO employeeDTO, CentronWebService connection, string loginToken) { var request = IntegrationTestHelper.GetRequest(employeeDTO, loginToken); var response = await connection.CallAsync(f => f.SaveEmployee(request)); Assert.Equal(StatusCode.Success, response.Status); Assert.NotNull(response.Result?.First()); return response.Result?.First() ?? 0; } #endregion #region Get/Create AppUser data private AppUserDTO CreateDrNoRightsAppUser(EmployeeDTO drNoRightsEmployee) { return new AppUserDTO() { EmployeeI3D = drNoRightsEmployee.I3D, Name = _appUserLogin, PasswordMinLength = 0, PasswordValidDurationDays = int.MaxValue, LastPasswordChangedDate = DateTime.Now, AccountDisabledFromDate = null, IsAccountDisabled = false, Kommentar = "Has no rights XD", Status = 1, LoginUsername = _appUserLogin, Password = _appUserPassword, UseTwoFactorAuthentication = false, TwoFactorValidDurationInDays = null, AuthentificationKind = AuthentificationKind.Default }; } private async Task GetOrCreateAppUser(CentronWebService connection, string adminToken, AppUserDTO newAppUserDTO) { var existingAppUser = await this.LoadAppUser(connection, adminToken, newAppUserDTO); if(existingAppUser == null) existingAppUser = await this.SaveAppUser(connection, adminToken, newAppUserDTO); return existingAppUser; } private async Task LoadAppUser(CentronWebService connection, string adminToken, AppUserDTO appUserDTO) { var request = new Request() { Ticket = adminToken }; var response = await connection.CallAsync(f => f.GetAllAppUsers(request)); Assert.Equal(StatusCode.Success, response.Status); Assert.NotNull(response.Result); return response.Result.FirstOrDefault(f => f.EmployeeI3D == appUserDTO.EmployeeI3D); } private async Task SaveAppUser(CentronWebService connection, string adminToken, AppUserDTO appUserDTO) { var request = IntegrationTestHelper.GetRequest(appUserDTO, adminToken); var response = await connection.CallAsync(f => f.SaveOrUpdateAppUser(request)); Assert.Equal(StatusCode.Success, response.Status); Assert.NotNull(response.Result?.First()); return response.Result!.First()!; } private async Task GetLoggedInEmployee(CentronWebService connection, string loginToken) { var request = new Request() { Ticket = loginToken }; var response = await connection.CallAsync(f => f.GetLoggedInUser(request)); Assert.Equal(StatusCode.Success, response.Status); Assert.NotNull(response.Result?.First()); var userEmployeePreview = response.Result!.First(); var userEmployeeData = await this.GetEmployeeByI3D(connection, loginToken, userEmployeePreview.I3D); Assert.NotNull(userEmployeeData); return userEmployeeData; } #endregion #region Get/Create RightsGroup private async Task GetOrCreateRightsGroup(CentronWebService connection, string adminToken) { var request = new Request() { Ticket = adminToken }; var response = await connection.CallAsync(f => f.GetAllRightGroups(request)); Assert.Equal(StatusCode.Success, response.Status); Assert.True(response.Result != null); var noRightsGroup = response.Result!.FirstOrDefault(f => string.Equals(f.Name, "NoRightsGroup")); if (noRightsGroup == null) { noRightsGroup = new AppGroupDTO() { Name = "NoRightsGroup" }; var createRequest = new Request() { Data = noRightsGroup, Ticket = adminToken }; var createResponse = await connection.CallAsync(f => f.SaveRightGroup(createRequest)); Assert.Equal(StatusCode.Success, createResponse.Status); Assert.NotNull(createResponse.Result?.First()); noRightsGroup = createResponse.Result.First(); } return noRightsGroup; } private async Task AddUserToRightsGroup(CentronWebService connection, string adminToken, int appUserI3D, int rightGroupI3D) { var updateRequest = new UpdateAppGroupAndUserDTO() { AppUserI3D = appUserI3D, AppGroupI3D = rightGroupI3D }; var request = new Request() { Data = updateRequest, Ticket = adminToken }; var removeResponse = await connection.CallAsync(f => f.RemoveUserFromRightGroup(request)); Assert.Equal(StatusCode.Success, removeResponse.Status); var addResponse = await connection.CallAsync(f => f.AddUserToRightGroup(request)); Assert.Equal(StatusCode.Success, addResponse.Status); } #endregion #region Test methods private async Task RequestOtherEmployeeDataWithAdministrativeRights(CentronWebService connection, string loginToken, EmployeeDTO referenceEmployeeData) { var otherEmployeePreview = await this.GetEmployeeInfoByI3D(connection, loginToken, referenceEmployeeData.I3D); Assert.NotNull(otherEmployeePreview); Assert.Equal(0, otherEmployeePreview.RemainingDaysOfVacation); // Currently not implemented by EmployeeToEmployeePreviewDTO, if that changes adjust the test Assert.Equal(0, otherEmployeePreview.VacationEntitlement); // Currently not implemented by EmployeeToEmployeePreviewDTO, if that changes adjust the test Assert.Null(otherEmployeePreview.LeavingDate); // Currently not implemented by EmployeeToEmployeePreviewDTO, if that changes adjust the test var otherEmployeeData = await this.GetEmployeeByI3D(connection, loginToken, referenceEmployeeData.I3D); Assert.NotNull(otherEmployeeData); this.AssertEmployeeDataEquals(otherEmployeeData, referenceEmployeeData); } private async Task RequestOwnEmployeeDataWithAdministrativeRights(CentronWebService connection, string loginToken, EmployeeDTO referenceEmployeeData) { var ownEmployeePreview = await this.GetEmployeeInfoByI3D(connection, loginToken, referenceEmployeeData.I3D); Assert.NotNull(ownEmployeePreview); var ownEmployeeData = await this.GetEmployeeByI3D(connection, loginToken, referenceEmployeeData.I3D); Assert.NotNull(ownEmployeeData); this.AssertEmployeeDataEquals(ownEmployeeData, referenceEmployeeData); } private async Task RequestOtherEmployeeDataWithoutAdministrativeRights(CentronWebService connection, string loginToken, EmployeeDTO referenceEmployee) { var testEmployeePreview = await this.GetEmployeeInfoByI3D(connection, loginToken, referenceEmployee.I3D); Assert.NotNull(testEmployeePreview); Assert.Equal(0, testEmployeePreview.RemainingDaysOfVacation); Assert.Equal(0, testEmployeePreview.VacationEntitlement); Assert.Null(testEmployeePreview.LeavingDate); // Sensible Data should now be replaced with placeholders. var testEmployee = await this.GetEmployeeByI3D(connection, loginToken, referenceEmployee.I3D); Assert.NotNull(testEmployee); Assert.Equal(0, testEmployee.RemainingDaysOfVacation); Assert.Equal(0, testEmployee.VacationEntitlement); Assert.Null(testEmployee.LeavingDate); Assert.Equal(string.Empty, testEmployee.Street); Assert.Equal(string.Empty, testEmployee.Zip); Assert.Equal(string.Empty, testEmployee.City); Assert.Equal(string.Empty, testEmployee.Phone3); Assert.Null(testEmployee.Birthday); Assert.Equal(decimal.Zero, testEmployee.Salary); Assert.Equal(string.Empty, testEmployee.LanguageSkills); Assert.Null(testEmployee.HoursForNextMonth); Assert.Null(testEmployee.TrialPeriod); Assert.Equal(int.MinValue, testEmployee.ContractPeriod); Assert.Equal(string.Empty, testEmployee.ContractKind); Assert.Null(testEmployee.CommencementDate); Assert.Equal(string.Empty, testEmployee.Comment); Assert.Equal(decimal.Zero, testEmployee.ManagementVariableField01); Assert.Equal(decimal.Zero, testEmployee.ManagementVariableField02); Assert.Equal(decimal.Zero, testEmployee.ManagementVariableField03); Assert.Equal(decimal.Zero, testEmployee.ManagementVariableField04); Assert.Equal(decimal.Zero, testEmployee.ManagementVariableField05); Assert.Equal(decimal.Zero, testEmployee.ManagementVariableField06); Assert.Equal(decimal.Zero, testEmployee.ManagementVariableField07); Assert.Equal(decimal.Zero, testEmployee.ManagementVariableField08); Assert.Equal(decimal.Zero, testEmployee.ManagementVariableField09); Assert.Equal(decimal.Zero, testEmployee.ManagementVariableField10); Assert.Null(testEmployee.SignatureAsPicture); Assert.Equal(string.Empty, testEmployee.Signature); } private async Task RequestOwnEmployeeDataWithoutAdministrativeRights(CentronWebService connection, string loginToken, EmployeeDTO referenceEmployeeData) { var ownEmployeePreview = await this.GetEmployeeInfoByI3D(connection, loginToken, referenceEmployeeData.I3D); Assert.NotNull(ownEmployeePreview); var ownEmployeeData = await this.GetEmployeeByI3D(connection, loginToken, referenceEmployeeData.I3D); Assert.NotNull(ownEmployeeData); this.AssertEmployeeDataEquals(ownEmployeeData, referenceEmployeeData); } private async Task GetEmployeeInfoByI3D(CentronWebService connection, string loginToken, int employeeI3D) { var request = IntegrationTestHelper.GetRequest(employeeI3D, loginToken); Expression>> execute = f => f.GetEmployeeInfoByI3D(request); var response = await connection.CallAsync(execute); if (response.Status != StatusCode.Success) throw new Exception($"Unable to get EmployeePreviewDTO: {response.Message}"); Assert.NotNull(response.Result?.FirstOrDefault()); return response.Result.First(); } private async Task GetEmployeeByI3D(CentronWebService connection, string loginToken, int employeeI3D) { var request = IntegrationTestHelper.GetRequest(employeeI3D, loginToken); Expression>> execute = f => f.GetEmployeeByI3D(request); var response = await connection.CallAsync(execute); if (response.Status != StatusCode.Success) throw new Exception($"Unable to get EmployeeDTO: {response.Message}"); Assert.NotNull(response.Result?.FirstOrDefault()); return response.Result.First(); } private void AssertEmployeeDataEquals(EmployeeDTO employee, EmployeeDTO reference) { Assert.Equal(reference.Street, employee.Street); Assert.Equal(reference.Zip, employee.Zip); Assert.Equal(reference.City, employee.City); Assert.Equal(reference.Phone3, employee.Phone3); Assert.Equal(reference.Birthday, employee.Birthday); Assert.Equal(reference.Salary, employee.Salary); Assert.Equal(reference.LanguageSkills, employee.LanguageSkills); Assert.Equal(reference.HoursForNextMonth, employee.HoursForNextMonth); Assert.Equal(reference.TrialPeriod, employee.TrialPeriod); Assert.Equal(reference.ContractPeriod, employee.ContractPeriod); Assert.Equal(reference.ContractKind, employee.ContractKind); Assert.Equal(reference.CommencementDate, employee.CommencementDate); Assert.Equal(reference.Comment, employee.Comment); Assert.Equal(reference.ManagementVariableField01, employee.ManagementVariableField01); Assert.Equal(reference.ManagementVariableField02, employee.ManagementVariableField02); Assert.Equal(reference.ManagementVariableField03, employee.ManagementVariableField03); Assert.Equal(reference.ManagementVariableField04, employee.ManagementVariableField04); Assert.Equal(reference.ManagementVariableField05, employee.ManagementVariableField05); Assert.Equal(reference.ManagementVariableField06, employee.ManagementVariableField06); Assert.Equal(reference.ManagementVariableField07, employee.ManagementVariableField07); Assert.Equal(reference.ManagementVariableField08, employee.ManagementVariableField08); Assert.Equal(reference.ManagementVariableField09, employee.ManagementVariableField09); Assert.Equal(reference.ManagementVariableField10, employee.ManagementVariableField10); Assert.Equal(reference.SignatureAsPicture, employee.SignatureAsPicture); Assert.Equal(reference.Signature, employee.Signature); } #endregion } }